8

Apparently, the clang bundled with Xcode doesn't respect the upstream __clang_major__ and __clang_minor__ values, and instead reports an Xcode user-facing version of some sort.

Here are, for reference, the values for the various MacPorts installs of clang. They seem to respect the upstream release identifiers. I get similar values when testing on Linux.

➜  prohibit-clang-3.2  /opt/local/bin/clang++-mp-3.2 -dM -E -x c /dev/null |
grep __clang_m
#define __clang_major__ 3
#define __clang_minor__ 2

➜  prohibit-clang-3.2  /opt/local/bin/clang++-mp-3.3 -dM -E -x c /dev/null |
grep __clang_m
#define __clang_major__ 3
#define __clang_minor__ 3

➜  prohibit-clang-3.2  /opt/local/bin/clang++-mp-3.4 -dM -E -x c /dev/null |
grep __clang_m
#define __clang_major__ 3
#define __clang_minor__ 4

However, for some reason, the Apple provided clang has __clang_major__ and __clang_minor__ versions that track the Xcode version, not the base clang revision:

➜  prohibit-clang-3.2 
/Applications/Xcode-4.6.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++
-dM -E -x c /dev/null | grep __clang_m
#define __clang_major__ 4
#define __clang_minor__ 2

➜  prohibit-clang-3.2 
/Applications/Xcode-4.6.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++
--version
Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)
Target: x86_64-apple-darwin12.5.0
Thread model: posix

➜  prohibit-clang-3.2 
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++
-dM -E -x c /dev/null | grep __clang_m
#define __clang_major__ 5
#define __clang_minor__ 0

➜  prohibit-clang-3.2 
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++
--version
Apple LLVM version 5.0 (clang-500.2.76) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin12.5.0
Thread model: posix

➜  prohibit-clang-3.2  /usr/bin/clang++ -dM -E -x c /dev/null | grep __clang_m
#define __clang_major__ 5
#define __clang_minor__ 0

This seems pretty awful, because it means you can't write conditional compilation lines like the following that will work accurately across both the Apple vendored clang, and clang built normally from the clang sources or from distro packages:

#if !defined(__clang__) || (__clang_major__ > 3) || ((__clang_major__ == 3) && (__clang_minor__ > 2))
// Thing that doesn't work for clang-3.2 due to an optimization bug.
#endif

I'd hate to need to extend that already pretty terrible preprocessor check to account for two different clang versioning schemes, one normal and one Apple. I'm not even sure how I could reliably detect that this is 'Xcode clang' rather than normal clang.

Does anyone have any suggestions on how to work around this? Is there a flag to pass to Apple's clang that will instruct it to report its 'true' version? Or has Apple doomed us to never be able to reliably use __clang_major__ and __clang_minor__? Are these not the macros I should be using here?

Cœur
  • 37,241
  • 25
  • 195
  • 267
acm
  • 12,183
  • 5
  • 39
  • 68

1 Answers1

5

If the feature checking macros don't cover what you need to check for then you do need to treat vendor releases separately as they may have very different content from the open source LLVM releases. You can use __apple_build_version__ to check for a specific Apple LLVM version.

Matt Stevens
  • 13,093
  • 3
  • 33
  • 27
  • Thanks, but unfortunately, the feature checking macros are not sufficient here, since what I'm working around is an LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=15555. Is there some documentation for the values of `__apple_build_version__` and how it maps to XCode revisions somewhere? – acm Oct 15 '13 at 21:50
  • Not that I know of, but it's a numeric representation of the clang version reported by --version so it would lend itself to a range check. The Apple LLVM version is independent of the Xcode version so I'm afraid you'd have to map those numbers yourself. – Matt Stevens Oct 15 '13 at 23:19
  • @acm I didn't try on Linux, but what about `__clang_version__`? – Cœur Mar 07 '18 at 09:30