Overview

Artifact ID: 9711899e2fb6c4df269031eb0237e0b3622f8f7c20f478912acb8cf597bb40ac
Ticket: f245681931009283f80ed29241d0e31313f97115
clang: Feature detection via has_feature vs has_extension
User & Date: luismachuca 2019-08-16 18:19:16
Changes

  1. foundin changed to: "all"
  2. icomment:
    At present, supported features in Clang are detected via <tt>__has_extension</tt> in config/clang.hpp , unlike in other compilers such as GCC where they are detected via parsing of the reported values of <tt>__cplusplus</tt> and the compiler's version number. 
    
    This is one of two ways of detecting features in Clang:
    
    <blockquote>
    <b><tt>__has_feature</tt> and <tt>__has_extension</tt></b><br/>
    <br/>
    
    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. 
    </blockquote>
    
    (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 <tt>explicit_cast</tt>, which with all versions up to <tt>CXXOMFORT_DATE == 20190215</tt> will generate the following warnings in Clang++ 3.x and 4.x:
    
    <verbatim>
    /usr/local/include/cxxomfort/impl/17-byte.hpp:156:2: warning: explicit conversion functions are a C++11 extension [-Wc++11-extensions]
    </verbatim>
    
    And the <tt>explicit_cast</tt> example in cxxomfort-examples errors out with messages such as the following, apparently due to setting up "<tt>explicit_cast</tt>" to be "<tt>static_cast</tt>", which doesn't have the same semantics in C++03:
    
    <verbatim>
    explicit_cast.cpp:70:12: error: no matching conversion for static_cast from 'myfoo' to 'mybar'
        dobar( explicit_cast<mybar>(foo2)); // <-- should work
    </verbatim>
    
    Other cxxomfort features might be also affected. Most likely: <tt>enum class</tt> emulation, local function emulation and stuff in <tt><functional></tt>.
    
    <hr/>
    
    Proposed solutions:
    
    <ul><li> Detection should take place using <tt>__has_feature</tt> for all Standard features, and library code should opt-in accordingly.
    </li><li> Detection should take place using <tt>__has_extension</tt> for all Standard extensions, and library code should opt-out accordingly.
    </li><li> Detection should take place either of the two on a per-feature basis, left to the user with a sensible default of <tt>__has_feature</tt>.
    </li> </ul>
    
  3. login: "luismachuca"
  4. mimetype: "text/x-fossil-wiki"
  5. severity changed to: "Important"
  6. status changed to: "Open"
  7. title changed to:
    clang: Feature detection via has_feature vs has_extension
    
  8. type changed to: "Code_Defect"