Ticket Hash: f245681931009283f80ed29241d0e31313f97115
Title: clang: Feature detection via has_feature vs has_extension
Status: Open Type: Code_Defect
Severity: Important Priority: Immediate
Subsystem: Resolution: Open
Last Modified: 2020-02-28 03:52:12
Version Found In: all
User Comments:
luismachuca added on 2019-08-16 18:19:16:

At present, supported features in Clang are detected via __has_extension in config/clang.hpp , unlike in other compilers such as GCC where they are detected via parsing of the reported values of __cplusplus and the compiler's version number.

This is one of two ways of detecting features in Clang:

__has_feature and __has_extension

These function-like macros take a single identifier argument that is the name of a feature. __has_feature evaluates to 1 if the feature is both supported by Clang and standardized in the current language standard or 0 if not (but see below), while __has_extension evaluates to 1 if the feature is supported by Clang in the current language (either as a language extension or a standard language feature) or 0 if not.

(Source: https://releases.llvm.org/4.0.0/tools/clang/docs/LanguageExtensions.html#feature-checking-macros )

This difference in implementation has maybe unintended effects when compiling code using cxxomfort in Clang: code (and the library itself) will detect a certain feature is available despite the Standard not supporting or Emulating it and thus code relying on the implementation of the backport can fail silently or generate undue warnings. One such example is explicit_cast, which with all versions up to CXXOMFORT_DATE == 20190215 will generate the following warnings in Clang++ 3.x and 4.x:

/usr/local/include/cxxomfort/impl/17-byte.hpp:156:2: warning: explicit conversion functions are a C++11 extension [-Wc++11-extensions]

And the explicit_cast example in cxxomfort-examples errors out with messages such as the following, apparently due to setting up "explicit_cast" to be "static_cast", which doesn't have the same semantics in C++03:

explicit_cast.cpp:70:12: error: no matching conversion for static_cast from 'myfoo' to 'mybar'
    dobar( explicit_cast<mybar>(foo2)); // <-- should work

Other cxxomfort features might be also affected. Most likely: enum class emulation, local function emulation and stuff in <functional>.


Proposed solutions:

  • Detection should take place using __has_feature for all Standard features, and library code should opt-in accordingly.
  • Detection should take place using __has_extension for all Standard extensions, and library code should opt-out accordingly.
  • Detection should take place either of the two on a per-feature basis, left to the user with a sensible default of __has_feature.


luismachuca added on 2020-02-28 03:52:12:

[4dad71eb] forces usage of __has_feature in clang to detect explicit operator. This means cxxomfort can not take advantage of explicit operator extension but in exchange gets rid of the warnings in the meantime and the code does not change meaning semantically.

Also theoretically affects [1cbdc0b48d].