r346521 - Introduce the _Clang scoped attribute token.

Aaron Ballman via cfe-commits cfe-commits at lists.llvm.org
Fri Nov 9 09:19:45 PST 2018


Author: aaronballman
Date: Fri Nov  9 09:19:45 2018
New Revision: 346521

URL: http://llvm.org/viewvc/llvm-project?rev=346521&view=rev
Log:
Introduce the _Clang scoped attribute token.

Currently, we only accept clang as the scoped attribute identifier for double square bracket attributes provided by Clang, but this has the potential to conflict with user-defined macros. To help alleviate these concerns, this introduces the _Clang scoped attribute identifier as an alias for clang. It also introduces a warning with a fixit on the off chance someone attempts to use __clang__ as the scoped attribute (which is a predefined compiler identification macro).

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/lib/Basic/Attributes.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Sema/ParsedAttr.cpp
    cfe/trunk/test/FixIt/fixit-cxx11-attributes.cpp
    cfe/trunk/test/Parser/cxx0x-attributes.cpp
    cfe/trunk/test/Preprocessor/has_attribute.cpp
    cfe/trunk/test/SemaCXX/attr-optnone.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=346521&r1=346520&r2=346521&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Fri Nov  9 09:19:45 2018
@@ -575,6 +575,9 @@ def warn_cxx98_compat_noexcept_expr : Wa
 def warn_cxx98_compat_nullptr : Warning<
   "'nullptr' is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore;
 
+def warn_wrong_clang_attr_namespace : Warning<
+  "'__clang__' is a predefined macro name, not an attribute scope specifier; "
+  "did you mean '_Clang' instead?">, InGroup<IgnoredAttributes>;
 def ext_ns_enum_attribute : Extension<
   "attributes on %select{a namespace|an enumerator}0 declaration are "
   "a C++17 extension">, InGroup<CXX17>;

Modified: cfe/trunk/lib/Basic/Attributes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Attributes.cpp?rev=346521&r1=346520&r2=346521&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Attributes.cpp (original)
+++ cfe/trunk/lib/Basic/Attributes.cpp Fri Nov  9 09:19:45 2018
@@ -9,16 +9,18 @@ int clang::hasAttribute(AttrSyntax Synta
                         const LangOptions &LangOpts) {
   StringRef Name = Attr->getName();
   // Normalize the attribute name, __foo__ becomes foo.
-  if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__"))
-    Name = Name.substr(2, Name.size() - 4);
-
-  // Normalize the scope name, but only for gnu attributes.
-  StringRef ScopeName = Scope ? Scope->getName() : "";
-  if (ScopeName == "__gnu__")
-    ScopeName = ScopeName.slice(2, ScopeName.size() - 2);
-
-#include "clang/Basic/AttrHasAttributeImpl.inc"
-
+  if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__"))
+    Name = Name.substr(2, Name.size() - 4);
+
+  // Normalize the scope name, but only for gnu and clang attributes.
+  StringRef ScopeName = Scope ? Scope->getName() : "";
+  if (ScopeName == "__gnu__")
+    ScopeName = "gnu";
+  else if (ScopeName == "_Clang")
+    ScopeName = "clang";
+
+#include "clang/Basic/AttrHasAttributeImpl.inc"
+
   return 0;
 }
 

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=346521&r1=346520&r2=346521&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Fri Nov  9 09:19:45 2018
@@ -3790,6 +3790,28 @@ IdentifierInfo *Parser::TryParseCXX11Att
     }
     return nullptr;
 
+  case tok::numeric_constant: {
+    // If we got a numeric constant, check to see if it comes from a macro that
+    // corresponds to the predefined __clang__ macro. If it does, warn the user
+    // and recover by pretending they said _Clang instead.
+    if (Tok.getLocation().isMacroID()) {
+      SmallString<8> ExpansionBuf;
+      SourceLocation ExpansionLoc =
+          PP.getSourceManager().getExpansionLoc(Tok.getLocation());
+      StringRef Spelling = PP.getSpelling(ExpansionLoc, ExpansionBuf);
+      if (Spelling == "__clang__") {
+        SourceRange TokRange(
+            ExpansionLoc,
+            PP.getSourceManager().getExpansionLoc(Tok.getEndLoc()));
+        Diag(Tok, diag::warn_wrong_clang_attr_namespace)
+            << FixItHint::CreateReplacement(TokRange, "_Clang");
+        Loc = ConsumeToken();
+        return &PP.getIdentifierTable().get("_Clang");
+      }
+    }
+    return nullptr;
+  }
+
   case tok::ampamp:       // 'and'
   case tok::pipe:         // 'bitor'
   case tok::pipepipe:     // 'or'
@@ -3865,24 +3887,22 @@ bool Parser::ParseCXX11AttributeArgs(Ide
     // Eat the left paren, then skip to the ending right paren.
     ConsumeParen();
     SkipUntil(tok::r_paren);
-    return false;
-  }
-
-  if (ScopeName &&
-      (ScopeName->getName() == "gnu" || ScopeName->getName() == "__gnu__")) {
-    // GNU-scoped attributes have some special cases to handle GNU-specific
-    // behaviors.
-    ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
+    return false;
+  }
+
+  if (ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"))) {
+    // GNU-scoped attributes have some special cases to handle GNU-specific
+    // behaviors.
+    ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
                           ScopeLoc, Syntax, nullptr);
     return true;
   }
 
   unsigned NumArgs;
   // Some Clang-scoped attributes have some special parsing behavior.
-  if (ScopeName && ScopeName->getName() == "clang")
-    NumArgs =
-        ParseClangAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
-                                ScopeLoc, Syntax);
+  if (ScopeName && (ScopeName->isStr("clang") || ScopeName->isStr("_Clang")))
+    NumArgs = ParseClangAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc,
+                                      ScopeName, ScopeLoc, Syntax);
   else
     NumArgs =
         ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc,

Modified: cfe/trunk/lib/Sema/ParsedAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/ParsedAttr.cpp?rev=346521&r1=346520&r2=346521&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/ParsedAttr.cpp (original)
+++ cfe/trunk/lib/Sema/ParsedAttr.cpp Fri Nov  9 09:19:45 2018
@@ -105,11 +105,15 @@ void AttributePool::takePool(AttributePo
 
 static StringRef normalizeAttrScopeName(StringRef ScopeName,
                                         ParsedAttr::Syntax SyntaxUsed) {
-  // We currently only normalize the "__gnu__" scope name to be "gnu".
-  if ((SyntaxUsed == ParsedAttr::AS_CXX11 ||
-       SyntaxUsed == ParsedAttr::AS_C2x) &&
-      ScopeName == "__gnu__")
-    ScopeName = ScopeName.slice(2, ScopeName.size() - 2);
+  // Normalize the "__gnu__" scope name to be "gnu" and the "_Clang" scope name
+  // to be "clang".
+  if (SyntaxUsed == ParsedAttr::AS_CXX11 ||
+    SyntaxUsed == ParsedAttr::AS_C2x) {
+    if (ScopeName == "__gnu__")
+      ScopeName = "gnu";
+    else if (ScopeName == "_Clang")
+      ScopeName = "clang";
+  }
   return ScopeName;
 }
 

Modified: cfe/trunk/test/FixIt/fixit-cxx11-attributes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit-cxx11-attributes.cpp?rev=346521&r1=346520&r2=346521&view=diff
==============================================================================
--- cfe/trunk/test/FixIt/fixit-cxx11-attributes.cpp (original)
+++ cfe/trunk/test/FixIt/fixit-cxx11-attributes.cpp Fri Nov  9 09:19:45 2018
@@ -49,3 +49,6 @@ namespace BaseSpecifier {
   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:26-[[@LINE-4]]:26}:"[{{\[}}d]]"
   // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:33-[[@LINE-2]]:39}:""
 }
+
+[[__clang__::annotate("test")]] void annotate3();  // expected-warning {{'__clang__' is a predefined macro name, not an attribute scope specifier; did you mean '_Clang' instead?}}
+// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:12}:"_Clang"

Modified: cfe/trunk/test/Parser/cxx0x-attributes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-attributes.cpp?rev=346521&r1=346520&r2=346521&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx0x-attributes.cpp (original)
+++ cfe/trunk/test/Parser/cxx0x-attributes.cpp Fri Nov  9 09:19:45 2018
@@ -373,3 +373,11 @@ int fallthru(int n) {
 [[attr_name, attr_name_2(bitor), attr_name_3(com, pl)]] int macro_attrs; // expected-warning {{unknown attribute 'compl' ignored}} \
    expected-warning {{unknown attribute 'bitor' ignored}} \
    expected-warning {{unknown attribute 'bitand' ignored}}
+
+// Check that we can parse an attribute in our vendor namespace.
+[[clang::annotate("test")]] void annotate1();
+[[_Clang::annotate("test")]] void annotate2();
+// Note: __clang__ is a predefined macro, which is why _Clang is the
+// prefered "protected" vendor namespace. We support __clang__ only for
+// people expecting it to behave the same as __gnu__.
+[[__clang__::annotate("test")]] void annotate3();  // expected-warning {{'__clang__' is a predefined macro name, not an attribute scope specifier; did you mean '_Clang' instead?}}

Modified: cfe/trunk/test/Preprocessor/has_attribute.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/has_attribute.cpp?rev=346521&r1=346520&r2=346521&view=diff
==============================================================================
--- cfe/trunk/test/Preprocessor/has_attribute.cpp (original)
+++ cfe/trunk/test/Preprocessor/has_attribute.cpp Fri Nov  9 09:19:45 2018
@@ -18,17 +18,33 @@
 // The attribute name can be bracketed with double underscores.
 // CHECK: has_clang_fallthrough_2
 #if __has_cpp_attribute(clang::__fallthrough__)
-  int has_clang_fallthrough_2();
-#endif
-
-// The scope cannot be bracketed with double underscores unless it is for gnu.
-// CHECK: does_not_have___clang___fallthrough
-#if !__has_cpp_attribute(__clang__::fallthrough)
-  int does_not_have___clang___fallthrough();
-#endif
-// CHECK: has_gnu_const
-#if __has_cpp_attribute(__gnu__::__const__)
-  int has_gnu_const();
+  int has_clang_fallthrough_2();
+#endif
+
+// The scope cannot be bracketed with double underscores unless it is
+// for gnu or clang.
+// CHECK: does_not_have___gsl___suppress
+#if !__has_cpp_attribute(__gsl__::suppress)
+  int does_not_have___gsl___suppress();
+#endif
+
+// We do somewhat support the __clang__ vendor namespace, but it is a
+// predefined macro and thus we encourage users to use _Clang instead.
+// Because of this, we do not support __has_cpp_attribute for that
+// vendor namespace.
+// CHECK: does_not_have___clang___fallthrough
+#if !__has_cpp_attribute(__clang__::fallthrough)
+  int does_not_have___clang___fallthrough();
+#endif
+
+// CHECK: does_have_Clang_fallthrough
+#if __has_cpp_attribute(_Clang::fallthrough)
+  int does_have_Clang_fallthrough();
+#endif
+
+// CHECK: has_gnu_const
+#if __has_cpp_attribute(__gnu__::__const__)
+  int has_gnu_const();
 #endif
 
 // Test that C++11, target-specific attributes behave properly.

Modified: cfe/trunk/test/SemaCXX/attr-optnone.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-optnone.cpp?rev=346521&r1=346520&r2=346521&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/attr-optnone.cpp (original)
+++ cfe/trunk/test/SemaCXX/attr-optnone.cpp Fri Nov  9 09:19:45 2018
@@ -71,3 +71,9 @@ struct B2 {
   static void bar();
 };
 
+// Verify that we can handle the [[_Clang::optnone]] and
+// [[__clang__::optnone]] spellings.
+[[_Clang::optnone]] int foo3();
+[[__clang__::optnone]] int foo4(); // expected-warning {{'__clang__' is a predefined macro name, not an attribute scope specifier; did you mean '_Clang' instead?}}
+
+[[_Clang::optnone]] int foo5; // expected-warning {{'optnone' attribute only applies to functions}}




More information about the cfe-commits mailing list