summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorTyler Nowicki <tnowicki@apple.com>2014-06-13 17:57:25 +0000
committerTyler Nowicki <tnowicki@apple.com>2014-06-13 17:57:25 +0000
commitfe84cfe70015f94322e3517b4bf3e5cbf29811d4 (patch)
tree09148b345995c1afd09db49217b82d944351b161 /utils
parentee5a39f2cf1dce6408eea925fab7312572b421f5 (diff)
downloadclang-fe84cfe70015f94322e3517b4bf3e5cbf29811d4.tar.gz
clang-fe84cfe70015f94322e3517b4bf3e5cbf29811d4.tar.bz2
clang-fe84cfe70015f94322e3517b4bf3e5cbf29811d4.tar.xz
Adds a Pragma spelling for attributes to tablegen and makes use of it for loop
hint attributes. Includes tests for pragma printing and for attribute order which is incorrectly reversed by ParsedAttributes. Reviewed by Aaron Ballman git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@210925 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils')
-rw-r--r--utils/TableGen/ClangAttrEmitter.cpp77
1 files changed, 53 insertions, 24 deletions
diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp
index 11c64eac7b..d7ab4fa1b1 100644
--- a/utils/TableGen/ClangAttrEmitter.cpp
+++ b/utils/TableGen/ClangAttrEmitter.cpp
@@ -41,7 +41,7 @@ public:
assert(V != "GCC" && "Given a GCC spelling, which means this hasn't been"
"flattened!");
- if (V == "CXX11")
+ if (V == "CXX11" || V == "Pragma")
NS = Spelling.getValueAsString("Namespace");
bool Unset;
K = Spelling.getValueAsBitOrUnset("KnownToGCC", Unset);
@@ -1055,7 +1055,7 @@ writePrettyPrintFunction(Record &R,
OS << "void " << R.getName() << "Attr::printPretty("
<< "raw_ostream &OS, const PrintingPolicy &Policy) const {\n";
- if (Spellings.size() == 0) {
+ if (Spellings.empty()) {
OS << "}\n\n";
return;
}
@@ -1082,7 +1082,7 @@ writePrettyPrintFunction(Record &R,
Prefix = " [[";
Suffix = "]]";
std::string Namespace = Spellings[I].nameSpace();
- if (Namespace != "") {
+ if (!Namespace.empty()) {
Spelling += Namespace;
Spelling += "::";
}
@@ -1092,6 +1092,14 @@ writePrettyPrintFunction(Record &R,
} else if (Variety == "Keyword") {
Prefix = " ";
Suffix = "";
+ } else if (Variety == "Pragma") {
+ Prefix = "#pragma ";
+ Suffix = "\n";
+ std::string Namespace = Spellings[I].nameSpace();
+ if (!Namespace.empty()) {
+ Spelling += Namespace;
+ Spelling += " ";
+ }
} else {
llvm_unreachable("Unknown attribute syntax variety!");
}
@@ -1102,6 +1110,14 @@ writePrettyPrintFunction(Record &R,
" case " << I << " : {\n"
" OS << \"" + Prefix.str() + Spelling.str();
+ if (Variety == "Pragma") {
+ OS << " \";\n";
+ OS << " printPrettyPragma(OS, Policy);\n";
+ OS << " break;\n";
+ OS << " }\n";
+ continue;
+ }
+
if (!Args.empty())
OS << "(";
if (Spelling == "availability") {
@@ -1782,7 +1798,7 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
// Separate all of the attributes out into four group: generic, C++11, GNU,
// and declspecs. Then generate a big switch statement for each of them.
std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
- std::vector<Record *> Declspec, GNU;
+ std::vector<Record *> Declspec, GNU, Pragma;
std::map<std::string, std::vector<Record *>> CXX;
// Walk over the list of all attributes, and split them out based on the
@@ -1795,9 +1811,10 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
GNU.push_back(R);
else if (Variety == "Declspec")
Declspec.push_back(R);
- else if (Variety == "CXX11") {
+ else if (Variety == "CXX11")
CXX[SI.nameSpace()].push_back(R);
- }
+ else if (Variety == "Pragma")
+ Pragma.push_back(R);
}
}
@@ -1811,6 +1828,9 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
OS << "case AttrSyntax::Declspec:\n";
OS << " return llvm::StringSwitch<bool>(Name)\n";
GenerateHasAttrSpellingStringSwitch(Declspec, OS, "Declspec");
+ OS << "case AttrSyntax::Pragma:\n";
+ OS << " return llvm::StringSwitch<bool>(Name)\n";
+ GenerateHasAttrSpellingStringSwitch(Pragma, OS, "Pragma");
OS << "case AttrSyntax::CXX: {\n";
// C++11-style attributes are further split out based on the Scope.
for (std::map<std::string, std::vector<Record *>>::iterator I = CXX.begin(),
@@ -1846,17 +1866,17 @@ void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) {
std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
OS << " case AT_" << I.first << ": {\n";
for (unsigned I = 0; I < Spellings.size(); ++ I) {
- OS << " if (Name == \""
- << Spellings[I].name() << "\" && "
- << "SyntaxUsed == "
- << StringSwitch<unsigned>(Spellings[I].variety())
- .Case("GNU", 0)
- .Case("CXX11", 1)
- .Case("Declspec", 2)
- .Case("Keyword", 3)
- .Default(0)
- << " && Scope == \"" << Spellings[I].nameSpace() << "\")\n"
- << " return " << I << ";\n";
+ OS << " if (Name == \"" << Spellings[I].name() << "\" && "
+ << "SyntaxUsed == "
+ << StringSwitch<unsigned>(Spellings[I].variety())
+ .Case("GNU", 0)
+ .Case("CXX11", 1)
+ .Case("Declspec", 2)
+ .Case("Keyword", 3)
+ .Case("Pragma", 4)
+ .Default(0)
+ << " && Scope == \"" << Spellings[I].nameSpace() << "\")\n"
+ << " return " << I << ";\n";
}
OS << " break;\n";
@@ -2476,7 +2496,7 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
emitSourceFileHeader("Attribute name matcher", OS);
std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
- std::vector<StringMatcher::StringPair> GNU, Declspec, CXX11, Keywords;
+ std::vector<StringMatcher::StringPair> GNU, Declspec, CXX11, Keywords, Pragma;
std::set<std::string> Seen;
for (const auto *A : Attrs) {
const Record &Attr = *A;
@@ -2519,6 +2539,8 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
Matches = &Declspec;
else if (Variety == "Keyword")
Matches = &Keywords;
+ else if (Variety == "Pragma")
+ Matches = &Pragma;
assert(Matches && "Unsupported spelling variety found");
@@ -2543,6 +2565,8 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
StringMatcher("Name", CXX11, OS).Emit();
OS << " } else if (AttributeList::AS_Keyword == Syntax) {\n";
StringMatcher("Name", Keywords, OS).Emit();
+ OS << " } else if (AttributeList::AS_Pragma == Syntax) {\n";
+ StringMatcher("Name", Pragma, OS).Emit();
OS << " }\n";
OS << " return AttributeList::UnknownAttribute;\n"
<< "}\n";
@@ -2648,7 +2672,8 @@ enum SpellingKind {
GNU = 1 << 0,
CXX11 = 1 << 1,
Declspec = 1 << 2,
- Keyword = 1 << 3
+ Keyword = 1 << 3,
+ Pragma = 1 << 4
};
static void WriteDocumentation(const DocumentationData &Doc,
@@ -2693,10 +2718,11 @@ static void WriteDocumentation(const DocumentationData &Doc,
unsigned SupportedSpellings = 0;
for (const auto &I : Spellings) {
SpellingKind Kind = StringSwitch<SpellingKind>(I.variety())
- .Case("GNU", GNU)
- .Case("CXX11", CXX11)
- .Case("Declspec", Declspec)
- .Case("Keyword", Keyword);
+ .Case("GNU", GNU)
+ .Case("CXX11", CXX11)
+ .Case("Declspec", Declspec)
+ .Case("Keyword", Keyword)
+ .Case("Pragma", Pragma);
// Mask in the supported spelling.
SupportedSpellings |= Kind;
@@ -2731,7 +2757,8 @@ static void WriteDocumentation(const DocumentationData &Doc,
// List what spelling syntaxes the attribute supports.
OS << ".. csv-table:: Supported Syntaxes\n";
- OS << " :header: \"GNU\", \"C++11\", \"__declspec\", \"Keyword\"\n\n";
+ OS << " :header: \"GNU\", \"C++11\", \"__declspec\", \"Keyword\",";
+ OS << " \"Pragma\"\n\n";
OS << " \"";
if (SupportedSpellings & GNU) OS << "X";
OS << "\",\"";
@@ -2741,6 +2768,8 @@ static void WriteDocumentation(const DocumentationData &Doc,
OS << "\",\"";
if (SupportedSpellings & Keyword) OS << "X";
OS << "\"\n\n";
+ if (SupportedSpellings & Pragma) OS << "X";
+ OS << "\"\n\n";
// If the attribute is deprecated, print a message about it, and possibly
// provide a replacement attribute.