simde-detect-clang.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /* Detect Clang Version
  2. * Created by Evan Nemerson <[email protected]>
  3. *
  4. * To the extent possible under law, the author(s) have dedicated all
  5. * copyright and related and neighboring rights to this software to
  6. * the public domain worldwide. This software is distributed without
  7. * any warranty.
  8. *
  9. * For details, see <http://creativecommons.org/publicdomain/zero/1.0/>.
  10. * SPDX-License-Identifier: CC0-1.0
  11. */
  12. /* This file was originally part of SIMDe
  13. * (<https://github.com/simd-everywhere/simde>). You're free to do with it as
  14. * you please, but I do have a few small requests:
  15. *
  16. * * If you make improvements, please submit them back to SIMDe
  17. * (at <https://github.com/simd-everywhere/simde/issues>) so others can
  18. * benefit from them.
  19. * * Please keep a link to SIMDe intact so people know where to submit
  20. * improvements.
  21. * * If you expose it publicly, please change the SIMDE_ prefix to
  22. * something specific to your project.
  23. *
  24. * The version numbers clang exposes (in the ___clang_major__,
  25. * __clang_minor__, and __clang_patchlevel__ macros) are unreliable.
  26. * Vendors such as Apple will define these values to their version
  27. * numbers; for example, "Apple Clang 4.0" is really clang 3.1, but
  28. * __clang_major__ and __clang_minor__ are defined to 4 and 0
  29. * respectively, instead of 3 and 1.
  30. *
  31. * The solution is *usually* to use clang's feature detection macros
  32. * (<https://clang.llvm.org/docs/LanguageExtensions.html#feature-checking-macros>)
  33. * to determine if the feature you're interested in is available. This
  34. * generally works well, and it should probably be the first thing you
  35. * try. Unfortunately, it's not possible to check for everything. In
  36. * particular, compiler bugs.
  37. *
  38. * This file just uses the feature checking macros to detect features
  39. * added in specific versions of clang to identify which version of
  40. * clang the compiler is based on.
  41. *
  42. * Right now it only goes back to 3.6, but I'm happy to accept patches
  43. * to go back further. And, of course, newer versions are welcome if
  44. * they're not already present, and if you find a way to detect a point
  45. * release that would be great, too!
  46. */
  47. #if !defined(SIMDE_DETECT_CLANG_H)
  48. #define SIMDE_DETECT_CLANG_H 1
  49. /* Attempt to detect the upstream clang version number. I usually only
  50. * worry about major version numbers (at least for 4.0+), but if you
  51. * need more resolution I'm happy to accept patches that are able to
  52. * detect minor versions as well. That said, you'll probably have a
  53. * hard time with detection since AFAIK most minor releases don't add
  54. * anything we can detect. */
  55. #if defined(__clang__) && !defined(SIMDE_DETECT_CLANG_VERSION)
  56. #if __has_warning("-Wformat-insufficient-args")
  57. #define SIMDE_DETECT_CLANG_VERSION 120000
  58. #elif __has_warning("-Wimplicit-const-int-float-conversion")
  59. #define SIMDE_DETECT_CLANG_VERSION 110000
  60. #elif __has_warning("-Wmisleading-indentation")
  61. #define SIMDE_DETECT_CLANG_VERSION 100000
  62. #elif defined(__FILE_NAME__)
  63. #define SIMDE_DETECT_CLANG_VERSION 90000
  64. #elif __has_warning("-Wextra-semi-stmt") || \
  65. __has_builtin(__builtin_rotateleft32)
  66. #define SIMDE_DETECT_CLANG_VERSION 80000
  67. #elif __has_warning("-Wc++98-compat-extra-semi")
  68. #define SIMDE_DETECT_CLANG_VERSION 70000
  69. #elif __has_warning("-Wpragma-pack")
  70. #define SIMDE_DETECT_CLANG_VERSION 60000
  71. #elif __has_warning("-Wbitfield-enum-conversion")
  72. #define SIMDE_DETECT_CLANG_VERSION 50000
  73. #elif __has_attribute(diagnose_if)
  74. #define SIMDE_DETECT_CLANG_VERSION 40000
  75. #elif __has_warning("-Wcast-calling-convention")
  76. #define SIMDE_DETECT_CLANG_VERSION 30900
  77. #elif __has_warning("-WCL4")
  78. #define SIMDE_DETECT_CLANG_VERSION 30800
  79. #elif __has_warning("-WIndependentClass-attribute")
  80. #define SIMDE_DETECT_CLANG_VERSION 30700
  81. #elif __has_warning("-Wambiguous-ellipsis")
  82. #define SIMDE_DETECT_CLANG_VERSION 30600
  83. #else
  84. #define SIMDE_DETECT_CLANG_VERSION 1
  85. #endif
  86. #endif /* defined(__clang__) && !defined(SIMDE_DETECT_CLANG_VERSION) */
  87. /* The SIMDE_DETECT_CLANG_VERSION_CHECK macro is pretty
  88. * straightforward; it returns true if the compiler is a derivative
  89. * of clang >= the specified version.
  90. *
  91. * Since this file is often (primarily?) useful for working around bugs
  92. * it is also helpful to have a macro which returns true if only if the
  93. * compiler is a version of clang *older* than the specified version to
  94. * make it a bit easier to ifdef regions to add code for older versions,
  95. * such as pragmas to disable a specific warning. */
  96. #if defined(SIMDE_DETECT_CLANG_VERSION)
  97. #define SIMDE_DETECT_CLANG_VERSION_CHECK(major, minor, revision) \
  98. (SIMDE_DETECT_CLANG_VERSION >= \
  99. ((major * 10000) + (minor * 1000) + (revision)))
  100. #define SIMDE_DETECT_CLANG_VERSION_NOT(major, minor, revision) \
  101. (SIMDE_DETECT_CLANG_VERSION < \
  102. ((major * 10000) + (minor * 1000) + (revision)))
  103. #else
  104. #define SIMDE_DETECT_CLANG_VERSION_CHECK(major, minor, revision) (0)
  105. #define SIMDE_DETECT_CLANG_VERSION_NOT(major, minor, revision) (1)
  106. #endif
  107. #endif /* !defined(SIMDE_DETECT_CLANG_H) */