1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3  * This file is part of openfx-supportext <https://github.com/devernay/openfx-supportext>,
4  * Copyright (C) 2013-2018 INRIA
5  *
6  * openfx-supportext is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * openfx-supportext is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with openfx-supportext.  If not, see <http://www.gnu.org/licenses/gpl-2.0.html>
18  * ***** END LICENSE BLOCK ***** */
19 
20 /*
21  * Useful macros.
22  */
23 
24 #ifndef openfx_supportext_ofxsMacros_h
25 #define openfx_supportext_ofxsMacros_h
26 
27 /* *INDENT-OFF* */
28 
29 #define OFXS_NAMESPACE_OFX_ENTER namespace OFX {
30 #define OFXS_NAMESPACE_OFX_EXIT }
31 
32 // anonymous namespace macros, mainly to avoid crazy intentation by some IDEs (e.g. Xcode)
33 #define OFXS_NAMESPACE_ANONYMOUS_ENTER namespace {
34 #define OFXS_NAMESPACE_ANONYMOUS_EXIT }
35 
36 // compiler_warning.h
37 #define STRINGISE_IMPL(x) # x
38 #define STRINGISE(x) STRINGISE_IMPL(x)
39 
40 // Use: #pragma message WARN("My message")
41 #if _MSC_VER
42 #   define FILE_LINE_LINK __FILE__ "(" STRINGISE(__LINE__) ") : "
43 #   define WARN(exp) (FILE_LINE_LINK "WARNING: " exp)
44 #else //__GNUC__ - may need other defines for different compilers
45 #   define WARN(exp) ("WARNING: " exp)
46 #endif
47 
48 // The following was grabbed from WTF/wtf/Compiler.h (where WTF was replaced by OFXS)
49 
50 /* COMPILER() - the compiler being used to build the project */
51 #define COMPILER(OFXS_FEATURE) (defined OFXS_COMPILER_ ## OFXS_FEATURE && OFXS_COMPILER_ ## OFXS_FEATURE)
52 
53 /* COMPILER_SUPPORTS() - whether the compiler being used to build the project supports the given feature. */
54 #define COMPILER_SUPPORTS(OFXS_COMPILER_FEATURE) (defined OFXS_COMPILER_SUPPORTS_ ## OFXS_COMPILER_FEATURE && OFXS_COMPILER_SUPPORTS_ ## OFXS_COMPILER_FEATURE)
55 
56 /* COMPILER_QUIRK() - whether the compiler being used to build the project requires a given quirk. */
57 #define COMPILER_QUIRK(OFXS_COMPILER_QUIRK) (defined OFXS_COMPILER_QUIRK_ ## OFXS_COMPILER_QUIRK && OFXS_COMPILER_QUIRK_ ## OFXS_COMPILER_QUIRK)
58 
59 /* ==== COMPILER() - the compiler being used to build the project ==== */
60 
61 /* COMPILER(CLANG) - Clang */
62 #if defined(__clang__)
63 #define OFXS_COMPILER_CLANG 1
64 
65 #ifndef __has_extension
66 #define __has_extension __has_feature /* Compatibility with older versions of clang */
67 #endif
68 
69 #define CLANG_PRAGMA(PRAGMA) _Pragma(PRAGMA)
70 
71 /* Specific compiler features */
72 #define OFXS_COMPILER_SUPPORTS_CXX_VARIADIC_TEMPLATES __has_extension(cxx_variadic_templates)
73 
74 /* There is a bug in clang that comes with Xcode 4.2 where AtomicStrings can't be implicitly converted to Strings
75    in the presence of move constructors and/or move assignment operators. This bug has been fixed in Xcode 4.3 clang, so we
76    check for both cxx_rvalue_references as well as the unrelated cxx_nonstatic_member_init feature which we know was added in 4.3 */
77 #define OFXS_COMPILER_SUPPORTS_CXX_RVALUE_REFERENCES __has_extension(cxx_rvalue_references) && __has_extension(cxx_nonstatic_member_init)
78 
79 #define OFXS_COMPILER_SUPPORTS_CXX_DELETED_FUNCTIONS __has_extension(cxx_deleted_functions)
80 #define OFXS_SUPPORTS_CXX_NULLPTR __has_feature(cxx_nullptr)
81 #define OFXS_COMPILER_SUPPORTS_CXX_EXPLICIT_CONVERSIONS __has_feature(cxx_explicit_conversions)
82 #define OFXS_COMPILER_SUPPORTS_BLOCKS __has_feature(blocks)
83 #define OFXS_COMPILER_SUPPORTS_C_STATIC_ASSERT __has_extension(c_static_assert)
84 #define OFXS_COMPILER_SUPPORTS_CXX_OVERRIDE_CONTROL __has_extension(cxx_override_control)
85 #define OFXS_COMPILER_SUPPORTS_HAS_TRIVIAL_DESTRUCTOR __has_extension(has_trivial_destructor)
86 
87 #endif
88 
89 #ifndef CLANG_PRAGMA
90 #define CLANG_PRAGMA(PRAGMA)
91 #endif
92 
93 /* COMPILER(MSVC) - Microsoft Visual C++ */
94 /* COMPILER(MSVC7_OR_LOWER) - Microsoft Visual C++ 2003 or lower*/
95 /* COMPILER(MSVC9_OR_LOWER) - Microsoft Visual C++ 2008 or lower*/
96 #if defined(_MSC_VER)
97 #define OFXS_COMPILER_MSVC 1
98 #if _MSC_VER < 1400
99 #define OFXS_COMPILER_MSVC7_OR_LOWER 1
100 #elif _MSC_VER < 1600
101 #define OFXS_COMPILER_MSVC9_OR_LOWER 1
102 #endif
103 
104 /* Specific compiler features */
105 #if !COMPILER(CLANG) && _MSC_VER >= 1600
106 #define OFXS_SUPPORTS_CXX_NULLPTR 1
107 #endif
108 
109 #if !COMPILER(CLANG)
110 #define OFXS_COMPILER_SUPPORTS_CXX_OVERRIDE_CONTROL 1
111 #define OFXS_COMPILER_QUIRK_FINAL_IS_CALLED_SEALED 1
112 #endif
113 
114 #endif
115 
116 /* COMPILER(RVCT) - ARM RealView Compilation Tools */
117 /* COMPILER(RVCT4_OR_GREATER) - ARM RealView Compilation Tools 4.0 or greater */
118 #if defined(__CC_ARM) || defined(__ARMCC__)
119 #define OFXS_COMPILER_RVCT 1
120 #define RVCT_VERSION_AT_LEAST(major, minor, patch, build) ( __ARMCC_VERSION >= (major * 100000 + minor * 10000 + patch * 1000 + build) )
121 #else
122 /* Define this for !RVCT compilers, just so we can write things like RVCT_VERSION_AT_LEAST(3, 0, 0, 0). */
123 #define RVCT_VERSION_AT_LEAST(major, minor, patch, build) 0
124 #endif
125 
126 /* COMPILER(GCCE) - GNU Compiler Collection for Embedded */
127 #if defined(__GCCE__)
128 #define OFXS_COMPILER_GCCE 1
129 #define GCCE_VERSION (__GCCE__ * 10000 + __GCCE_MINOR__ * 100 + __GCCE_PATCHLEVEL__)
130 #define GCCE_VERSION_AT_LEAST(major, minor, patch) ( GCCE_VERSION >= (major * 10000 + minor * 100 + patch) )
131 #endif
132 
133 /* COMPILER(GCC) - GNU Compiler Collection */
134 /* --gnu option of the RVCT compiler also defines __GNUC__ */
135 #if defined(__GNUC__) && !COMPILER(RVCT)
136 #define OFXS_COMPILER_GCC 1
137 #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
138 #define GCC_VERSION_AT_LEAST(major, minor, patch) ( GCC_VERSION >= (major * 10000 + minor * 100 + patch) )
139 #else
140 /* Define this for !GCC compilers, just so we can write things like GCC_VERSION_AT_LEAST(4, 1, 0). */
141 #define GCC_VERSION_AT_LEAST(major, minor, patch) 0
142 #endif
143 
144 /* Specific compiler features */
145 #if COMPILER(GCC) && !COMPILER(CLANG)
146 #if GCC_VERSION_AT_LEAST(4, 7, 0) && defined(__cplusplus) && __cplusplus >= 201103L
147 #define OFXS_COMPILER_SUPPORTS_CXX_RVALUE_REFERENCES 1
148 #define OFXS_COMPILER_SUPPORTS_CXX_DELETED_FUNCTIONS 1
149 #define OFXS_SUPPORTS_CXX_NULLPTR 1
150 #define OFXS_COMPILER_SUPPORTS_CXX_OVERRIDE_CONTROL 1
151 #define OFXS_COMPILER_QUIRK_GCC11_GLOBAL_ISINF_ISNAN 1
152 
153 #elif GCC_VERSION_AT_LEAST(4, 6, 0) && defined(__GXX_EXPERIMENTAL_CXX0X__)
154 #define OFXS_SUPPORTS_CXX_NULLPTR 1
155 #define OFXS_COMPILER_QUIRK_GCC11_GLOBAL_ISINF_ISNAN 1
156 #endif
157 
158 #endif
159 
160 /* COMPILER(MINGW) - MinGW GCC */
161 /* COMPILER(MINGW64) - mingw-w64 GCC - only used as additional check to exclude mingw.org specific functions */
162 #if defined(__MINGW32__)
163 #define OFXS_COMPILER_MINGW 1
164 #include <_mingw.h> /* private MinGW header */
165 #if defined(__MINGW64_VERSION_MAJOR) /* best way to check for mingw-w64 vs mingw.org */
166 #define OFXS_COMPILER_MINGW64 1
167 #endif /* __MINGW64_VERSION_MAJOR */
168 #endif /* __MINGW32__ */
169 
170 /* COMPILER(INTEL) - Intel C++ Compiler */
171 #if defined(__INTEL_COMPILER)
172 #define OFXS_COMPILER_INTEL 1
173 #endif
174 
175 /* COMPILER(SUNCC) */
176 #if defined(__SUNPRO_CC) || defined(__SUNPRO_C)
177 #define OFXS_COMPILER_SUNCC 1
178 #endif
179 
180 /* ==== Compiler features ==== */
181 
182 
183 /* ALWAYS_INLINE */
184 
185 #ifndef ALWAYS_INLINE
186 #if COMPILER(GCC) && defined(NDEBUG) && !COMPILER(MINGW)
187 #define ALWAYS_INLINE inline __attribute__( (__always_inline__) )
188 #elif (COMPILER(MSVC) || COMPILER(RVCT ) ) && defined(NDEBUG)
189 #define ALWAYS_INLINE __forceinline
190 #else
191 #define ALWAYS_INLINE inline
192 #endif
193 #endif
194 
195 
196 /* NEVER_INLINE */
197 
198 #ifndef NEVER_INLINE
199 #if COMPILER(GCC)
200 #define NEVER_INLINE __attribute__( (__noinline__) )
201 #elif COMPILER(RVCT)
202 #define NEVER_INLINE __declspec(noinline)
203 #else
204 #define NEVER_INLINE
205 #endif
206 #endif
207 
208 
209 /* UNLIKELY */
210 
211 #ifndef UNLIKELY
212 #if COMPILER(GCC) || (RVCT_VERSION_AT_LEAST(3, 0, 0, 0) && defined(__GNUC__ ) )
213 #define UNLIKELY(x) __builtin_expect( (x), 0 )
214 #else
215 #define UNLIKELY(x) (x)
216 #endif
217 #endif
218 
219 
220 /* LIKELY */
221 
222 #ifndef LIKELY
223 #if COMPILER(GCC) || (RVCT_VERSION_AT_LEAST(3, 0, 0, 0) && defined(__GNUC__ ) )
224 #define LIKELY(x) __builtin_expect( (x), 1 )
225 #else
226 #define LIKELY(x) (x)
227 #endif
228 #endif
229 
230 
231 /* NO_RETURN */
232 
233 
234 #ifndef NO_RETURN
235 #if COMPILER(GCC)
236 #define NO_RETURN __attribute( (__noreturn__) )
237 #elif COMPILER(MSVC) || COMPILER(RVCT)
238 #define NO_RETURN __declspec(noreturn)
239 #else
240 #define NO_RETURN
241 #endif
242 #endif
243 
244 
245 /* NO_RETURN_WITH_VALUE */
246 
247 #ifndef NO_RETURN_WITH_VALUE
248 #if !COMPILER(MSVC)
249 #define NO_RETURN_WITH_VALUE NO_RETURN
250 #else
251 #define NO_RETURN_WITH_VALUE
252 #endif
253 #endif
254 
255 
256 /* WARN_UNUSED_RETURN */
257 
258 #if COMPILER(GCC)
259 #define WARN_UNUSED_RETURN __attribute__ ( (warn_unused_result) )
260 #else
261 #define WARN_UNUSED_RETURN
262 #endif
263 
264 /* OVERRIDE and FINAL */
265 
266 #if COMPILER_SUPPORTS(CXX_OVERRIDE_CONTROL) &&  !COMPILER(MSVC) //< patch so msvc 2010 ignores the override and final keywords.
267 #define OVERRIDE override
268 
269 #if COMPILER_QUIRK(FINAL_IS_CALLED_SEALED)
270 #define FINAL sealed
271 #else
272 #define FINAL final
273 #endif
274 
275 #else
276 #define OVERRIDE
277 #define FINAL
278 #endif
279 
280 /* REFERENCED_FROM_ASM */
281 
282 #ifndef REFERENCED_FROM_ASM
283 #if COMPILER(GCC)
284 #define REFERENCED_FROM_ASM __attribute__( (used) )
285 #else
286 #define REFERENCED_FROM_ASM
287 #endif
288 #endif
289 
290 /* OBJC_CLASS */
291 
292 #ifndef OBJC_CLASS
293 #ifdef __OBJC__
294 #define OBJC_CLASS @class
295 #else
296 #define OBJC_CLASS class
297 #endif
298 #endif
299 
300 /* ABI */
301 #if defined(__ARM_EABI__) || defined(__EABI__)
302 #define OFXS_COMPILER_SUPPORTS_EABI 1
303 #endif
304 
305 // Warning control from https://svn.boost.org/trac/boost/wiki/Guidelines/WarningsGuidelines
306 #if ( ( __GNUC__ * 100) + __GNUC_MINOR__) >= 402
307 #define GCC_DIAG_STR(s) # s
308 #define GCC_DIAG_JOINSTR(x,y) GCC_DIAG_STR(x ## y)
309 # define GCC_DIAG_DO_PRAGMA(x) _Pragma ( # x)
310 # define GCC_DIAG_PRAGMA(x) GCC_DIAG_DO_PRAGMA(GCC diagnostic x)
311 # if ( ( __GNUC__ * 100) + __GNUC_MINOR__) >= 406
312 #  define GCC_DIAG_OFF(x) GCC_DIAG_PRAGMA(push) \
313     GCC_DIAG_PRAGMA( ignored GCC_DIAG_JOINSTR(-W,x) )
314 #  define GCC_DIAG_ON(x) GCC_DIAG_PRAGMA(pop)
315 # else
316 #  define GCC_DIAG_OFF(x) GCC_DIAG_PRAGMA( ignored GCC_DIAG_JOINSTR(-W,x) )
317 #  define GCC_DIAG_ON(x)  GCC_DIAG_PRAGMA( warning GCC_DIAG_JOINSTR(-W,x) )
318 # endif
319 #else
320 # define GCC_DIAG_OFF(x)
321 # define GCC_DIAG_ON(x)
322 #endif
323 
324 #ifdef __clang__
325 #  define CLANG_DIAG_STR(s) # s
326 // stringize s to "no-unused-variable"
327 #  define CLANG_DIAG_JOINSTR(x,y) CLANG_DIAG_STR(x ## y)
328 //  join -W with no-unused-variable to "-Wno-unused-variable"
329 #  define CLANG_DIAG_DO_PRAGMA(x) _Pragma ( # x)
330 // _Pragma is unary operator  #pragma ("")
331 #  define CLANG_DIAG_PRAGMA(x) CLANG_DIAG_DO_PRAGMA(clang diagnostic x)
332 #    define CLANG_DIAG_OFF(x) CLANG_DIAG_PRAGMA(push) \
333     CLANG_DIAG_PRAGMA( ignored CLANG_DIAG_JOINSTR(-W,x) )
334 // For example: #pragma clang diagnostic ignored "-Wno-unused-variable"
335 #   define CLANG_DIAG_ON(x) CLANG_DIAG_PRAGMA(pop)
336 // For example: #pragma clang diagnostic warning "-Wno-unused-variable"
337 #else // Ensure these macros so nothing for other compilers.
338 #  define CLANG_DIAG_OFF(x)
339 #  define CLANG_DIAG_ON(x)
340 #  define CLANG_DIAG_PRAGMA(x)
341 #endif
342 
343 /* Usage:
344    CLANG_DIAG_OFF(unused-variable)
345    CLANG_DIAG_OFF(unused-parameter)
346    CLANG_DIAG_OFF(uninitialized)
347  */
348 
349 #if COMPILER_SUPPORTS(CXX_OVERRIDE_CONTROL)
350 // we want to use override & final, and get no warnings even if not compiling in c++11 mode
351 CLANG_DIAG_OFF(c++11-extensions)
352 //GCC_DIAG_OFF(c++11-extensions) // no corresponding GCC warning option?
353 #endif
354 
355 /* *INDENT-ON* */
356 
357 #endif // ifndef openfx_supportext_ofxsMacros_h
358