compiler.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  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. #if __has_feature(leak_sanitizer)
  265. #define _lsan_enabled_
  266. #endif
  267. #else
  268. #if defined(thread_sanitizer_enabled) || defined(__SANITIZE_THREAD__)
  269. #define _tsan_enabled_
  270. #endif
  271. #if defined(memory_sanitizer_enabled)
  272. #define _msan_enabled_
  273. #endif
  274. #if defined(address_sanitizer_enabled) || defined(__SANITIZE_ADDRESS__)
  275. #define _asan_enabled_
  276. #endif
  277. #if defined(leak_sanitizer_enabled) || defined(__SANITIZE_LEAK__)
  278. #define _lsan_enabled_
  279. #endif
  280. #endif
  281. #if defined(_asan_enabled_) || defined(_msan_enabled_) || defined(_tsan_enabled_) || defined(_ubsan_enabled_) || defined(_lsan_enabled_)
  282. #define _san_enabled_
  283. #endif
  284. #if defined(_MSC_VER)
  285. #define __PRETTY_FUNCTION__ __FUNCSIG__
  286. #endif
  287. #if defined(__GNUC__)
  288. #define Y_WEAK __attribute__((weak))
  289. #else
  290. #define Y_WEAK
  291. #endif
  292. #if defined(__CUDACC_VER_MAJOR__)
  293. #define Y_CUDA_AT_LEAST(x, y) (__CUDACC_VER_MAJOR__ > x || (__CUDACC_VER_MAJOR__ == x && __CUDACC_VER_MINOR__ >= y))
  294. #else
  295. #define Y_CUDA_AT_LEAST(x, y) 0
  296. #endif
  297. #if defined(__GNUC__)
  298. #define Y_COLD __attribute__((cold))
  299. #define Y_LEAF __attribute__((leaf))
  300. #define Y_WRAPPER __attribute__((artificial))
  301. #else
  302. #define Y_COLD
  303. #define Y_LEAF
  304. #define Y_WRAPPER
  305. #endif
  306. /**
  307. * @def Y_PRAGMA
  308. *
  309. * Macro for use in other macros to define compiler pragma
  310. * See below for other usage examples
  311. *
  312. * @code
  313. * #if defined(__clang__) || defined(__GNUC__)
  314. * #define Y_PRAGMA_NO_WSHADOW \
  315. * Y_PRAGMA("GCC diagnostic ignored \"-Wshadow\"")
  316. * #elif defined(_MSC_VER)
  317. * #define Y_PRAGMA_NO_WSHADOW \
  318. * Y_PRAGMA("warning(disable:4456 4457")
  319. * #else
  320. * #define Y_PRAGMA_NO_WSHADOW
  321. * #endif
  322. * @endcode
  323. */
  324. #if defined(__clang__) || defined(__GNUC__)
  325. #define Y_PRAGMA(x) _Pragma(x)
  326. #elif defined(_MSC_VER)
  327. #define Y_PRAGMA(x) __pragma(x)
  328. #else
  329. #define Y_PRAGMA(x)
  330. #endif
  331. /**
  332. * @def Y_PRAGMA_DIAGNOSTIC_PUSH
  333. *
  334. * Cross-compiler pragma to save diagnostic settings
  335. *
  336. * @see
  337. * GCC: https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html
  338. * MSVC: https://msdn.microsoft.com/en-us/library/2c8f766e.aspx
  339. * Clang: https://clang.llvm.org/docs/UsersManual.html#controlling-diagnostics-via-pragmas
  340. *
  341. * @code
  342. * Y_PRAGMA_DIAGNOSTIC_PUSH
  343. * @endcode
  344. */
  345. #if defined(__clang__) || defined(__GNUC__)
  346. #define Y_PRAGMA_DIAGNOSTIC_PUSH \
  347. Y_PRAGMA("GCC diagnostic push")
  348. #elif defined(_MSC_VER)
  349. #define Y_PRAGMA_DIAGNOSTIC_PUSH \
  350. Y_PRAGMA(warning(push))
  351. #else
  352. #define Y_PRAGMA_DIAGNOSTIC_PUSH
  353. #endif
  354. /**
  355. * @def Y_PRAGMA_DIAGNOSTIC_POP
  356. *
  357. * Cross-compiler pragma to restore diagnostic settings
  358. *
  359. * @see
  360. * GCC: https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html
  361. * MSVC: https://msdn.microsoft.com/en-us/library/2c8f766e.aspx
  362. * Clang: https://clang.llvm.org/docs/UsersManual.html#controlling-diagnostics-via-pragmas
  363. *
  364. * @code
  365. * Y_PRAGMA_DIAGNOSTIC_POP
  366. * @endcode
  367. */
  368. #if defined(__clang__) || defined(__GNUC__)
  369. #define Y_PRAGMA_DIAGNOSTIC_POP \
  370. Y_PRAGMA("GCC diagnostic pop")
  371. #elif defined(_MSC_VER)
  372. #define Y_PRAGMA_DIAGNOSTIC_POP \
  373. Y_PRAGMA(warning(pop))
  374. #else
  375. #define Y_PRAGMA_DIAGNOSTIC_POP
  376. #endif
  377. /**
  378. * @def Y_PRAGMA_NO_WSHADOW
  379. *
  380. * Cross-compiler pragma to disable warnings about shadowing variables
  381. *
  382. * @code
  383. * Y_PRAGMA_DIAGNOSTIC_PUSH
  384. * Y_PRAGMA_NO_WSHADOW
  385. *
  386. * // some code which use variable shadowing, e.g.:
  387. *
  388. * for (int i = 0; i < 100; ++i) {
  389. * Use(i);
  390. *
  391. * for (int i = 42; i < 100500; ++i) { // this i is shadowing previous i
  392. * AnotherUse(i);
  393. * }
  394. * }
  395. *
  396. * Y_PRAGMA_DIAGNOSTIC_POP
  397. * @endcode
  398. */
  399. #if defined(__clang__) || defined(__GNUC__)
  400. #define Y_PRAGMA_NO_WSHADOW \
  401. Y_PRAGMA("GCC diagnostic ignored \"-Wshadow\"")
  402. #elif defined(_MSC_VER)
  403. #define Y_PRAGMA_NO_WSHADOW \
  404. Y_PRAGMA(warning(disable : 4456 4457))
  405. #else
  406. #define Y_PRAGMA_NO_WSHADOW
  407. #endif
  408. /**
  409. * @ def Y_PRAGMA_NO_UNUSED_FUNCTION
  410. *
  411. * Cross-compiler pragma to disable warnings about unused functions
  412. *
  413. * @see
  414. * GCC: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
  415. * Clang: https://clang.llvm.org/docs/DiagnosticsReference.html#wunused-function
  416. * MSVC: there is no such warning
  417. *
  418. * @code
  419. * Y_PRAGMA_DIAGNOSTIC_PUSH
  420. * Y_PRAGMA_NO_UNUSED_FUNCTION
  421. *
  422. * // some code which introduces a function which later will not be used, e.g.:
  423. *
  424. * void Foo() {
  425. * }
  426. *
  427. * int main() {
  428. * return 0; // Foo() never called
  429. * }
  430. *
  431. * Y_PRAGMA_DIAGNOSTIC_POP
  432. * @endcode
  433. */
  434. #if defined(__clang__) || defined(__GNUC__)
  435. #define Y_PRAGMA_NO_UNUSED_FUNCTION \
  436. Y_PRAGMA("GCC diagnostic ignored \"-Wunused-function\"")
  437. #else
  438. #define Y_PRAGMA_NO_UNUSED_FUNCTION
  439. #endif
  440. /**
  441. * @ def Y_PRAGMA_NO_UNUSED_PARAMETER
  442. *
  443. * Cross-compiler pragma to disable warnings about unused function parameters
  444. *
  445. * @see
  446. * GCC: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
  447. * Clang: https://clang.llvm.org/docs/DiagnosticsReference.html#wunused-parameter
  448. * MSVC: https://msdn.microsoft.com/en-us/library/26kb9fy0.aspx
  449. *
  450. * @code
  451. * Y_PRAGMA_DIAGNOSTIC_PUSH
  452. * Y_PRAGMA_NO_UNUSED_PARAMETER
  453. *
  454. * // some code which introduces a function with unused parameter, e.g.:
  455. *
  456. * void foo(int a) {
  457. * // a is not referenced
  458. * }
  459. *
  460. * int main() {
  461. * foo(1);
  462. * return 0;
  463. * }
  464. *
  465. * Y_PRAGMA_DIAGNOSTIC_POP
  466. * @endcode
  467. */
  468. #if defined(__clang__) || defined(__GNUC__)
  469. #define Y_PRAGMA_NO_UNUSED_PARAMETER \
  470. Y_PRAGMA("GCC diagnostic ignored \"-Wunused-parameter\"")
  471. #elif defined(_MSC_VER)
  472. #define Y_PRAGMA_NO_UNUSED_PARAMETER \
  473. Y_PRAGMA(warning(disable : 4100))
  474. #else
  475. #define Y_PRAGMA_NO_UNUSED_PARAMETER
  476. #endif
  477. /**
  478. * @def Y_PRAGMA_NO_DEPRECATED
  479. *
  480. * Cross compiler pragma to disable warnings and errors about deprecated
  481. *
  482. * @see
  483. * GCC: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
  484. * Clang: https://clang.llvm.org/docs/DiagnosticsReference.html#wdeprecated
  485. * MSVC: https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-3-c4996?view=vs-2017
  486. *
  487. * @code
  488. * Y_PRAGMA_DIAGNOSTIC_PUSH
  489. * Y_PRAGMA_NO_DEPRECATED
  490. *
  491. * [deprecated] void foo() {
  492. * // ...
  493. * }
  494. *
  495. * int main() {
  496. * foo();
  497. * return 0;
  498. * }
  499. *
  500. * Y_PRAGMA_DIAGNOSTIC_POP
  501. * @endcode
  502. */
  503. #if defined(__clang__) || defined(__GNUC__)
  504. #define Y_PRAGMA_NO_DEPRECATED \
  505. Y_PRAGMA("GCC diagnostic ignored \"-Wdeprecated\"")
  506. #elif defined(_MSC_VER)
  507. #define Y_PRAGMA_NO_DEPRECATED \
  508. Y_PRAGMA(warning(disable : 4996))
  509. #else
  510. #define Y_PRAGMA_NO_DEPRECATED
  511. #endif
  512. // Memory sanitizer sometimes doesn't correctly set parameter shadow of constant functions.
  513. #if (defined(__clang__) || defined(__GNUC__)) && !defined(_msan_enabled_)
  514. /**
  515. * @def Y_CONST_FUNCTION
  516. methods and functions, marked with this method are promised to:
  517. 1. do not have side effects
  518. 2. this method do not read global memory
  519. NOTE: this attribute can't be set for methods that depend on data, pointed by this
  520. this allow compilers to do hard optimization of that functions
  521. NOTE: in common case this attribute can't be set if method have pointer-arguments
  522. NOTE: as result there no any reason to discard result of such method
  523. */
  524. #define Y_CONST_FUNCTION [[gnu::const]]
  525. #endif
  526. #if !defined(Y_CONST_FUNCTION)
  527. #define Y_CONST_FUNCTION
  528. #endif
  529. #if defined(__clang__) || defined(__GNUC__)
  530. /**
  531. * @def Y_PURE_FUNCTION
  532. methods and functions, marked with this method are promised to:
  533. 1. do not have side effects
  534. 2. result will be the same if no global memory changed
  535. this allow compilers to do hard optimization of that functions
  536. NOTE: as result there no any reason to discard result of such method
  537. */
  538. #define Y_PURE_FUNCTION [[gnu::pure]]
  539. #endif
  540. #if !defined(Y_PURE_FUNCTION)
  541. #define Y_PURE_FUNCTION
  542. #endif
  543. /**
  544. * @ def Y_HAVE_INT128
  545. *
  546. * Defined when the compiler supports __int128 extension
  547. *
  548. * @code
  549. *
  550. * #if defined(Y_HAVE_INT128)
  551. * __int128 myVeryBigInt = 12345678901234567890;
  552. * #endif
  553. *
  554. * @endcode
  555. */
  556. #if defined(__SIZEOF_INT128__)
  557. #define Y_HAVE_INT128 1
  558. #endif
  559. #if defined(__clang__) && (!defined(__CUDACC__) || Y_CUDA_AT_LEAST(11, 0))
  560. #define Y_REINITIALIZES_OBJECT [[clang::reinitializes]]
  561. #else
  562. #define Y_REINITIALIZES_OBJECT
  563. #endif
  564. // Use at the end of macros declaration. It allows macros usage only with semicolon at the end.
  565. // It prevents from warnings for extra semicolons when building with flag `-Wextra-semi`.
  566. #define Y_SEMICOLON_GUARD static_assert(true, "")
  567. #ifdef __cplusplus
  568. void UseCharPointerImpl(volatile const char*);
  569. template <typename T>
  570. Y_FORCE_INLINE void DoNotOptimizeAway(T&& datum) {
  571. #if defined(_MSC_VER)
  572. UseCharPointerImpl(&reinterpret_cast<volatile const char&>(datum));
  573. _ReadWriteBarrier();
  574. #elif defined(__GNUC__) && defined(_x86_)
  575. asm volatile(""
  576. :
  577. : "X"(datum));
  578. #else
  579. Y_FAKE_READ(datum);
  580. #endif
  581. }
  582. /**
  583. * The usage for `const T&` is prohibited.
  584. * The compiler assume that a constant reference, even though escaped via asm volatile, is unchanged.
  585. * The const-ref interface is deleted to discourage new uses of it, as subtle compiler optimizations (invariant hoisting, etc.) can occur.
  586. * For more details see https://github.com/google/benchmark/pull/1493.
  587. */
  588. template <typename T>
  589. Y_FORCE_INLINE void DoNotOptimizeAway(const T&) = delete;
  590. /**
  591. * Use this macro to prevent unused variables elimination.
  592. */
  593. #define Y_DO_NOT_OPTIMIZE_AWAY(X) ::DoNotOptimizeAway(X)
  594. #endif
  595. /**
  596. * @def Y_LIFETIME_BOUND
  597. *
  598. * The attribute on a function parameter can be used to tell the compiler
  599. * that function return value may refer that parameter.
  600. * The compiler may produce compile-time warning if it is able to detect that
  601. * an object or reference refers to another object with a shorter lifetime.
  602. */
  603. #if defined(__clang__) && defined(__cplusplus) && defined(__has_cpp_attribute)
  604. #if defined(__CUDACC__) && (!Y_CUDA_AT_LEAST(11, 0) || (__clang_major__ < 13))
  605. #define Y_LIFETIME_BOUND
  606. #elif __has_cpp_attribute(clang::lifetimebound)
  607. #define Y_LIFETIME_BOUND [[clang::lifetimebound]]
  608. #else
  609. #define Y_LIFETIME_BOUND
  610. #endif
  611. #else
  612. #define Y_LIFETIME_BOUND
  613. #endif
  614. /**
  615. * @def Y_HAVE_ATTRIBUTE
  616. *
  617. * A function-like feature checking macro that is a wrapper around
  618. * `__has_attribute`, which is defined by GCC 5+ and Clang and evaluates to a
  619. * nonzero constant integer if the attribute is supported or 0 if not.
  620. *
  621. * It evaluates to zero if `__has_attribute` is not defined by the compiler.
  622. *
  623. * @see
  624. * GCC: https://gcc.gnu.org/gcc-5/changes.html
  625. * Clang: https://clang.llvm.org/docs/LanguageExtensions.html
  626. */
  627. #ifdef __has_attribute
  628. #define Y_HAVE_ATTRIBUTE(x) __has_attribute(x)
  629. #else
  630. #define Y_HAVE_ATTRIBUTE(x) 0
  631. #endif
  632. /**
  633. * @def Y_RETURNS_NONNULL
  634. *
  635. * The returns_nonnull attribute specifies that the function return value should
  636. * be a non-null pointer. It lets the compiler optimize callers based on
  637. * the knowledge that the return value will never be null.
  638. *
  639. * @see
  640. * GCC: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-returns_005fnonnull-function-attribute
  641. * Clang: https://clang.llvm.org/docs/AttributeReference.html#returns-nonnull
  642. *
  643. * @code
  644. * Y_RETURNS_NONNULL extern void* mymalloc(size_t len);
  645. * @endcode
  646. */
  647. #if Y_HAVE_ATTRIBUTE(returns_nonnull)
  648. #define Y_RETURNS_NONNULL __attribute__((returns_nonnull))
  649. #else
  650. #define Y_RETURNS_NONNULL
  651. #endif