Pyrogenesis HEAD
Pyrogenesis, a RTS Engine
code_annotation.h
Go to the documentation of this file.
1/* Copyright (c) 2021 Wildfire Games.
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining
4 * a copy of this software and associated documentation files (the
5 * "Software"), to deal in the Software without restriction, including
6 * without limitation the rights to use, copy, modify, merge, publish,
7 * distribute, sublicense, and/or sell copies of the Software, and to
8 * permit persons to whom the Software is furnished to do so, subject to
9 * the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23/*
24 * macros for code annotation.
25 */
26
27#ifndef INCLUDED_CODE_ANNOTATION
28#define INCLUDED_CODE_ANNOTATION
29
30#include "lib/sysdep/compiler.h"
31#include "lib/sysdep/arch.h" // ARCH_AMD64
32
33#include <cstddef>
34
35/**
36 * mark a function parameter as unused and avoid
37 * the corresponding compiler warning.
38 * wrap around the parameter name, e.g. void f(int UNUSED(x))
39 **/
40#define UNUSED(param)
41
42/**
43 * mark a function local variable or parameter as unused and avoid
44 * the corresponding compiler warning.
45 * note that UNUSED is not applicable to variable definitions that
46 * involve initialization, nor is it sufficient in cases where
47 * an argument is unused only in certain situations.
48 * example: void f(int x) { ASSERT(x == 0); UNUSED2(x); }
49 * this asserts in debug builds and avoids warnings in release.
50 **/
51#if HAVE_C99 && GCC_VERSION // _Pragma from C99, unused from GCC
52# define UNUSED2(param) _Pragma("unused " #param)
53#elif ICC_VERSION
54// ICC 12 still doesn't recognize pragma unused, casting to void
55// isn't sufficient, and self-assignment doesn't work for references.
56# define UNUSED2(param) do{ if(&param) {} } while(false)
57#else
58# define UNUSED2(param) ((void)(param))
59#endif
60
61/**
62 * Silence the 'unused result' warning.
63 * (void) would be sufficient but Spidermonkey still uses warn_unused_result,
64 * and GCC is stricter about that. See https://bugzilla.mozilla.org/show_bug.cgi?id=1571631.
65 **/
66template<typename T>
67inline void ignore_result(const T&) {}
68
69/**
70 * indicate a function will not throw any synchronous exceptions,
71 * thus hopefully generating smaller and more efficient code.
72 *
73 * must be placed BEFORE return types because "The [VC++] compiler
74 * ignores, without warning, any __declspec keywords placed after *".
75 * such syntax is apparently also legal in GCC, per the example
76 * "__attribute__((noreturn)) void d0 (void)".
77 *
78 * example:
79 * NOTHROW_DECLARE void function();
80 * NOTHROW_DEFINE void function() {}
81 **/
82#if GCC_VERSION
83# define NOTHROW_DECLARE __attribute__((nothrow))
84# define NOTHROW_DEFINE // not supported for definitions
85#elif CLANG_VERSION
86# define NOTHROW_DECLARE __attribute__((nothrow))
87# define NOTHROW_DEFINE // not supported for definitions
88#elif MSC_VERSION
89// Kevin Frei, 2006-03-23: "I work on the Visual C++ compiler team,
90// and agree completely with Paul Parks: don't use throw(), because
91// there's a chance that we'll eventually implement it according to the standard".
92# define NOTHROW_DECLARE __declspec(nothrow)
93# define NOTHROW_DEFINE __declspec(nothrow)
94#else
95// don't use throw() because it might result in ADDITIONAL checks
96// (the standard mandates calling unexpected())
97# define NOTHROW_DECLARE
98# define NOTHROW_DEFINE
99#endif
100
101
102/**
103 * mark a function as noreturn for static analyzer purposes.
104 * currently only for clang-analyzer.
105 */
106#if __has_feature(attribute_analyzer_noreturn)
107# define ANALYZER_NORETURN __attribute__((analyzer_noreturn))
108#else
109# define ANALYZER_NORETURN
110#endif
111
112
113/**
114 * "unreachable code" helpers
115 *
116 * unreachable lines of code are often the source or symptom of subtle bugs.
117 * they are flagged by compiler warnings; however, the opposite problem -
118 * erroneously reaching certain spots (e.g. due to missing return statement)
119 * is worse and not detected automatically.
120 *
121 * to defend against this, the programmer can annotate their code to
122 * indicate to humans that a particular spot should never be reached.
123 * however, that isn't much help; better is a sentinel that raises an
124 * error if if it is actually reached. hence, the UNREACHABLE macro.
125 *
126 * ironically, if the code guarded by UNREACHABLE works as it should,
127 * compilers may flag the macro's code as unreachable. this would
128 * distract from genuine warnings, which is unacceptable.
129 *
130 * even worse, compilers differ in their code checking: GCC only complains if
131 * non-void functions end without returning a value (i.e. missing return
132 * statement), while VC checks if lines are unreachable (e.g. if they are
133 * preceded by a return on all paths).
134 *
135 * the implementation below enables optimization and automated checking
136 * without raising warnings.
137 **/
138#define UNREACHABLE // actually defined below.. this is for
139# undef UNREACHABLE // CppDoc's benefit only.
140
141// this macro should not generate any fallback code; it is merely the
142// compiler-specific backend for UNREACHABLE.
143// #define it to nothing if the compiler doesn't support such a hint.
144#define HAVE_ASSUME_UNREACHABLE 1
145#if MSC_VERSION && !ICC_VERSION // (ICC ignores this)
146# define ASSUME_UNREACHABLE __assume(0)
147#elif GCC_VERSION
148# define ASSUME_UNREACHABLE __builtin_unreachable()
149#else
150# define ASSUME_UNREACHABLE
151# undef HAVE_ASSUME_UNREACHABLE
152# define HAVE_ASSUME_UNREACHABLE 0
153#endif
154
155// compiler supports ASSUME_UNREACHABLE => allow it to assume the code is
156// never reached (improves optimization at the cost of undefined behavior
157// if the annotation turns out to be incorrect).
158#if HAVE_ASSUME_UNREACHABLE && !CONFIG_ENABLE_CHECKS
159# define UNREACHABLE ASSUME_UNREACHABLE
160// otherwise (or if CONFIG_ENABLE_CHECKS is set), add a user-visible
161// warning if the code is reached. note that abort() fails to stop
162// ICC from warning about the lack of a return statement, so we
163// use an infinite loop instead.
164#else
165# define UNREACHABLE\
166 STMT(\
167 DEBUG_WARN_ERR(ERR::LOGIC); /* hit supposedly unreachable code */\
168 for(;;){};\
169 )
170#endif
171
172/**
173convenient specialization of UNREACHABLE for switch statements whose
174default can never be reached. example usage:
175int x;
176switch(x % 2)
177{
178 case 0: break;
179 case 1: break;
180 NODEFAULT;
181}
182**/
183#define NODEFAULT default: UNREACHABLE
184
185
186// generate a symbol containing the line number of the macro invocation.
187// used to give a unique name (per file) to types or variables.
188// we can't prepend __FILE__ to make it globally unique - the filename
189// may be enclosed in quotes. PASTE3_HIDDEN__ is needed to make sure
190// __LINE__ is expanded correctly.
191#define PASTE3_HIDDEN__(a, b, c) a ## b ## c
192#define PASTE3__(a, b, c) PASTE3_HIDDEN__(a, b, c)
193#define UID__ PASTE3__(LINE_, __LINE__, _)
194#define UID2__ PASTE3__(LINE_, __LINE__, _2)
195
196
197//-----------------------------------------------------------------------------
198// cassert
199
200/**
201 * Compile-time assertion. Causes a compile error if the expression
202 * evaluates to zero/false.
203 *
204 * No runtime overhead; may be used anywhere, including file scope.
205 * Especially useful for testing sizeof types.
206 *
207 * @param expr Expression that is expected to evaluate to non-zero at compile-time.
208 **/
209#define cassert(expr) static_assert((expr), #expr)
210
211
212/**
213 * Indicates that a class is noncopyable (usually due to const or reference
214 * members, or because the class works as a singleton).
215 *
216 * For example:
217 *
218 * @code
219 * class ClassName {
220 * NONCOPYABLE(ClassName);
221 * public: // etc.
222 * };
223 * @endcode
224 *
225 * This is preferable to inheritance from boost::noncopyable because it avoids
226 * ICC 11 W4 warnings about non-virtual dtors and suppression of the copy
227 * assignment operator.
228 */
229#define NONCOPYABLE(className) \
230 className(const className&) = delete; \
231 className& operator=(const className&) = delete
232
233/**
234 * Indicates that move semantics can be used, so that a NONCOPYABLE class can still be assigned by taking over the reference to the value.
235 * Make sure to use the macro with the necessary access modifier.
236 */
237#define MOVABLE(className) \
238 className(className&&) = default; \
239 className& operator=(className&&) = default
240
241#if ICC_VERSION
242# define ASSUME_ALIGNED(ptr, multiple) __assume_aligned(ptr, multiple)
243#else
244# define ASSUME_ALIGNED(ptr, multiple)
245#endif
246
247// annotate printf-style functions for compile-time type checking.
248// fmtpos is the index of the format argument, counting from 1 or
249// (if it's a non-static class function) 2; the '...' is assumed
250// to come directly after it.
251#if GCC_VERSION
252# define PRINTF_ARGS(fmtpos) __attribute__ ((format (printf, fmtpos, fmtpos+1)))
253# define VPRINTF_ARGS(fmtpos) __attribute__ ((format (printf, fmtpos, 0)))
254# define WPRINTF_ARGS(fmtpos) /* not currently supported in GCC */
255# define VWPRINTF_ARGS(fmtpos) /* not currently supported in GCC */
256#else
257# define PRINTF_ARGS(fmtpos)
258# define VPRINTF_ARGS(fmtpos)
259# define WPRINTF_ARGS(fmtpos)
260# define VWPRINTF_ARGS(fmtpos)
261// TODO: support _Printf_format_string_ for VC9+
262#endif
263
264// annotate vararg functions that expect to end with an explicit NULL
265#if GCC_VERSION
266# define SENTINEL_ARG __attribute__ ((sentinel))
267#else
268# define SENTINEL_ARG
269#endif
270
271/**
272 * prevent the compiler from reordering loads or stores across this point.
273 **/
274#if ICC_VERSION
275# define COMPILER_FENCE __memory_barrier()
276#elif MSC_VERSION
277# include <intrin.h>
278# pragma intrinsic(_ReadWriteBarrier)
279# define COMPILER_FENCE _ReadWriteBarrier()
280#elif GCC_VERSION
281# define COMPILER_FENCE asm volatile("" : : : "memory")
282#else
283# define COMPILER_FENCE
284#endif
285
286
287// try to define _W64, if not already done
288// (this is useful for catching pointer size bugs)
289#ifndef _W64
290# if MSC_VERSION
291# define _W64 __w64
292# elif GCC_VERSION
293# define _W64 __attribute__((mode (__pointer__)))
294# else
295# define _W64
296# endif
297#endif
298
299
300// C99-like restrict (non-standard in C++, but widely supported in various forms).
301//
302// May be used on pointers. May also be used on member functions to indicate
303// that 'this' is unaliased (e.g. "void C::m() RESTRICT { ... }").
304// Must not be used on references - GCC supports that but VC doesn't.
305//
306// We call this "RESTRICT" to avoid conflicts with VC's __declspec(restrict),
307// and because it's not really the same as C99's restrict.
308//
309// To be safe and satisfy the compilers' stated requirements: an object accessed
310// by a restricted pointer must not be accessed by any other pointer within the
311// lifetime of the restricted pointer, if the object is modified.
312// To maximise the chance of optimisation, any pointers that could potentially
313// alias with the restricted one should be marked as restricted too.
314//
315// It would probably be a good idea to write test cases for any code that uses
316// this in an even very slightly unclear way, in case it causes obscure problems
317// in a rare compiler due to differing semantics.
318//
319// .. GCC
320#if GCC_VERSION
321# define RESTRICT __restrict__
322// .. VC8 provides __restrict
323#elif MSC_VERSION
324# define RESTRICT __restrict
325// .. ICC supports the keyword 'restrict' when run with the /Qrestrict option,
326// but it always also supports __restrict__ or __restrict to be compatible
327// with GCC/MSVC, so we'll use the underscored version. One of {GCC,MSC}_VERSION
328// should have been defined in addition to ICC_VERSION, so we should be using
329// one of the above cases (unless it's an old VS7.1-emulating ICC).
330#elif ICC_VERSION
331# error ICC_VERSION defined without either GCC_VERSION or an adequate MSC_VERSION
332// .. unsupported; remove it from code
333#else
334# define RESTRICT
335#endif
336
337
338//
339// number of array elements
340//
341
342// (function taking a reference to an array and returning a pointer to
343// an array of characters. it's only declared and never defined; we just
344// need it to determine n, the size of the array that was passed.)
345template<typename T, size_t n> char (*ArraySizeDeducer(T (&)[n]))[n];
346
347// (although requiring C++, this method is much better than the standard
348// sizeof(name) / sizeof(name[0]) because it doesn't compile when a
349// pointer is passed, which can easily happen under maintenance.)
350#define ARRAY_SIZE(name) (sizeof(*ArraySizeDeducer(name)))
351
352
353// C99-style __func__
354// .. newer GCC already have it
355#if GCC_VERSION
356// nothing need be done
357// .. MSVC have __FUNCTION__
358#elif MSC_VERSION
359# define __func__ __FUNCTION__
360// .. unsupported
361#else
362# define __func__ "(unknown)"
363#endif
364
365
366// extern "C", but does the right thing in pure-C mode
367#if defined(__cplusplus)
368# define EXTERN_C extern "C"
369#else
370# define EXTERN_C extern
371#endif
372
373
374#if MSC_VERSION
375# define INLINE __forceinline
376#else
377# define INLINE inline
378#endif
379
380
381#if MSC_VERSION
382# define CALL_CONV __cdecl
383#else
384# define CALL_CONV
385#endif
386
387
388#if MSC_VERSION && !ARCH_AMD64
389# define DECORATED_NAME(name) _##name
390#else
391# define DECORATED_NAME(name) name
392#endif
393
394
395// workaround for preprocessor limitation: macro args aren't expanded
396// before being pasted.
397#define STRINGIZE2(id) # id
398#define STRINGIZE(id) STRINGIZE2(id)
399
400// for widening non-literals (e.g. __FILE__)
401// note: C99 says __func__ is a magic *variable*, and GCC doesn't allow
402// widening it via preprocessor.
403#define WIDEN2(x) L ## x
404#define WIDEN(x) WIDEN2(x)
405
406// TODO: Replace this with [[fallthrough]] once we support C++17
407#if __has_cpp_attribute(fallthrough) || defined(__cplusplus) && __cplusplus >= 201703L
408# define FALLTHROUGH [[fallthrough]]
409#elif __has_cpp_attribute(gnu::fallthrough)
410# define FALLTHROUGH [[gnu::fallthrough]]
411#elif __has_cpp_attribute(clang::fallthrough)
412# define FALLTHROUGH [[clang::fallthrough]]
413#else
414# define FALLTHROUGH
415// TODO: Maybe use __fallthrough for the MSVC code analyzer (also figure out if we need to add some switch when switching to a newer version of VS that supports [[fallthrough]]
416#endif
417
418#endif // #ifndef INCLUDED_CODE_ANNOTATION
char(* ArraySizeDeducer(T(&)[n]))[n]
void ignore_result(const T &)
Silence the 'unused result' warning.
Definition: code_annotation.h:67
#define T(string_literal)
Definition: secure_crt.cpp:77