language.hpp (10136B)
1 #ifndef _C4_LANGUAGE_HPP_ 2 #define _C4_LANGUAGE_HPP_ 3 4 /** @file language.hpp Provides language standard information macros and 5 * compiler agnostic utility macros: namespace facilities, function attributes, 6 * variable attributes, etc. 7 * @ingroup basic_headers */ 8 9 #include "c4/preprocessor.hpp" 10 #include "c4/compiler.hpp" 11 12 /* Detect C++ standard. 13 * @see http://stackoverflow.com/a/7132549/5875572 */ 14 #ifndef C4_CPP 15 # if defined(_MSC_VER) && !defined(__clang__) 16 # if _MSC_VER >= 1910 // >VS2015: VS2017, VS2019 17 # if (!defined(_MSVC_LANG)) 18 # error _MSVC not defined 19 # endif 20 # if _MSVC_LANG >= 201705L 21 # define C4_CPP 20 22 # define C4_CPP20 23 # elif _MSVC_LANG == 201703L 24 # define C4_CPP 17 25 # define C4_CPP17 26 # elif _MSVC_LANG >= 201402L 27 # define C4_CPP 14 28 # define C4_CPP14 29 # elif _MSVC_LANG >= 201103L 30 # define C4_CPP 11 31 # define C4_CPP11 32 # else 33 # error C++ lesser than C++11 not supported 34 # endif 35 # else 36 # if _MSC_VER == 1900 37 # define C4_CPP 14 // VS2015 is c++14 https://devblogs.microsoft.com/cppblog/c111417-features-in-vs-2015-rtm/ 38 # define C4_CPP14 39 # elif _MSC_VER == 1800 // VS2013 40 # define C4_CPP 11 41 # define C4_CPP11 42 # else 43 # error C++ lesser than C++11 not supported 44 # endif 45 # endif 46 # elif defined(__INTEL_COMPILER) // https://software.intel.com/en-us/node/524490 47 # ifdef __INTEL_CXX20_MODE__ // not sure about this 48 # define C4_CPP 20 49 # define C4_CPP20 50 # elif defined __INTEL_CXX17_MODE__ // not sure about this 51 # define C4_CPP 17 52 # define C4_CPP17 53 # elif defined __INTEL_CXX14_MODE__ // not sure about this 54 # define C4_CPP 14 55 # define C4_CPP14 56 # elif defined __INTEL_CXX11_MODE__ 57 # define C4_CPP 11 58 # define C4_CPP11 59 # else 60 # error C++ lesser than C++11 not supported 61 # endif 62 # else 63 # ifndef __cplusplus 64 # error __cplusplus is not defined? 65 # endif 66 # if __cplusplus == 1 67 # error cannot handle __cplusplus==1 68 # elif __cplusplus >= 201709L 69 # define C4_CPP 20 70 # define C4_CPP20 71 # elif __cplusplus >= 201703L 72 # define C4_CPP 17 73 # define C4_CPP17 74 # elif __cplusplus >= 201402L 75 # define C4_CPP 14 76 # define C4_CPP14 77 # elif __cplusplus >= 201103L 78 # define C4_CPP 11 79 # define C4_CPP11 80 # elif __cplusplus >= 199711L 81 # error C++ lesser than C++11 not supported 82 # endif 83 # endif 84 #else 85 # ifdef C4_CPP == 20 86 # define C4_CPP20 87 # elif C4_CPP == 17 88 # define C4_CPP17 89 # elif C4_CPP == 14 90 # define C4_CPP14 91 # elif C4_CPP == 11 92 # define C4_CPP11 93 # elif C4_CPP == 98 94 # define C4_CPP98 95 # error C++ lesser than C++11 not supported 96 # else 97 # error C4_CPP must be one of 20, 17, 14, 11, 98 98 # endif 99 #endif 100 101 #ifdef C4_CPP20 102 # define C4_CPP17 103 # define C4_CPP14 104 # define C4_CPP11 105 #elif defined(C4_CPP17) 106 # define C4_CPP14 107 # define C4_CPP11 108 #elif defined(C4_CPP14) 109 # define C4_CPP11 110 #endif 111 112 /** lifted from this answer: http://stackoverflow.com/a/20170989/5875572 */ 113 #if defined(_MSC_VER) && !defined(__clang__) 114 # if _MSC_VER < 1900 115 # define C4_CONSTEXPR11 116 # define C4_CONSTEXPR14 117 # elif _MSC_VER < 2000 118 # define C4_CONSTEXPR11 constexpr 119 # define C4_CONSTEXPR14 120 # else 121 # define C4_CONSTEXPR11 constexpr 122 # define C4_CONSTEXPR14 constexpr 123 # endif 124 #else 125 # if __cplusplus < 201103 126 # define C4_CONSTEXPR11 127 # define C4_CONSTEXPR14 128 # elif __cplusplus == 201103 129 # define C4_CONSTEXPR11 constexpr 130 # define C4_CONSTEXPR14 131 # else 132 # define C4_CONSTEXPR11 constexpr 133 # define C4_CONSTEXPR14 constexpr 134 # endif 135 #endif // _MSC_VER 136 137 138 #if C4_CPP < 17 139 #define C4_IF_CONSTEXPR 140 #define C4_INLINE_CONSTEXPR constexpr 141 #else 142 #define C4_IF_CONSTEXPR constexpr 143 #define C4_INLINE_CONSTEXPR inline constexpr 144 #endif 145 146 #if defined(_MSC_VER) && !defined(__clang__) 147 # if (defined(_CPPUNWIND) && (_CPPUNWIND == 1)) 148 # define C4_EXCEPTIONS 149 # endif 150 #else 151 # if defined(__EXCEPTIONS) || defined(__cpp_exceptions) 152 # define C4_EXCEPTIONS 153 # endif 154 #endif 155 156 #ifdef C4_EXCEPTIONS 157 # define C4_IF_EXCEPTIONS_(exc_code, setjmp_code) exc_code 158 # define C4_IF_EXCEPTIONS(exc_code, setjmp_code) do { exc_code } while(0) 159 #else 160 # define C4_IF_EXCEPTIONS_(exc_code, setjmp_code) setjmp_code 161 # define C4_IF_EXCEPTIONS(exc_code, setjmp_code) do { setjmp_code } while(0) 162 #endif 163 164 #if defined(_MSC_VER) && !defined(__clang__) 165 # if defined(_CPPRTTI) 166 # define C4_RTTI 167 # endif 168 #else 169 # if defined(__GXX_RTTI) 170 # define C4_RTTI 171 # endif 172 #endif 173 174 #ifdef C4_RTTI 175 # define C4_IF_RTTI_(code_rtti, code_no_rtti) code_rtti 176 # define C4_IF_RTTI(code_rtti, code_no_rtti) do { code_rtti } while(0) 177 #else 178 # define C4_IF_RTTI_(code_rtti, code_no_rtti) code_no_rtti 179 # define C4_IF_RTTI(code_rtti, code_no_rtti) do { code_no_rtti } while(0) 180 #endif 181 182 183 //------------------------------------------------------------ 184 185 #define _C4_BEGIN_NAMESPACE(ns) namespace ns { 186 #define _C4_END_NAMESPACE(ns) } 187 188 // MSVC cant handle the C4_FOR_EACH macro... need to fix this 189 //#define C4_BEGIN_NAMESPACE(...) C4_FOR_EACH_SEP(_C4_BEGIN_NAMESPACE, , __VA_ARGS__) 190 //#define C4_END_NAMESPACE(...) C4_FOR_EACH_SEP(_C4_END_NAMESPACE, , __VA_ARGS__) 191 #define C4_BEGIN_NAMESPACE(ns) namespace ns { 192 #define C4_END_NAMESPACE(ns) } 193 194 #define C4_BEGIN_HIDDEN_NAMESPACE namespace /*hidden*/ { 195 #define C4_END_HIDDEN_NAMESPACE } /* namespace hidden */ 196 197 //------------------------------------------------------------ 198 199 #ifndef C4_API 200 # if defined(_MSC_VER) && !defined(__clang__) 201 # if defined(C4_EXPORT) 202 # define C4_API __declspec(dllexport) 203 # elif defined(C4_IMPORT) 204 # define C4_API __declspec(dllimport) 205 # else 206 # define C4_API 207 # endif 208 # else 209 # define C4_API 210 # endif 211 #endif 212 213 #if defined(_MSC_VER) && !defined(__clang__) 214 # define C4_RESTRICT __restrict 215 # define C4_RESTRICT_FN __declspec(restrict) 216 # define C4_NO_INLINE __declspec(noinline) 217 # define C4_ALWAYS_INLINE inline __forceinline 218 /** these are not available in VS AFAIK */ 219 # define C4_CONST 220 # define C4_PURE 221 # define C4_FLATTEN 222 # define C4_HOT /** @todo */ 223 # define C4_COLD /** @todo */ 224 # define C4_EXPECT(x, y) x /** @todo */ 225 # define C4_LIKELY(x) x /** @todo */ 226 # define C4_UNLIKELY(x) x /** @todo */ 227 # define C4_UNREACHABLE() /** @todo */ 228 # define C4_ATTR_FORMAT(...) /** */ 229 # define C4_NORETURN /** @todo */ 230 #else 231 ///< @todo assuming gcc-like compiler. check it is actually so. 232 /** for function attributes in GCC, 233 * @see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes */ 234 /** for __builtin functions in GCC, 235 * @see https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html */ 236 # define C4_RESTRICT __restrict__ 237 # define C4_RESTRICT_FN __attribute__((restrict)) 238 # define C4_NO_INLINE __attribute__((noinline)) 239 # define C4_ALWAYS_INLINE inline __attribute__((always_inline)) 240 # define C4_CONST __attribute__((const)) 241 # define C4_PURE __attribute__((pure)) 242 /** force inlining of every callee function */ 243 # define C4_FLATTEN __atribute__((flatten)) 244 /** mark a function as hot, ie as having a visible impact in CPU time 245 * thus making it more likely to inline, etc 246 * @see http://stackoverflow.com/questions/15028990/semantics-of-gcc-hot-attribute */ 247 # define C4_HOT __attribute__((hot)) 248 /** mark a function as cold, ie as NOT having a visible impact in CPU time 249 * @see http://stackoverflow.com/questions/15028990/semantics-of-gcc-hot-attribute */ 250 # define C4_COLD __attribute__((cold)) 251 # define C4_EXPECT(x, y) __builtin_expect(x, y) ///< @see https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html 252 # define C4_LIKELY(x) __builtin_expect(x, 1) 253 # define C4_UNLIKELY(x) __builtin_expect(x, 0) 254 # define C4_UNREACHABLE() __builtin_unreachable() 255 # define C4_ATTR_FORMAT(...) //__attribute__((format (__VA_ARGS__))) ///< @see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes 256 # define C4_NORETURN __attribute__((noreturn)) 257 #endif 258 259 #ifdef _MSC_VER 260 # define C4_FUNC __FUNCTION__ 261 # define C4_PRETTY_FUNC __FUNCSIG__ 262 #else /// @todo assuming gcc-like compiler. check it is actually so. 263 # define C4_FUNC __FUNCTION__ 264 # define C4_PRETTY_FUNC __PRETTY_FUNCTION__ 265 #endif 266 267 /** prevent compiler warnings about a specific var being unused */ 268 #define C4_UNUSED(var) (void)var 269 270 #if C4_CPP >= 17 271 #define C4_STATIC_ASSERT(cond) static_assert(cond) 272 #else 273 #define C4_STATIC_ASSERT(cond) static_assert((cond), #cond) 274 #endif 275 #define C4_STATIC_ASSERT_MSG(cond, msg) static_assert((cond), #cond ": " msg) 276 277 /** @def C4_DONT_OPTIMIZE idea lifted from GoogleBenchmark. 278 * @see https://github.com/google/benchmark/blob/master/include/benchmark/benchmark_api.h */ 279 namespace c4 { 280 namespace detail { 281 #ifdef __GNUC__ 282 # define C4_DONT_OPTIMIZE(var) c4::detail::dont_optimize(var) 283 template< class T > 284 C4_ALWAYS_INLINE void dont_optimize(T const& value) { asm volatile("" : : "g"(value) : "memory"); } 285 #else 286 # define C4_DONT_OPTIMIZE(var) c4::detail::use_char_pointer(reinterpret_cast< const char* >(&var)) 287 void use_char_pointer(char const volatile*); 288 #endif 289 } // namespace detail 290 } // namespace c4 291 292 /** @def C4_KEEP_EMPTY_LOOP prevent an empty loop from being optimized out. 293 * @see http://stackoverflow.com/a/7084193/5875572 */ 294 #if defined(_MSC_VER) && !defined(__clang__) 295 # define C4_KEEP_EMPTY_LOOP { char c; C4_DONT_OPTIMIZE(c); } 296 #else 297 # define C4_KEEP_EMPTY_LOOP { asm(""); } 298 #endif 299 300 /** @def C4_VA_LIST_REUSE_MUST_COPY 301 * @todo <jpmag> I strongly suspect that this is actually only in UNIX platforms. revisit this. */ 302 #ifdef __GNUC__ 303 # define C4_VA_LIST_REUSE_MUST_COPY 304 #endif 305 306 #endif /* _C4_LANGUAGE_HPP_ */