[PATCH] D32949: [Lexer] Make __has_extension ignore -pedantic-errors inside system headers

Eric Fiselier via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Sat May 6 17:17:56 PDT 2017


EricWF created this revision.

Libc++ needs to be able to detect and use certain language extensions inside the STL headers. However `__has_extension` currently return `0` when `-pedantic-errors` is specified. However libc++ can still safely use these extensions since `-pedantic-errors` is ignored within system headers.

This patch make `__has_extension` ignore `-pedantic-errors` when the expansion occurs in a system header.


https://reviews.llvm.org/D32949

Files:
  docs/LanguageExtensions.rst
  lib/Lex/PPMacroExpansion.cpp
  test/Lexer/has_extension_system_header.cpp
  test/Lexer/has_extension_system_header.h


Index: test/Lexer/has_extension_system_header.h
===================================================================
--- /dev/null
+++ test/Lexer/has_extension_system_header.h
@@ -0,0 +1,13 @@
+#pragma once
+
+static_assert(__has_extension(cxx_init_captures) == !Pedantic, "");
+static_assert(MY_HAS_EXT(cxx_init_captures) == !Pedantic, "");
+
+#pragma clang system_header
+
+// Test expansions from macros defined in system headers and used elsewhere.
+#define SYSTEM_HAS_EXT(ID) __has_extension(ID)
+
+static_assert(__has_extension(cxx_init_captures), "");
+static_assert(SYSTEM_HAS_EXT(cxx_init_captures), "");
+static_assert(MY_HAS_EXT(cxx_init_captures), "");
Index: test/Lexer/has_extension_system_header.cpp
===================================================================
--- /dev/null
+++ test/Lexer/has_extension_system_header.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only  %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -pedantic-errors -DIS_PEDANTIC %s
+
+#ifdef IS_PEDANTIC
+constexpr bool Pedantic = true;
+#else
+constexpr bool Pedantic = false;
+#endif
+
+// Test expansions from macros defined outside of system headers
+#define MY_HAS_EXT(ID) __has_extension(ID)
+
+#include "has_extension_system_header.h"
+
+static_assert(__has_extension(cxx_init_captures) == !Pedantic, "");
+static_assert(SYSTEM_HAS_EXT(cxx_init_captures) == !Pedantic, "");
+static_assert(MY_HAS_EXT(cxx_init_captures) == !Pedantic, "");
Index: lib/Lex/PPMacroExpansion.cpp
===================================================================
--- lib/Lex/PPMacroExpansion.cpp
+++ lib/Lex/PPMacroExpansion.cpp
@@ -1271,14 +1271,15 @@
 /// HasExtension - Return true if we recognize and implement the feature
 /// specified by the identifier, either as an extension or a standard language
 /// feature.
-static bool HasExtension(const Preprocessor &PP, StringRef Extension) {
+static bool HasExtension(const Preprocessor &PP, StringRef Extension,
+                         bool IsInSystemHeader) {
   if (HasFeature(PP, Extension))
     return true;
 
   // If the use of an extension results in an error diagnostic, extensions are
   // effectively unavailable, so just return false here.
   if (PP.getDiagnostics().getExtensionHandlingBehavior() >=
-      diag::Severity::Error)
+      diag::Severity::Error && !IsInSystemHeader)
     return false;
 
   const LangOptions &LangOpts = PP.getLangOpts();
@@ -1730,7 +1731,9 @@
       [this](Token &Tok, bool &HasLexedNextToken) -> int {
         IdentifierInfo *II = ExpectFeatureIdentifierInfo(Tok, *this,
                                            diag::err_feature_check_malformed);
-        return II && HasExtension(*this, II->getName());
+        if (!II) return false;
+        bool IsInSystemHeader = SourceMgr.isInSystemHeader(Tok.getLocation());
+        return HasExtension(*this, II->getName(), IsInSystemHeader);
       });
   } else if (II == Ident__has_builtin) {
     EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this,
Index: docs/LanguageExtensions.rst
===================================================================
--- docs/LanguageExtensions.rst
+++ docs/LanguageExtensions.rst
@@ -89,6 +89,9 @@
   // language extension in C++98.
   #endif
 
+Note that Clang may need to change the language extensions it offers, including
+removing extensions completely.
+
 .. _langext-has-feature-back-compat:
 
 For backward compatibility, ``__has_feature`` can also be used to test
@@ -100,7 +103,8 @@
 <AddressSanitizer>`.
 
 If the ``-pedantic-errors`` option is given, ``__has_extension`` is equivalent
-to ``__has_feature``.
+to ``__has_feature`` unless the expansion is within a system header in which
+case ``-pedantic-errors`` has no effect.
 
 The feature tag is described along with the language feature below.
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D32949.98085.patch
Type: text/x-patch
Size: 3796 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170507/342c4675/attachment.bin>


More information about the cfe-commits mailing list