aaron.ballman created this revision.
aaron.ballman added a reviewer: rsmith.
Herald added a subscriber: krytarowski.
aaron.ballman requested review of this revision.

WG14 N2481 was adopted with minor modifications at this week's WG14 meetings. 
The only modification to the paper was to correct the date for the `deprecated` 
attribute to be `201904L` (the corrected date value will be present in WG14 
N2553 when it gets published).

Clang already supported __has_c_attribute, but was missing support for 
returning specific values for the dates when an attribute was adopted while 
waiting to see if WG14 wanted that functionality. Now that WG14 has accepted 
the proposal for C2x, this patch adds the dates from the paper.


https://reviews.llvm.org/D85450

Files:
  clang/include/clang/Basic/Attr.td
  clang/test/Preprocessor/has_c_attribute.c
  clang/utils/TableGen/ClangAttrEmitter.cpp

Index: clang/utils/TableGen/ClangAttrEmitter.cpp
===================================================================
--- clang/utils/TableGen/ClangAttrEmitter.cpp
+++ clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -3064,18 +3064,22 @@
     // attribute version information should be taken from the SD-6 standing
     // document, which can be found at:
     // https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations
+    //
+    // C2x-style attributes have the same kind of version information
+    // associated with them. The unscoped attribute version information should
+    // be taken from the specification of the attribute in the C Standard.
     int Version = 1;
 
-    if (Variety == "CXX11") {
-        std::vector<Record *> Spellings = Attr->getValueAsListOfDefs("Spellings");
-        for (const auto &Spelling : Spellings) {
-          if (Spelling->getValueAsString("Variety") == "CXX11") {
-            Version = static_cast<int>(Spelling->getValueAsInt("Version"));
-            if (Scope.empty() && Version == 1)
-              PrintError(Spelling->getLoc(), "C++ standard attributes must "
-              "have valid version information.");
-            break;
-          }
+    if (Variety == "CXX11" || Variety == "C2x") {
+      std::vector<Record *> Spellings = Attr->getValueAsListOfDefs("Spellings");
+      for (const auto &Spelling : Spellings) {
+        if (Spelling->getValueAsString("Variety") == Variety) {
+          Version = static_cast<int>(Spelling->getValueAsInt("Version"));
+          if (Scope.empty() && Version == 1)
+            PrintError(Spelling->getLoc(), "Standard attributes must have "
+                                           "valid version information.");
+          break;
+        }
       }
     }
 
Index: clang/test/Preprocessor/has_c_attribute.c
===================================================================
--- clang/test/Preprocessor/has_c_attribute.c
+++ clang/test/Preprocessor/has_c_attribute.c
@@ -1,22 +1,44 @@
-// RUN: %clang_cc1 -fdouble-square-bracket-attributes -std=c11 -E %s -o - | FileCheck %s
-// RUN: %clang_cc1 -std=c2x -E %s -o - | FileCheck %s
-
-// CHECK: has_fallthrough
-#if __has_c_attribute(fallthrough)
-  int has_fallthrough();
-#endif
-
-// CHECK: does_not_have_selectany
-#if !__has_c_attribute(selectany)
-  int does_not_have_selectany();
-#endif
-
-// CHECK: has_nodiscard_underscore
-#if __has_c_attribute(__nodiscard__)
-  int has_nodiscard_underscore();
-#endif
-
-// CHECK: has_clang_annotate
-#if __has_c_attribute(clang::annotate)
-  int has_clang_annotate();
-#endif
+// RUN: %clang_cc1 -fdouble-square-bracket-attributes -std=c11 -E -P %s -o - | FileCheck %s
+// RUN: %clang_cc1 -std=c2x -E -P %s -o - | FileCheck %s
+
+#define C2x(x) x: __has_c_attribute(x)
+
+// CHECK: fallthrough: 201904L
+C2x(fallthrough)
+
+// CHECK: __nodiscard__: 201904L
+C2x(__nodiscard__)
+
+// CHECK: selectany: 0
+C2x(selectany); // Known attribute not supported in C mode
+
+// CHECK: frobble: 0
+C2x(frobble) // Unknown attribute
+
+// CHECK: frobble::frobble: 0
+C2x(frobble::frobble) // Unknown vendor namespace
+
+// CHECK: clang::annotate: 1
+C2x(clang::annotate)
+
+// CHECK: deprecated: 201904L
+C2x(deprecated)
+
+// CHECK: maybe_unused: 201904L
+C2x(maybe_unused)
+
+// CHECK: __gnu__::warn_unused_result: 201904L
+C2x(__gnu__::warn_unused_result)
+
+// CHECK: gnu::__warn_unused_result__: 201904L
+C2x(gnu::__warn_unused_result__)
+
+// 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_c_attribute for that
+// vendor namespace.
+//
+// Note, we can't use C2x here because it will expand __clang__ to 1
+// too early.
+// CHECK: 1::fallthrough: 0
+__clang__::fallthrough: __has_c_attribute(__clang__::fallthrough)
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -267,8 +267,10 @@
   string Namespace = namespace;
   int Version = version;
 }
-class C2x<string namespace, string name> : Spelling<name, "C2x"> {
+class C2x<string namespace, string name, int version = 1>
+    : Spelling<name, "C2x"> {
   string Namespace = namespace;
+  int Version = version;
 }
 
 class Keyword<string name> : Spelling<name, "Keyword">;
@@ -1221,7 +1223,8 @@
 
 def Deprecated : InheritableAttr {
   let Spellings = [GCC<"deprecated">, Declspec<"deprecated">,
-                   CXX11<"","deprecated", 201309>, C2x<"", "deprecated">];
+                   CXX11<"","deprecated", 201309>,
+                   C2x<"", "deprecated", 201904>];
   let Args = [StringArgument<"Message", 1>,
               // An optional string argument that enables us to provide a
               // Fix-It.
@@ -1278,7 +1281,8 @@
 }
 
 def FallThrough : StmtAttr {
-  let Spellings = [CXX11<"", "fallthrough", 201603>, C2x<"", "fallthrough">,
+  let Spellings = [CXX11<"", "fallthrough", 201603>,
+                   C2x<"", "fallthrough", 201904>,
                    CXX11<"clang", "fallthrough">, GCC<"fallthrough">];
 //  let Subjects = [NullStmt];
   let Documentation = [FallthroughDocs];
@@ -2442,7 +2446,7 @@
 
 def Unused : InheritableAttr {
   let Spellings = [CXX11<"", "maybe_unused", 201603>, GCC<"unused">,
-                   C2x<"", "maybe_unused">];
+                   C2x<"", "maybe_unused", 201904>];
   let Subjects = SubjectList<[Var, ObjCIvar, Type, Enum, EnumConstant, Label,
                               Field, ObjCMethod, FunctionLike]>;
   let Documentation = [WarnMaybeUnusedDocs];
@@ -2528,7 +2532,8 @@
 }
 
 def WarnUnusedResult : InheritableAttr {
-  let Spellings = [CXX11<"", "nodiscard", 201907>, C2x<"", "nodiscard">,
+  let Spellings = [CXX11<"", "nodiscard", 201907>,
+                   C2x<"", "nodiscard", 201904>,
                    CXX11<"clang", "warn_unused_result">,
                    GCC<"warn_unused_result">];
   let Subjects = SubjectList<[ObjCMethod, Enum, Record, FunctionLike]>;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to