aboutsummaryrefslogtreecommitdiff
path: root/utils/TableGen/ClangAttrEmitter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/TableGen/ClangAttrEmitter.cpp')
-rw-r--r--utils/TableGen/ClangAttrEmitter.cpp161
1 files changed, 140 insertions, 21 deletions
diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp
index ef618cea4e..b873636b4a 100644
--- a/utils/TableGen/ClangAttrEmitter.cpp
+++ b/utils/TableGen/ClangAttrEmitter.cpp
@@ -735,6 +735,82 @@ static void writeAvailabilityValue(raw_ostream &OS) {
<< " OS << \"";
}
+static void writePrettyPrintFunction(Record &R, std::vector<Argument*> &Args,
+ raw_ostream &OS) {
+ std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings");
+
+ OS << "void " << R.getName() << "Attr::printPretty("
+ << "raw_ostream &OS, const PrintingPolicy &Policy) const {\n";
+
+ if (Spellings.size() == 0) {
+ OS << "}\n\n";
+ return;
+ }
+
+ OS <<
+ " switch (SpellingListIndex) {\n"
+ " default:\n"
+ " llvm_unreachable(\"Unknown attribute spelling!\");\n"
+ " break;\n";
+
+ for (unsigned I = 0; I < Spellings.size(); ++ I) {
+ llvm::SmallString<16> Prefix;
+ llvm::SmallString<8> Suffix;
+ // The actual spelling of the name and namespace (if applicable)
+ // of an attribute without considering prefix and suffix.
+ llvm::SmallString<64> Spelling;
+ std::string Name = Spellings[I]->getValueAsString("Name");
+ std::string Variety = Spellings[I]->getValueAsString("Variety");
+
+ if (Variety == "GNU") {
+ Prefix = " __attribute__((";
+ Suffix = "))";
+ } else if (Variety == "CXX11") {
+ Prefix = " [[";
+ Suffix = "]]";
+ std::string Namespace = Spellings[I]->getValueAsString("Namespace");
+ if (Namespace != "") {
+ Spelling += Namespace;
+ Spelling += "::";
+ }
+ } else if (Variety == "Declspec") {
+ Prefix = " __declspec(";
+ Suffix = ")";
+ } else {
+ llvm_unreachable("Unkown attribute syntax variety!");
+ }
+
+ Spelling += Name;
+
+ OS <<
+ " case " << I << " : {\n"
+ " OS << \"" + Prefix.str() + Spelling.str();
+
+ if (Args.size()) OS << "(";
+ if (Spelling == "availability") {
+ writeAvailabilityValue(OS);
+ } else {
+ for (std::vector<Argument*>::const_iterator I = Args.begin(),
+ E = Args.end(); I != E; ++ I) {
+ if (I != Args.begin()) OS << ", ";
+ (*I)->writeValue(OS);
+ }
+ }
+
+ if (Args.size()) OS << ")";
+ OS << Suffix.str() + "\";\n";
+
+ OS <<
+ " break;\n"
+ " }\n";
+ }
+
+ // End of the switch statement.
+ OS << "}\n";
+ // End of the print function.
+ OS << "}\n\n";
+}
+
namespace clang {
// Emits the class definitions for attributes.
@@ -783,9 +859,12 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
(*ai)->writeCtorParameters(OS);
OS << "\n";
}
-
+
+ OS << " , ";
+ OS << "unsigned SI = 0\n";
+
OS << " )\n";
- OS << " : " << SuperName << "(attr::" << R.getName() << ", R)\n";
+ OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n";
for (ai = Args.begin(); ai != ae; ++ai) {
OS << " , ";
@@ -841,7 +920,6 @@ void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
continue;
std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
- std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings");
std::vector<Argument*> Args;
for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri)
Args.push_back(createArgument(**ri, R.getName()));
@@ -858,24 +936,7 @@ void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
}
OS << ");\n}\n\n";
- OS << "void " << R.getName() << "Attr::printPretty("
- << "raw_ostream &OS, const PrintingPolicy &Policy) const {\n";
- if (Spellings.begin() != Spellings.end()) {
- std::string Spelling = (*Spellings.begin())->getValueAsString("Name");
- OS << " OS << \" __attribute__((" << Spelling;
- if (Args.size()) OS << "(";
- if (Spelling == "availability") {
- writeAvailabilityValue(OS);
- } else {
- for (ai = Args.begin(); ai != ae; ++ai) {
- if (ai!=Args.begin()) OS <<", ";
- (*ai)->writeValue(OS);
- }
- }
- if (Args.size()) OS << ")";
- OS << "))\";\n";
- }
- OS << "}\n\n";
+ writePrettyPrintFunction(R, Args, OS);
}
}
@@ -1044,6 +1105,64 @@ void EmitClangAttrSpellingList(RecordKeeper &Records, raw_ostream &OS) {
}
+void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) {
+ OS << "// This file is generated by TableGen. Do not edit it. \n\n";
+
+ OS <<
+ " unsigned Index = 0;\n"
+ " switch (AttrKind) {\n"
+ " default:\n"
+ " llvm_unreachable(\"Unknown attribute kind!\");\n"
+ " break;\n";
+
+ std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
+ for (std::vector<Record*>::const_iterator I = Attrs.begin(), E = Attrs.end();
+ I != E; ++I) {
+ Record &R = **I;
+ // We only care about attributes that participate in Sema checking, so
+ // skip those attributes that are not able to make their way to Sema.
+ if (!R.getValueAsBit("SemaHandler"))
+ continue;
+
+ std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings");
+ // Each distinct spelling yields an attribute kind.
+ if (R.getValueAsBit("DistinctSpellings")) {
+ for (unsigned I = 0; I < Spellings.size(); ++ I) {
+ OS <<
+ " case AT_" << Spellings[I]->getValueAsString("Name") << ": \n"
+ " Index = " << I << ";\n"
+ " break;\n";
+ }
+ } else {
+ OS << " case AT_" << R.getName() << " : {\n";
+ for (unsigned I = 0; I < Spellings.size(); ++ I) {
+ SmallString<16> Namespace;
+ if (Spellings[I]->getValueAsString("Variety") == "CXX11")
+ Namespace = Spellings[I]->getValueAsString("Namespace");
+ else
+ Namespace = "";
+
+ OS << " if (Name == \""
+ << Spellings[I]->getValueAsString("Name") << "\" && "
+ << "SyntaxUsed == "
+ << StringSwitch<unsigned>(Spellings[I]->getValueAsString("Variety"))
+ .Case("GNU", 0)
+ .Case("CXX11", 1)
+ .Case("Declspec", 2)
+ .Default(0)
+ << " && Scope == \"" << Namespace << "\")\n"
+ << " return " << I << ";\n";
+ }
+
+ OS << " break;\n";
+ OS << " }\n";
+ }
+ }
+
+ OS << " }\n";
+ OS << " return Index;\n";
+}
+
// Emits the LateParsed property for attributes.
void EmitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS) {
OS << "// This file is generated by TableGen. Do not edit.\n\n";