This revision was automatically updated to reflect the committed changes.
Closed by commit rL341097: Improve attribute documentation to list which 
spellings are used in which… (authored by rsmith, committed by ).
Herald added a subscriber: llvm-commits.

Repository:
  rL LLVM

https://reviews.llvm.org/D51473

Files:
  cfe/trunk/include/clang/Basic/AttrDocs.td
  cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp

Index: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
===================================================================
--- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
+++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
@@ -3747,18 +3747,66 @@
   getPragmaAttributeSupport(Records).generateParsingHelpers(OS);
 }
 
+enum class SpellingKind {
+  GNU,
+  CXX11,
+  C2x,
+  Declspec,
+  Microsoft,
+  Keyword,
+  Pragma,
+};
+static const size_t NumSpellingKinds = (size_t)SpellingKind::Pragma + 1;
+
+class SpellingList {
+  std::vector<std::string> Spellings[NumSpellingKinds];
+
+public:
+  ArrayRef<std::string> operator[](SpellingKind K) const {
+    return Spellings[(size_t)K];
+  }
+
+  void add(const Record &Attr, FlattenedSpelling Spelling) {
+    SpellingKind Kind = StringSwitch<SpellingKind>(Spelling.variety())
+                            .Case("GNU", SpellingKind::GNU)
+                            .Case("CXX11", SpellingKind::CXX11)
+                            .Case("C2x", SpellingKind::C2x)
+                            .Case("Declspec", SpellingKind::Declspec)
+                            .Case("Microsoft", SpellingKind::Microsoft)
+                            .Case("Keyword", SpellingKind::Keyword)
+                            .Case("Pragma", SpellingKind::Pragma);
+    std::string Name;
+    if (!Spelling.nameSpace().empty()) {
+      switch (Kind) {
+      case SpellingKind::CXX11:
+      case SpellingKind::C2x:
+        Name = Spelling.nameSpace() + "::";
+        break;
+      case SpellingKind::Pragma:
+        Name = Spelling.nameSpace() + " ";
+        break;
+      default:
+        PrintFatalError(Attr.getLoc(), "Unexpected namespace in spelling");
+      }
+    }
+    Name += Spelling.name();
+
+    Spellings[(size_t)Kind].push_back(Name);
+  }
+};
+
 class DocumentationData {
 public:
   const Record *Documentation;
   const Record *Attribute;
   std::string Heading;
-  unsigned SupportedSpellings;
+  SpellingList SupportedSpellings;
 
   DocumentationData(const Record &Documentation, const Record &Attribute,
-                    const std::pair<std::string, unsigned> HeadingAndKinds)
+                    std::pair<std::string, SpellingList> HeadingAndSpellings)
       : Documentation(&Documentation), Attribute(&Attribute),
-        Heading(std::move(HeadingAndKinds.first)),
-        SupportedSpellings(HeadingAndKinds.second) {}
+        Heading(std::move(HeadingAndSpellings.first)),
+        SupportedSpellings(std::move(HeadingAndSpellings.second)) {}
 };
 
 static void WriteCategoryHeader(const Record *DocCategory,
@@ -3774,28 +3822,21 @@
   OS << "\n\n";
 }
 
-enum SpellingKind {
-  GNU = 1 << 0,
-  CXX11 = 1 << 1,
-  C2x = 1 << 2,
-  Declspec = 1 << 3,
-  Microsoft = 1 << 4,
-  Keyword = 1 << 5,
-  Pragma = 1 << 6
-};
-
-static std::pair<std::string, unsigned>
-GetAttributeHeadingAndSpellingKinds(const Record &Documentation,
-                                    const Record &Attribute) {
+static std::pair<std::string, SpellingList>
+GetAttributeHeadingAndSpellings(const Record &Documentation,
+                                const Record &Attribute) {
   // FIXME: there is no way to have a per-spelling category for the attribute
   // documentation. This may not be a limiting factor since the spellings
   // should generally be consistently applied across the category.
 
   std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attribute);
+  if (Spellings.empty())
+    PrintFatalError(Attribute.getLoc(),
+                    "Attribute has no supported spellings; cannot be "
+                    "documented");
 
   // Determine the heading to be used for this attribute.
   std::string Heading = Documentation.getValueAsString("Heading");
-  bool CustomHeading = !Heading.empty();
   if (Heading.empty()) {
     // If there's only one spelling, we can simply use that.
     if (Spellings.size() == 1)
@@ -3819,76 +3860,42 @@
     PrintFatalError(Attribute.getLoc(),
                     "This attribute requires a heading to be specified");
 
-  // Gather a list of unique spellings; this is not the same as the semantic
-  // spelling for the attribute. Variations in underscores and other non-
-  // semantic characters are still acceptable.
-  std::vector<std::string> Names;
-
-  unsigned SupportedSpellings = 0;
-  for (const auto &I : Spellings) {
-    SpellingKind Kind = StringSwitch<SpellingKind>(I.variety())
-                            .Case("GNU", GNU)
-                            .Case("CXX11", CXX11)
-                            .Case("C2x", C2x)
-                            .Case("Declspec", Declspec)
-                            .Case("Microsoft", Microsoft)
-                            .Case("Keyword", Keyword)
-                            .Case("Pragma", Pragma);
-
-    // Mask in the supported spelling.
-    SupportedSpellings |= Kind;
+  SpellingList SupportedSpellings;
+  for (const auto &I : Spellings)
+    SupportedSpellings.add(Attribute, I);
 
-    std::string Name;
-    if ((Kind == CXX11 || Kind == C2x) && !I.nameSpace().empty())
-      Name = I.nameSpace() + "::";
-    Name += I.name();
-
-    // If this name is the same as the heading, do not add it.
-    if (Name != Heading)
-      Names.push_back(Name);
-  }
-
-  // Print out the heading for the attribute. If there are alternate spellings,
-  // then display those after the heading.
-  if (!CustomHeading && !Names.empty()) {
-    Heading += " (";
-    for (auto I = Names.begin(), E = Names.end(); I != E; ++I) {
-      if (I != Names.begin())
-        Heading += ", ";
-      Heading += *I;
-    }
-    Heading += ")";
-  }
-  if (!SupportedSpellings)
-    PrintFatalError(Attribute.getLoc(),
-                    "Attribute has no supported spellings; cannot be "
-                    "documented");
-  return std::make_pair(std::move(Heading), SupportedSpellings);
+  return std::make_pair(std::move(Heading), std::move(SupportedSpellings));
 }
 
 static void WriteDocumentation(RecordKeeper &Records,
                                const DocumentationData &Doc, raw_ostream &OS) {
   OS << Doc.Heading << "\n" << std::string(Doc.Heading.length(), '-') << "\n";
 
   // List what spelling syntaxes the attribute supports.
   OS << ".. csv-table:: Supported Syntaxes\n";
-  OS << "   :header: \"GNU\", \"C++11\", \"C2x\", \"__declspec\", \"Keyword\",";
-  OS << " \"Pragma\", \"Pragma clang attribute\"\n\n";
+  OS << "   :header: \"GNU\", \"C++11\", \"C2x\", \"``__declspec``\",";
+  OS << " \"Keyword\", \"``#pragma``\", \"``#pragma clang attribute``\"\n\n";
   OS << "   \"";
-  if (Doc.SupportedSpellings & GNU) OS << "X";
-  OS << "\",\"";
-  if (Doc.SupportedSpellings & CXX11) OS << "X";
-  OS << "\",\"";
-  if (Doc.SupportedSpellings & C2x) OS << "X";
-  OS << "\",\"";
-  if (Doc.SupportedSpellings & Declspec) OS << "X";
-  OS << "\",\"";
-  if (Doc.SupportedSpellings & Keyword) OS << "X";
-  OS << "\", \"";
-  if (Doc.SupportedSpellings & Pragma) OS << "X";
-  OS << "\", \"";
-  if (getPragmaAttributeSupport(Records).isAttributedSupported(*Doc.Attribute))
-    OS << "X";
+  for (size_t Kind = 0; Kind != NumSpellingKinds; ++Kind) {
+    SpellingKind K = (SpellingKind)Kind;
+    // FIXME: Why are Microsoft spellings not listed?
+    if (K == SpellingKind::Microsoft)
+      continue;
+
+    bool PrintedAny = false;
+    for (StringRef Spelling : Doc.SupportedSpellings[K]) {
+      if (PrintedAny)
+        OS << " |br| ";
+      OS << "``" << Spelling << "``";
+      PrintedAny = true;
+    }
+
+    OS << "\",\"";
+  }
+
+  if (getPragmaAttributeSupport(Records).isAttributedSupported(
+          *Doc.Attribute))
+    OS << "Yes";
   OS << "\"\n\n";
 
   // If the attribute is deprecated, print a message about it, and possibly
@@ -3944,7 +3951,7 @@
 
       if (!Undocumented)
         SplitDocs[Category].push_back(DocumentationData(
-            Doc, Attr, GetAttributeHeadingAndSpellingKinds(Doc, Attr)));
+            Doc, Attr, GetAttributeHeadingAndSpellings(Doc, Attr)));
     }
   }
 
Index: cfe/trunk/include/clang/Basic/AttrDocs.td
===================================================================
--- cfe/trunk/include/clang/Basic/AttrDocs.td
+++ cfe/trunk/include/clang/Basic/AttrDocs.td
@@ -38,6 +38,10 @@
 .. contents::
    :local:
 
+.. |br| raw:: html
+
+  <br/>
+
 Introduction
 ============
 
@@ -51,7 +55,7 @@
 The ``section`` attribute allows you to specify a specific section a
 global variable or function should be in after translation.
   }];
-  let Heading = "section (gnu::section, __declspec(allocate))";
+  let Heading = "section, __declspec(allocate)";
 }
 
 def InitSegDocs : Documentation {
@@ -270,24 +274,24 @@
 
 def AssertCapabilityDocs : Documentation {
   let Category = DocCatFunction;
-  let Heading = "assert_capability (assert_shared_capability, clang::assert_capability, clang::assert_shared_capability)";
+  let Heading = "assert_capability, assert_shared_capability";
   let Content = [{
 Marks a function that dynamically tests whether a capability is held, and halts
 the program if it is not held.
   }];
 }
 
 def AcquireCapabilityDocs : Documentation {
   let Category = DocCatFunction;
-  let Heading = "acquire_capability (acquire_shared_capability, clang::acquire_capability, clang::acquire_shared_capability)";
+  let Heading = "acquire_capability, acquire_shared_capability";
   let Content = [{
 Marks a function as acquiring a capability.
   }];
 }
 
 def TryAcquireCapabilityDocs : Documentation {
   let Category = DocCatFunction;
-  let Heading = "try_acquire_capability (try_acquire_shared_capability, clang::try_acquire_capability, clang::try_acquire_shared_capability)";
+  let Heading = "try_acquire_capability, try_acquire_shared_capability";
   let Content = [{
 Marks a function that attempts to acquire a capability. This function may fail to
 actually acquire the capability; they accept a Boolean value determining
@@ -298,7 +302,7 @@
 
 def ReleaseCapabilityDocs : Documentation {
   let Category = DocCatFunction;
-  let Heading = "release_capability (release_shared_capability, clang::release_capability, clang::release_shared_capability)";
+  let Heading = "release_capability, release_shared_capability";
   let Content = [{
 Marks a function as releasing a capability.
   }];
@@ -1261,7 +1265,7 @@
 
 def WarnMaybeUnusedDocs : Documentation {
   let Category = DocCatVariable;
-  let Heading = "maybe_unused, unused, gnu::unused";
+  let Heading = "maybe_unused, unused";
   let Content = [{
 When passing the ``-Wunused`` flag to Clang, entities that are unused by the
 program may be diagnosed. The ``[[maybe_unused]]`` (or
@@ -1287,7 +1291,7 @@
 
 def WarnUnusedResultsDocs : Documentation {
   let Category = DocCatFunction;
-  let Heading = "nodiscard, warn_unused_result, clang::warn_unused_result, gnu::warn_unused_result";
+  let Heading = "nodiscard, warn_unused_result";
   let Content  = [{
 Clang supports the ability to diagnose when the results of a function call
 expression are discarded under suspicious circumstances. A diagnostic is
@@ -1312,7 +1316,7 @@
 
 def FallthroughDocs : Documentation {
   let Category = DocCatStmt;
-  let Heading = "fallthrough, clang::fallthrough";
+  let Heading = "fallthrough";
   let Content = [{
 The ``fallthrough`` (or ``clang::fallthrough``) attribute is used
 to annotate intentional fall-through
@@ -1460,7 +1464,7 @@
 
 def MipsLongCallStyleDocs : Documentation {
   let Category = DocCatFunction;
-  let Heading = "long_call (gnu::long_call, gnu::far)";
+  let Heading = "long_call, far";
   let Content = [{
 Clang supports the ``__attribute__((long_call))``, ``__attribute__((far))``,
 and ``__attribute__((near))`` attributes on MIPS targets. These attributes may
@@ -1481,7 +1485,7 @@
 
 def MipsShortCallStyleDocs : Documentation {
   let Category = DocCatFunction;
-  let Heading = "short_call (gnu::short_call, gnu::near)";
+  let Heading = "short_call, near";
   let Content = [{
 Clang supports the ``__attribute__((long_call))``, ``__attribute__((far))``,
 ``__attribute__((short__call))``, and ``__attribute__((near))`` attributes
@@ -1940,7 +1944,7 @@
   let Category = DocCatFunction;
   // This function has multiple distinct spellings, and so it requires a custom
   // heading to be specified. The most common spelling is sufficient.
-  let Heading = "no_sanitize_address (no_address_safety_analysis, gnu::no_address_safety_analysis, gnu::no_sanitize_address)";
+  let Heading = "no_sanitize_address, no_address_safety_analysis";
   let Content = [{
 .. _langext-address_sanitizer:
 
@@ -2563,7 +2567,6 @@
 
 def OpenCLUnrollHintDocs : Documentation {
   let Category = DocCatStmt;
-  let Heading = "__attribute__((opencl_unroll_hint))";
   let Content = [{
 The opencl_unroll_hint attribute qualifier can be used to specify that a loop
 (for, while and do loops) can be unrolled. This attribute qualifier can be
@@ -2576,7 +2579,6 @@
 
 def OpenCLIntelReqdSubGroupSizeDocs : Documentation {
   let Category = DocCatStmt;
-  let Heading = "__attribute__((intel_reqd_sub_group_size))";
   let Content = [{
 The optional attribute intel_reqd_sub_group_size can be used to indicate that
 the kernel must be compiled and executed with the specified subgroup size. When
@@ -3396,7 +3398,7 @@
 
 def XRayDocs : Documentation {
   let Category = DocCatFunction;
-  let Heading = "xray_always_instrument (clang::xray_always_instrument), xray_never_instrument (clang::xray_never_instrument), xray_log_args (clang::xray_log_args)";
+  let Heading = "xray_always_instrument, xray_never_instrument, xray_log_args";
   let Content = [{
 ``__attribute__((xray_always_instrument))`` or ``[[clang::xray_always_instrument]]`` is used to mark member functions (in C++), methods (in Objective C), and free functions (in C, C++, and Objective C) to be instrumented with XRay. This will cause the function to always have space at the beginning and exit points to allow for runtime patching.
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D51473: I... Richard Smith - zygoloid via Phabricator via cfe-commits
    • [PATCH] D514... Aaron Ballman via Phabricator via cfe-commits
    • [PATCH] D514... Richard Smith - zygoloid via Phabricator via cfe-commits
    • [PATCH] D514... Richard Smith - zygoloid via Phabricator via cfe-commits
      • Re: [PAT... Aaron Ballman via cfe-commits
        • Re: ... Richard Smith via cfe-commits
          • ... Aaron Ballman via cfe-commits

Reply via email to