diff options
Diffstat (limited to 'utils/TableGen/ClangAttrEmitter.cpp')
-rw-r--r-- | utils/TableGen/ClangAttrEmitter.cpp | 161 |
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"; |