Pyrogenesis HEAD
Pyrogenesis, a RTS Engine
code_annotation.h File Reference
#include "lib/sysdep/compiler.h"
#include "lib/sysdep/arch.h"
#include <cstddef>
Include dependency graph for code_annotation.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define UNUSED(param)
 mark a function parameter as unused and avoid the corresponding compiler warning. More...
 
#define UNUSED2(param)   ((void)(param))
 mark a function local variable or parameter as unused and avoid the corresponding compiler warning. More...
 
#define NOTHROW_DECLARE
 indicate a function will not throw any synchronous exceptions, thus hopefully generating smaller and more efficient code. More...
 
#define NOTHROW_DEFINE
 
#define ANALYZER_NORETURN
 mark a function as noreturn for static analyzer purposes. More...
 
#define UNREACHABLE
 "unreachable code" helpers More...
 
#define HAVE_ASSUME_UNREACHABLE   1
 
#define ASSUME_UNREACHABLE
 
#define HAVE_ASSUME_UNREACHABLE   0
 
#define UNREACHABLE
 "unreachable code" helpers More...
 
#define NODEFAULT   default: UNREACHABLE
 convenient specialization of UNREACHABLE for switch statements whose default can never be reached. More...
 
#define PASTE3_HIDDEN__(a, b, c)   a ## b ## c
 
#define PASTE3__(a, b, c)   PASTE3_HIDDEN__(a, b, c)
 
#define UID__   PASTE3__(LINE_, __LINE__, _)
 
#define UID2__   PASTE3__(LINE_, __LINE__, _2)
 
#define cassert(expr)   static_assert((expr), #expr)
 Compile-time assertion. More...
 
#define NONCOPYABLE(className)
 Indicates that a class is noncopyable (usually due to const or reference members, or because the class works as a singleton). More...
 
#define MOVABLE(className)
 Indicates that move semantics can be used, so that a NONCOPYABLE class can still be assigned by taking over the reference to the value. More...
 
#define ASSUME_ALIGNED(ptr, multiple)
 
#define PRINTF_ARGS(fmtpos)
 
#define VPRINTF_ARGS(fmtpos)
 
#define WPRINTF_ARGS(fmtpos)
 
#define VWPRINTF_ARGS(fmtpos)
 
#define SENTINEL_ARG
 
#define COMPILER_FENCE
 prevent the compiler from reordering loads or stores across this point. More...
 
#define _W64
 
#define RESTRICT
 
#define ARRAY_SIZE(name)   (sizeof(*ArraySizeDeducer(name)))
 
#define __func__   "(unknown)"
 
#define EXTERN_C   extern
 
#define INLINE   inline
 
#define CALL_CONV
 
#define DECORATED_NAME(name)   name
 
#define STRINGIZE2(id)   # id
 
#define STRINGIZE(id)   STRINGIZE2(id)
 
#define WIDEN2(x)   L ## x
 
#define WIDEN(x)   WIDEN2(x)
 
#define FALLTHROUGH
 

Functions

template<typename T >
void ignore_result (const T &)
 Silence the 'unused result' warning. More...
 
template<typename T , size_t n>
char(* ArraySizeDeducer (T(&)[n]))[n]
 

Macro Definition Documentation

◆ __func__

#define __func__   "(unknown)"

◆ _W64

#define _W64

◆ ANALYZER_NORETURN

#define ANALYZER_NORETURN

mark a function as noreturn for static analyzer purposes.

currently only for clang-analyzer.

◆ ARRAY_SIZE

#define ARRAY_SIZE (   name)    (sizeof(*ArraySizeDeducer(name)))

◆ ASSUME_ALIGNED

#define ASSUME_ALIGNED (   ptr,
  multiple 
)

◆ ASSUME_UNREACHABLE

#define ASSUME_UNREACHABLE

◆ CALL_CONV

#define CALL_CONV

◆ cassert

#define cassert (   expr)    static_assert((expr), #expr)

Compile-time assertion.

Causes a compile error if the expression evaluates to zero/false.

No runtime overhead; may be used anywhere, including file scope. Especially useful for testing sizeof types.

Parameters
exprExpression that is expected to evaluate to non-zero at compile-time.

◆ COMPILER_FENCE

#define COMPILER_FENCE

prevent the compiler from reordering loads or stores across this point.

◆ DECORATED_NAME

#define DECORATED_NAME (   name)    name

◆ EXTERN_C

#define EXTERN_C   extern

◆ FALLTHROUGH

#define FALLTHROUGH

◆ HAVE_ASSUME_UNREACHABLE [1/2]

#define HAVE_ASSUME_UNREACHABLE   1

◆ HAVE_ASSUME_UNREACHABLE [2/2]

#define HAVE_ASSUME_UNREACHABLE   0

◆ INLINE

#define INLINE   inline

◆ MOVABLE

#define MOVABLE (   className)
Value:
className(className&&) = default; \
className& operator=(className&&) = default

Indicates that move semantics can be used, so that a NONCOPYABLE class can still be assigned by taking over the reference to the value.

Make sure to use the macro with the necessary access modifier.

◆ NODEFAULT

#define NODEFAULT   default: UNREACHABLE

convenient specialization of UNREACHABLE for switch statements whose default can never be reached.

example usage: int x; switch(x % 2) { case 0: break; case 1: break; NODEFAULT; }

◆ NONCOPYABLE

#define NONCOPYABLE (   className)
Value:
className(const className&) = delete; \
className& operator=(const className&) = delete

Indicates that a class is noncopyable (usually due to const or reference members, or because the class works as a singleton).

For example:

class ClassName {
NONCOPYABLE(ClassName);
public: // etc.
};
#define NONCOPYABLE(className)
Indicates that a class is noncopyable (usually due to const or reference members, or because the clas...
Definition: code_annotation.h:229

This is preferable to inheritance from boost::noncopyable because it avoids ICC 11 W4 warnings about non-virtual dtors and suppression of the copy assignment operator.

◆ NOTHROW_DECLARE

#define NOTHROW_DECLARE

indicate a function will not throw any synchronous exceptions, thus hopefully generating smaller and more efficient code.

must be placed BEFORE return types because "The [VC++] compiler ignores, without warning, any __declspec keywords placed after *". such syntax is apparently also legal in GCC, per the example "__attribute__((noreturn)) void d0 (void)".

example: NOTHROW_DECLARE void function(); NOTHROW_DEFINE void function() {}

◆ NOTHROW_DEFINE

#define NOTHROW_DEFINE

◆ PASTE3__

#define PASTE3__ (   a,
  b,
 
)    PASTE3_HIDDEN__(a, b, c)

◆ PASTE3_HIDDEN__

#define PASTE3_HIDDEN__ (   a,
  b,
 
)    a ## b ## c

◆ PRINTF_ARGS

#define PRINTF_ARGS (   fmtpos)

◆ RESTRICT

#define RESTRICT

◆ SENTINEL_ARG

#define SENTINEL_ARG

◆ STRINGIZE

#define STRINGIZE (   id)    STRINGIZE2(id)

◆ STRINGIZE2

#define STRINGIZE2 (   id)    # id

◆ UID2__

#define UID2__   PASTE3__(LINE_, __LINE__, _2)

◆ UID__

#define UID__   PASTE3__(LINE_, __LINE__, _)

◆ UNREACHABLE [1/2]

#define UNREACHABLE

"unreachable code" helpers

unreachable lines of code are often the source or symptom of subtle bugs. they are flagged by compiler warnings; however, the opposite problem - erroneously reaching certain spots (e.g. due to missing return statement) is worse and not detected automatically.

to defend against this, the programmer can annotate their code to indicate to humans that a particular spot should never be reached. however, that isn't much help; better is a sentinel that raises an error if if it is actually reached. hence, the UNREACHABLE macro.

ironically, if the code guarded by UNREACHABLE works as it should, compilers may flag the macro's code as unreachable. this would distract from genuine warnings, which is unacceptable.

even worse, compilers differ in their code checking: GCC only complains if non-void functions end without returning a value (i.e. missing return statement), while VC checks if lines are unreachable (e.g. if they are preceded by a return on all paths).

the implementation below enables optimization and automated checking without raising warnings.

◆ UNREACHABLE [2/2]

#define UNREACHABLE
Value:
STMT(\
DEBUG_WARN_ERR(ERR::LOGIC); /* hit supposedly unreachable code */\
for(;;){};\
)
#define STMT(STMT_code__)
package code into a single statement.
Definition: code_generation.h:41
#define DEBUG_WARN_ERR(status)
display the error dialog with text corresponding to the given error code.
Definition: debug.h:326
const Status LOGIC
Definition: status.h:411

"unreachable code" helpers

unreachable lines of code are often the source or symptom of subtle bugs. they are flagged by compiler warnings; however, the opposite problem - erroneously reaching certain spots (e.g. due to missing return statement) is worse and not detected automatically.

to defend against this, the programmer can annotate their code to indicate to humans that a particular spot should never be reached. however, that isn't much help; better is a sentinel that raises an error if if it is actually reached. hence, the UNREACHABLE macro.

ironically, if the code guarded by UNREACHABLE works as it should, compilers may flag the macro's code as unreachable. this would distract from genuine warnings, which is unacceptable.

even worse, compilers differ in their code checking: GCC only complains if non-void functions end without returning a value (i.e. missing return statement), while VC checks if lines are unreachable (e.g. if they are preceded by a return on all paths).

the implementation below enables optimization and automated checking without raising warnings.

◆ UNUSED

#define UNUSED (   param)

mark a function parameter as unused and avoid the corresponding compiler warning.

wrap around the parameter name, e.g. void f(int UNUSED(x))

◆ UNUSED2

#define UNUSED2 (   param)    ((void)(param))

mark a function local variable or parameter as unused and avoid the corresponding compiler warning.

note that UNUSED is not applicable to variable definitions that involve initialization, nor is it sufficient in cases where an argument is unused only in certain situations. example: void f(int x) { ASSERT(x == 0); UNUSED2(x); } this asserts in debug builds and avoids warnings in release.

◆ VPRINTF_ARGS

#define VPRINTF_ARGS (   fmtpos)

◆ VWPRINTF_ARGS

#define VWPRINTF_ARGS (   fmtpos)

◆ WIDEN

#define WIDEN (   x)    WIDEN2(x)

◆ WIDEN2

#define WIDEN2 (   x)    L ## x

◆ WPRINTF_ARGS

#define WPRINTF_ARGS (   fmtpos)

Function Documentation

◆ ArraySizeDeducer()

template<typename T , size_t n>
char(* ArraySizeDeducer ( T(&)  [n]) )[n]

◆ ignore_result()

template<typename T >
void ignore_result ( const T )
inline

Silence the 'unused result' warning.

(void) would be sufficient but Spidermonkey still uses warn_unused_result, and GCC is stricter about that. See https://bugzilla.mozilla.org/show_bug.cgi?id=1571631.