r341097 - Improve attribute documentation to list which spellings are used in which syntaxes.
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 30 12:16:33 PDT 2018
Author: rsmith
Date: Thu Aug 30 12:16:33 2018
New Revision: 341097
URL: http://llvm.org/viewvc/llvm-project?rev=341097&view=rev
Log:
Improve attribute documentation to list which spellings are used in which syntaxes.
Summary:
Instead of listing all the spellings (including attribute namespaces) in
the section heading, only list the actual attribute names there, and
list the spellings in the supported syntaxes table.
This allows us to properly describe things like [[fallthrough]], for
which we allow a clang:: prefix in C++ but not in C, and AlwaysInline,
which has one spelling as a GNU attribute and a different spelling as a
keyword, without needing to repeat the syntax description in the
documentation text.
Sample rendering: https://pste.eu/p/T1ZV.html
Reviewers: aaron.ballman
Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D51473
Modified:
cfe/trunk/include/clang/Basic/AttrDocs.td
cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
Modified: cfe/trunk/include/clang/Basic/AttrDocs.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttrDocs.td?rev=341097&r1=341096&r2=341097&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/AttrDocs.td (original)
+++ cfe/trunk/include/clang/Basic/AttrDocs.td Thu Aug 30 12:16:33 2018
@@ -38,6 +38,10 @@ Attributes in Clang
.. contents::
:local:
+.. |br| raw:: html
+
+ <br/>
+
Introduction
============
@@ -51,7 +55,7 @@ def SectionDocs : Documentation {
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,7 +274,7 @@ that appears to be capable of returning
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.
@@ -279,7 +283,7 @@ 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.
}];
@@ -287,7 +291,7 @@ Marks a function as acquiring a capabili
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 @@ the capability means success (false).
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 @@ of silently falling back on dynamic init
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 @@ enumerator, a non-static data member, or
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 @@ potentially-evaluated discarded-value ex
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 @@ on the command line.
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 @@ as ``-mlong-calls`` and ``-mno-long-call
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 @@ def NoSanitizeAddressDocs : Documentatio
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 @@ for further details including limitation
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 @@ s6.11.5 for details.
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 @@ See the RenderScript_ documentation for
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.
Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=341097&r1=341096&r2=341097&view=diff
==============================================================================
--- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)
+++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Thu Aug 30 12:16:33 2018
@@ -3747,18 +3747,66 @@ void EmitClangAttrSubjectMatchRulesParse
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 @@ static void WriteCategoryHeader(const Re
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,51 +3860,11 @@ GetAttributeHeadingAndSpellingKinds(cons
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,
@@ -3872,23 +3873,29 @@ static void WriteDocumentation(RecordKee
// 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 @@ void EmitClangAttrDocs(RecordKeeper &Rec
if (!Undocumented)
SplitDocs[Category].push_back(DocumentationData(
- Doc, Attr, GetAttributeHeadingAndSpellingKinds(Doc, Attr)));
+ Doc, Attr, GetAttributeHeadingAndSpellings(Doc, Attr)));
}
}
More information about the cfe-commits
mailing list