compiler.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. #pragma once
  2. #if defined(_MSC_VER) && defined(__clang__)
  3. #define _compiler_clang_cl_
  4. #elif defined(_MSC_VER)
  5. #define _compiler_msvc_
  6. #elif defined(__clang__)
  7. #define _compiler_clang_
  8. #elif defined(__GNUC__)
  9. #define _compiler_gcc_
  10. #else
  11. #warning("Current compiler is not supported by " __FILE__)
  12. #endif
  13. #if defined(_MSC_VER)
  14. #include <intrin.h>
  15. #endif
  16. // useful cross-platfrom definitions for compilers
  17. /**
  18. * @def Y_FUNC_SIGNATURE
  19. *
  20. * Use this macro to get pretty function name (see example).
  21. *
  22. * @code
  23. * void Hi() {
  24. * Cout << Y_FUNC_SIGNATURE << Endl;
  25. * }
  26. * template <typename T>
  27. * void Do() {
  28. * Cout << Y_FUNC_SIGNATURE << Endl;
  29. * }
  30. * int main() {
  31. * Hi(); // void Hi()
  32. * Do<int>(); // void Do() [T = int]
  33. * Do<TString>(); // void Do() [T = TString]
  34. * }
  35. * @endcode
  36. */
  37. #if defined(__GNUC__)
  38. #define Y_FUNC_SIGNATURE __PRETTY_FUNCTION__
  39. #elif defined(_MSC_VER)
  40. #define Y_FUNC_SIGNATURE __FUNCSIG__
  41. #else
  42. #define Y_FUNC_SIGNATURE ""
  43. #endif
  44. #ifdef __GNUC__
  45. #define Y_PRINTF_FORMAT(n, m) __attribute__((__format__(__printf__, n, m)))
  46. #endif
  47. #ifndef Y_PRINTF_FORMAT
  48. #define Y_PRINTF_FORMAT(n, m)
  49. #endif
  50. #if defined(__clang__)
  51. #define Y_NO_SANITIZE(...) __attribute__((no_sanitize(__VA_ARGS__)))
  52. #endif
  53. #if !defined(Y_NO_SANITIZE)
  54. #define Y_NO_SANITIZE(...)
  55. #endif
  56. /**
  57. * @def Y_DECLARE_UNUSED
  58. *
  59. * Macro is needed to silence compiler warning about unused entities (e.g. function or argument).
  60. *
  61. * @code
  62. * Y_DECLARE_UNUSED int FunctionUsedSolelyForDebugPurposes();
  63. * assert(FunctionUsedSolelyForDebugPurposes() == 42);
  64. *
  65. * void Foo(const int argumentUsedOnlyForDebugPurposes Y_DECLARE_UNUSED) {
  66. * assert(argumentUsedOnlyForDebugPurposes == 42);
  67. * // however you may as well omit `Y_DECLARE_UNUSED` and use `UNUSED` macro instead
  68. * Y_UNUSED(argumentUsedOnlyForDebugPurposes);
  69. * }
  70. * @endcode
  71. */
  72. #ifdef __GNUC__
  73. #define Y_DECLARE_UNUSED __attribute__((unused))
  74. #endif
  75. #ifndef Y_DECLARE_UNUSED
  76. #define Y_DECLARE_UNUSED
  77. #endif
  78. #if defined(__GNUC__)
  79. #define Y_LIKELY(Cond) __builtin_expect(!!(Cond), 1)
  80. #define Y_UNLIKELY(Cond) __builtin_expect(!!(Cond), 0)
  81. #define Y_PREFETCH_READ(Pointer, Priority) __builtin_prefetch((const void*)(Pointer), 0, Priority)
  82. #define Y_PREFETCH_WRITE(Pointer, Priority) __builtin_prefetch((const void*)(Pointer), 1, Priority)
  83. #endif
  84. /**
  85. * @def Y_FORCE_INLINE
  86. *
  87. * Macro to use in place of 'inline' in function declaration/definition to force
  88. * it to be inlined.
  89. */
  90. #if !defined(Y_FORCE_INLINE)
  91. #if defined(CLANG_COVERAGE)
  92. #/* excessive __always_inline__ might significantly slow down compilation of an instrumented unit */
  93. #define Y_FORCE_INLINE inline
  94. #elif defined(_MSC_VER)
  95. #define Y_FORCE_INLINE __forceinline
  96. #elif defined(__GNUC__)
  97. #/* Clang also defines __GNUC__ (as 4) */
  98. #define Y_FORCE_INLINE inline __attribute__((__always_inline__))
  99. #else
  100. #define Y_FORCE_INLINE inline
  101. #endif
  102. #endif
  103. /**
  104. * @def Y_NO_INLINE
  105. *
  106. * Macro to use in place of 'inline' in function declaration/definition to
  107. * prevent it from being inlined.
  108. */
  109. #if !defined(Y_NO_INLINE)
  110. #if defined(_MSC_VER)
  111. #define Y_NO_INLINE __declspec(noinline)
  112. #elif defined(__GNUC__) || defined(__INTEL_COMPILER)
  113. #/* Clang also defines __GNUC__ (as 4) */
  114. #define Y_NO_INLINE __attribute__((__noinline__))
  115. #else
  116. #define Y_NO_INLINE
  117. #endif
  118. #endif
  119. //to cheat compiler about strict aliasing or similar problems
  120. #if defined(__GNUC__)
  121. #define Y_FAKE_READ(X) \
  122. do { \
  123. __asm__ __volatile__("" \
  124. : \
  125. : "m"(X)); \
  126. } while (0)
  127. #define Y_FAKE_WRITE(X) \
  128. do { \
  129. __asm__ __volatile__("" \
  130. : "=m"(X)); \
  131. } while (0)
  132. #endif
  133. #if !defined(Y_FAKE_READ)
  134. #define Y_FAKE_READ(X)
  135. #endif
  136. #if !defined(Y_FAKE_WRITE)
  137. #define Y_FAKE_WRITE(X)
  138. #endif
  139. #ifndef Y_PREFETCH_READ
  140. #define Y_PREFETCH_READ(Pointer, Priority) (void)(const void*)(Pointer), (void)Priority
  141. #endif
  142. #ifndef Y_PREFETCH_WRITE
  143. #define Y_PREFETCH_WRITE(Pointer, Priority) (void)(const void*)(Pointer), (void)Priority
  144. #endif
  145. #ifndef Y_LIKELY
  146. #define Y_LIKELY(Cond) (Cond)
  147. #define Y_UNLIKELY(Cond) (Cond)
  148. #endif
  149. #if defined(_compiler_clang_) || defined(_compiler_clang_cl_) || defined(_compiler_gcc_)
  150. #define Y_PACKED __attribute__((packed))
  151. #else
  152. #define Y_PACKED
  153. #endif
  154. #if defined(__GNUC__)
  155. #define Y_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
  156. #endif
  157. #ifndef Y_WARN_UNUSED_RESULT
  158. #define Y_WARN_UNUSED_RESULT
  159. #endif
  160. #if defined(__GNUC__)
  161. #define Y_HIDDEN __attribute__((visibility("hidden")))
  162. #endif
  163. #if !defined(Y_HIDDEN)
  164. #define Y_HIDDEN
  165. #endif
  166. #if defined(__GNUC__)
  167. #define Y_PUBLIC __attribute__((visibility("default")))
  168. #endif
  169. #if !defined(Y_PUBLIC)
  170. #define Y_PUBLIC
  171. #endif
  172. #if !defined(Y_UNUSED) && !defined(__cplusplus)
  173. #define Y_UNUSED(var) (void)(var)
  174. #endif
  175. #if !defined(Y_UNUSED) && defined(__cplusplus)
  176. template <class... Types>
  177. constexpr Y_FORCE_INLINE int Y_UNUSED(Types&&...) {
  178. return 0;
  179. }
  180. #endif
  181. /**
  182. * @def Y_ASSUME
  183. *
  184. * Macro that tells the compiler that it can generate optimized code
  185. * as if the given expression will always evaluate true.
  186. * The behavior is undefined if it ever evaluates false.
  187. *
  188. * @code
  189. * // factored into a function so that it's testable
  190. * inline int Avg(int x, int y) {
  191. * if (x >= 0 && y >= 0) {
  192. * return (static_cast<unsigned>(x) + static_cast<unsigned>(y)) >> 1;
  193. * } else {
  194. * // a slower implementation
  195. * }
  196. * }
  197. *
  198. * // we know that xs and ys are non-negative from domain knowledge,
  199. * // but we can't change the types of xs and ys because of API constrains
  200. * int Foo(const TVector<int>& xs, const TVector<int>& ys) {
  201. * TVector<int> avgs;
  202. * avgs.resize(xs.size());
  203. * for (size_t i = 0; i < xs.size(); ++i) {
  204. * auto x = xs[i];
  205. * auto y = ys[i];
  206. * Y_ASSUME(x >= 0);
  207. * Y_ASSUME(y >= 0);
  208. * xs[i] = Avg(x, y);
  209. * }
  210. * }
  211. * @endcode
  212. */
  213. #if defined(__GNUC__)
  214. #define Y_ASSUME(condition) ((condition) ? (void)0 : __builtin_unreachable())
  215. #elif defined(_MSC_VER)
  216. #define Y_ASSUME(condition) __assume(condition)
  217. #else
  218. #define Y_ASSUME(condition) Y_UNUSED(condition)
  219. #endif
  220. #ifdef __cplusplus
  221. [[noreturn]]
  222. #endif
  223. Y_HIDDEN void
  224. _YandexAbort();
  225. /**
  226. * @def Y_UNREACHABLE
  227. *
  228. * Macro that marks the rest of the code branch unreachable.
  229. * The behavior is undefined if it's ever reached.
  230. *
  231. * @code
  232. * switch (i % 3) {
  233. * case 0:
  234. * return foo;
  235. * case 1:
  236. * return bar;
  237. * case 2:
  238. * return baz;
  239. * default:
  240. * Y_UNREACHABLE();
  241. * }
  242. * @endcode
  243. */
  244. #if defined(__GNUC__)
  245. #define Y_UNREACHABLE() __builtin_unreachable()
  246. #elif defined(_MSC_VER)
  247. #define Y_UNREACHABLE() __assume(false)
  248. #else
  249. #define Y_UNREACHABLE() _YandexAbort()
  250. #endif
  251. #if defined(undefined_sanitizer_enabled)
  252. #define _ubsan_enabled_
  253. #endif
  254. #ifdef __clang__
  255. #if __has_feature(thread_sanitizer)
  256. #define _tsan_enabled_
  257. #endif
  258. #if __has_feature(memory_sanitizer)
  259. #define _msan_enabled_
  260. #endif
  261. #if __has_feature(address_sanitizer)
  262. #define _asan_enabled_
  263. #endif
  264. #else
  265. #if defined(thread_sanitizer_enabled) || defined(__SANITIZE_THREAD__)
  266. #define _tsan_enabled_
  267. #endif
  268. #if defined(memory_sanitizer_enabled)
  269. #define _msan_enabled_
  270. #endif
  271. #if defined(address_sanitizer_enabled) || defined(__SANITIZE_ADDRESS__)
  272. #define _asan_enabled_
  273. #endif
  274. #endif
  275. #if defined(_asan_enabled_) || defined(_msan_enabled_) || defined(_tsan_enabled_) || defined(_ubsan_enabled_)
  276. #define _san_enabled_
  277. #endif
  278. #if defined(_MSC_VER)
  279. #define __PRETTY_FUNCTION__ __FUNCSIG__
  280. #endif
  281. #if defined(__GNUC__)
  282. #define Y_WEAK __attribute__((weak))
  283. #else
  284. #define Y_WEAK
  285. #endif
  286. #if defined(__CUDACC_VER_MAJOR__)
  287. #define Y_CUDA_AT_LEAST(x, y) (__CUDACC_VER_MAJOR__ > x || (__CUDACC_VER_MAJOR__ == x && __CUDACC_VER_MINOR__ >= y))
  288. #else
  289. #define Y_CUDA_AT_LEAST(x, y) 0
  290. #endif
  291. #if defined(__GNUC__)
  292. #define Y_COLD __attribute__((cold))
  293. #define Y_LEAF __attribute__((leaf))
  294. #define Y_WRAPPER __attribute__((artificial))
  295. #else
  296. #define Y_COLD
  297. #define Y_LEAF
  298. #define Y_WRAPPER
  299. #endif
  300. /**
  301. * @def Y_PRAGMA
  302. *
  303. * Macro for use in other macros to define compiler pragma
  304. * See below for other usage examples
  305. *
  306. * @code
  307. * #if defined(__clang__) || defined(__GNUC__)
  308. * #define Y_PRAGMA_NO_WSHADOW \
  309. * Y_PRAGMA("GCC diagnostic ignored \"-Wshadow\"")
  310. * #elif defined(_MSC_VER)
  311. * #define Y_PRAGMA_NO_WSHADOW \
  312. * Y_PRAGMA("warning(disable:4456 4457")
  313. * #else
  314. * #define Y_PRAGMA_NO_WSHADOW
  315. * #endif
  316. * @endcode
  317. */
  318. #if defined(__clang__) || defined(__GNUC__)
  319. #define Y_PRAGMA(x) _Pragma(x)
  320. #elif defined(_MSC_VER)
  321. #define Y_PRAGMA(x) __pragma(x)
  322. #else
  323. #define Y_PRAGMA(x)
  324. #endif
  325. /**
  326. * @def Y_PRAGMA_DIAGNOSTIC_PUSH
  327. *
  328. * Cross-compiler pragma to save diagnostic settings
  329. *
  330. * @see
  331. * GCC: https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html
  332. * MSVC: https://msdn.microsoft.com/en-us/library/2c8f766e.aspx
  333. * Clang: https://clang.llvm.org/docs/UsersManual.html#controlling-diagnostics-via-pragmas
  334. *
  335. * @code
  336. * Y_PRAGMA_DIAGNOSTIC_PUSH
  337. * @endcode
  338. */
  339. #if defined(__clang__) || defined(__GNUC__)
  340. #define Y_PRAGMA_DIAGNOSTIC_PUSH \
  341. Y_PRAGMA("GCC diagnostic push")
  342. #elif defined(_MSC_VER)
  343. #define Y_PRAGMA_DIAGNOSTIC_PUSH \
  344. Y_PRAGMA(warning(push))
  345. #else
  346. #define Y_PRAGMA_DIAGNOSTIC_PUSH
  347. #endif
  348. /**
  349. * @def Y_PRAGMA_DIAGNOSTIC_POP
  350. *
  351. * Cross-compiler pragma to restore diagnostic settings
  352. *
  353. * @see
  354. * GCC: https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html
  355. * MSVC: https://msdn.microsoft.com/en-us/library/2c8f766e.aspx
  356. * Clang: https://clang.llvm.org/docs/UsersManual.html#controlling-diagnostics-via-pragmas
  357. *
  358. * @code
  359. * Y_PRAGMA_DIAGNOSTIC_POP
  360. * @endcode
  361. */
  362. #if defined(__clang__) || defined(__GNUC__)
  363. #define Y_PRAGMA_DIAGNOSTIC_POP \
  364. Y_PRAGMA("GCC diagnostic pop")
  365. #elif defined(_MSC_VER)
  366. #define Y_PRAGMA_DIAGNOSTIC_POP \
  367. Y_PRAGMA(warning(pop))
  368. #else
  369. #define Y_PRAGMA_DIAGNOSTIC_POP
  370. #endif
  371. /**
  372. * @def Y_PRAGMA_NO_WSHADOW
  373. *
  374. * Cross-compiler pragma to disable warnings about shadowing variables
  375. *
  376. * @code
  377. * Y_PRAGMA_DIAGNOSTIC_PUSH
  378. * Y_PRAGMA_NO_WSHADOW
  379. *
  380. * // some code which use variable shadowing, e.g.:
  381. *
  382. * for (int i = 0; i < 100; ++i) {
  383. * Use(i);
  384. *
  385. * for (int i = 42; i < 100500; ++i) { // this i is shadowing previous i
  386. * AnotherUse(i);
  387. * }
  388. * }
  389. *
  390. * Y_PRAGMA_DIAGNOSTIC_POP
  391. * @endcode
  392. */
  393. #if defined(__clang__) || defined(__GNUC__)
  394. #define Y_PRAGMA_NO_WSHADOW \
  395. Y_PRAGMA("GCC diagnostic ignored \"-Wshadow\"")
  396. #elif defined(_MSC_VER)
  397. #define Y_PRAGMA_NO_WSHADOW \
  398. Y_PRAGMA(warning(disable : 4456 4457))
  399. #else
  400. #define Y_PRAGMA_NO_WSHADOW
  401. #endif
  402. /**
  403. * @ def Y_PRAGMA_NO_UNUSED_FUNCTION
  404. *
  405. * Cross-compiler pragma to disable warnings about unused functions
  406. *
  407. * @see
  408. * GCC: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
  409. * Clang: https://clang.llvm.org/docs/DiagnosticsReference.html#wunused-function
  410. * MSVC: there is no such warning
  411. *
  412. * @code
  413. * Y_PRAGMA_DIAGNOSTIC_PUSH
  414. * Y_PRAGMA_NO_UNUSED_FUNCTION
  415. *
  416. * // some code which introduces a function which later will not be used, e.g.:
  417. *
  418. * void Foo() {
  419. * }
  420. *
  421. * int main() {
  422. * return 0; // Foo() never called
  423. * }
  424. *
  425. * Y_PRAGMA_DIAGNOSTIC_POP
  426. * @endcode
  427. */
  428. #if defined(__clang__) || defined(__GNUC__)
  429. #define Y_PRAGMA_NO_UNUSED_FUNCTION \
  430. Y_PRAGMA("GCC diagnostic ignored \"-Wunused-function\"")
  431. #else
  432. #define Y_PRAGMA_NO_UNUSED_FUNCTION
  433. #endif
  434. /**
  435. * @ def Y_PRAGMA_NO_UNUSED_PARAMETER
  436. *
  437. * Cross-compiler pragma to disable warnings about unused function parameters
  438. *
  439. * @see
  440. * GCC: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
  441. * Clang: https://clang.llvm.org/docs/DiagnosticsReference.html#wunused-parameter
  442. * MSVC: https://msdn.microsoft.com/en-us/library/26kb9fy0.aspx
  443. *
  444. * @code
  445. * Y_PRAGMA_DIAGNOSTIC_PUSH
  446. * Y_PRAGMA_NO_UNUSED_PARAMETER
  447. *
  448. * // some code which introduces a function with unused parameter, e.g.:
  449. *
  450. * void foo(int a) {
  451. * // a is not referenced
  452. * }
  453. *
  454. * int main() {
  455. * foo(1);
  456. * return 0;
  457. * }
  458. *
  459. * Y_PRAGMA_DIAGNOSTIC_POP
  460. * @endcode
  461. */
  462. #if defined(__clang__) || defined(__GNUC__)
  463. #define Y_PRAGMA_NO_UNUSED_PARAMETER \
  464. Y_PRAGMA("GCC diagnostic ignored \"-Wunused-parameter\"")
  465. #elif defined(_MSC_VER)
  466. #define Y_PRAGMA_NO_UNUSED_PARAMETER \
  467. Y_PRAGMA(warning(disable : 4100))
  468. #else
  469. #define Y_PRAGMA_NO_UNUSED_PARAMETER
  470. #endif
  471. /**
  472. * @def Y_PRAGMA_NO_DEPRECATED
  473. *
  474. * Cross compiler pragma to disable warnings and errors about deprecated
  475. *
  476. * @see
  477. * GCC: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
  478. * Clang: https://clang.llvm.org/docs/DiagnosticsReference.html#wdeprecated
  479. * MSVC: https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-3-c4996?view=vs-2017
  480. *
  481. * @code
  482. * Y_PRAGMA_DIAGNOSTIC_PUSH
  483. * Y_PRAGMA_NO_DEPRECATED
  484. *
  485. * [deprecated] void foo() {
  486. * // ...
  487. * }
  488. *
  489. * int main() {
  490. * foo();
  491. * return 0;
  492. * }
  493. *
  494. * Y_PRAGMA_DIAGNOSTIC_POP
  495. * @endcode
  496. */
  497. #if defined(__clang__) || defined(__GNUC__)
  498. #define Y_PRAGMA_NO_DEPRECATED \
  499. Y_PRAGMA("GCC diagnostic ignored \"-Wdeprecated\"")
  500. #elif defined(_MSC_VER)
  501. #define Y_PRAGMA_NO_DEPRECATED \
  502. Y_PRAGMA(warning(disable : 4996))
  503. #else
  504. #define Y_PRAGMA_NO_DEPRECATED
  505. #endif
  506. // Memory sanitizer sometimes doesn't correctly set parameter shadow of constant functions.
  507. #if (defined(__clang__) || defined(__GNUC__)) && !defined(_msan_enabled_)
  508. /**
  509. * @def Y_CONST_FUNCTION
  510. methods and functions, marked with this method are promised to:
  511. 1. do not have side effects
  512. 2. this method do not read global memory
  513. NOTE: this attribute can't be set for methods that depend on data, pointed by this
  514. this allow compilers to do hard optimization of that functions
  515. NOTE: in common case this attribute can't be set if method have pointer-arguments
  516. NOTE: as result there no any reason to discard result of such method
  517. */
  518. #define Y_CONST_FUNCTION [[gnu::const]]
  519. #endif
  520. #if !defined(Y_CONST_FUNCTION)
  521. #define Y_CONST_FUNCTION
  522. #endif
  523. #if defined(__clang__) || defined(__GNUC__)
  524. /**
  525. * @def Y_PURE_FUNCTION
  526. methods and functions, marked with this method are promised to:
  527. 1. do not have side effects
  528. 2. result will be the same if no global memory changed
  529. this allow compilers to do hard optimization of that functions
  530. NOTE: as result there no any reason to discard result of such method
  531. */
  532. #define Y_PURE_FUNCTION [[gnu::pure]]
  533. #endif
  534. #if !defined(Y_PURE_FUNCTION)
  535. #define Y_PURE_FUNCTION
  536. #endif
  537. /**
  538. * @ def Y_HAVE_INT128
  539. *
  540. * Defined when the compiler supports __int128 extension
  541. *
  542. * @code
  543. *
  544. * #if defined(Y_HAVE_INT128)
  545. * __int128 myVeryBigInt = 12345678901234567890;
  546. * #endif
  547. *
  548. * @endcode
  549. */
  550. #if defined(__SIZEOF_INT128__)
  551. #define Y_HAVE_INT128 1
  552. #endif
  553. #if defined(__clang__) && Y_CUDA_AT_LEAST(11, 0)
  554. #define Y_REINITIALIZES_OBJECT [[clang::reinitializes]]
  555. #else
  556. #define Y_REINITIALIZES_OBJECT
  557. #endif
  558. // Use at the end of macros declaration. It allows macros usage only with semicolon at the end.
  559. // It prevents from warnings for extra semicolons when building with flag `-Wextra-semi`.
  560. #define Y_SEMICOLON_GUARD static_assert(true, "")
  561. #ifdef __cplusplus
  562. void UseCharPointerImpl(volatile const char*);
  563. template <typename T>
  564. Y_FORCE_INLINE void DoNotOptimizeAway(T&& datum) {
  565. #if defined(_MSC_VER)
  566. UseCharPointerImpl(&reinterpret_cast<volatile const char&>(datum));
  567. _ReadWriteBarrier();
  568. #elif defined(__GNUC__) && defined(_x86_)
  569. asm volatile(""
  570. :
  571. : "X"(datum));
  572. #else
  573. Y_FAKE_READ(datum);
  574. #endif
  575. }
  576. /**
  577. * Use this macro to prevent unused variables elimination.
  578. */
  579. #define Y_DO_NOT_OPTIMIZE_AWAY(X) ::DoNotOptimizeAway(X)
  580. #endif