diff options
Diffstat (limited to 'contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp | 136 |
1 files changed, 84 insertions, 52 deletions
diff --git a/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp b/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp index 5dd3f7e..11a766c 100644 --- a/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -28,6 +28,7 @@ using namespace llvm; +namespace { class FlattenedSpelling { std::string V, N, NS; bool K; @@ -53,18 +54,19 @@ public: const std::string &nameSpace() const { return NS; } bool knownToGCC() const { return K; } }; +} // namespace -std::vector<FlattenedSpelling> GetFlattenedSpellings(const Record &Attr) { +static std::vector<FlattenedSpelling> +GetFlattenedSpellings(const Record &Attr) { std::vector<Record *> Spellings = Attr.getValueAsListOfDefs("Spellings"); std::vector<FlattenedSpelling> Ret; for (const auto &Spelling : Spellings) { if (Spelling->getValueAsString("Variety") == "GCC") { // Gin up two new spelling objects to add into the list. - Ret.push_back(FlattenedSpelling("GNU", Spelling->getValueAsString("Name"), - "", true)); - Ret.push_back(FlattenedSpelling( - "CXX11", Spelling->getValueAsString("Name"), "gnu", true)); + Ret.emplace_back("GNU", Spelling->getValueAsString("Name"), "", true); + Ret.emplace_back("CXX11", Spelling->getValueAsString("Name"), "gnu", + true); } else Ret.push_back(FlattenedSpelling(*Spelling)); } @@ -79,6 +81,7 @@ static std::string ReadPCHRecord(StringRef type) { .Case("TypeSourceInfo *", "GetTypeSourceInfo(F, Record, Idx)") .Case("Expr *", "ReadExpr(F)") .Case("IdentifierInfo *", "GetIdentifierInfo(F, Record, Idx)") + .Case("std::string", "ReadString(Record, Idx)") .Default("Record[Idx++]"); } @@ -92,6 +95,7 @@ static std::string WritePCHRecord(StringRef type, StringRef name) { .Case("Expr *", "AddStmt(" + std::string(name) + ");\n") .Case("IdentifierInfo *", "AddIdentifierRef(" + std::string(name) + ", Record);\n") + .Case("std::string", "AddString(" + std::string(name) + ", Record);\n") .Default("Record.push_back(" + std::string(name) + ");\n"); } @@ -112,11 +116,7 @@ static StringRef NormalizeAttrName(StringRef AttrName) { // This is different from NormalizeAttrName in that it also handles names like // _pascal and __pascal. static StringRef NormalizeNameForSpellingComparison(StringRef Name) { - while (Name.startswith("_")) - Name = Name.substr(1, Name.size()); - while (Name.endswith("_")) - Name = Name.substr(0, Name.size() - 1); - return Name; + return Name.trim("_"); } // Normalize attribute spelling only if the spelling has both leading @@ -414,15 +414,14 @@ namespace { // FIXME: Do not do the calculation here // FIXME: Handle types correctly // A null pointer means maximum alignment - // FIXME: Load the platform-specific maximum alignment, rather than - // 16, the x86 max. OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName() << "(ASTContext &Ctx) const {\n"; OS << " assert(!is" << getUpperName() << "Dependent());\n"; OS << " if (is" << getLowerName() << "Expr)\n"; - OS << " return (" << getLowerName() << "Expr ? " << getLowerName() - << "Expr->EvaluateKnownConstInt(Ctx).getZExtValue() : 16)" - << "* Ctx.getCharWidth();\n"; + OS << " return " << getLowerName() << "Expr ? " << getLowerName() + << "Expr->EvaluateKnownConstInt(Ctx).getZExtValue()" + << " * Ctx.getCharWidth() : " + << "Ctx.getTargetDefaultAlignForAttributeAligned();\n"; OS << " else\n"; OS << " return 0; // FIXME\n"; OS << "}\n"; @@ -985,6 +984,16 @@ namespace { } }; + class VariadicStringArgument : public VariadicArgument { + public: + VariadicStringArgument(const Record &Arg, StringRef Attr) + : VariadicArgument(Arg, Attr, "std::string") + {} + void writeValueImpl(raw_ostream &OS) const override { + OS << " OS << \"\\\"\" << Val << \"\\\"\";\n"; + } + }; + class TypeArgument : public SimpleArgument { public: TypeArgument(const Record &Arg, StringRef Attr) @@ -1046,6 +1055,8 @@ createArgument(const Record &Arg, StringRef Attr, Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "unsigned"); else if (ArgName == "VariadicUnsignedArgument") Ptr = llvm::make_unique<VariadicArgument>(Arg, Attr, "unsigned"); + else if (ArgName == "VariadicStringArgument") + Ptr = llvm::make_unique<VariadicStringArgument>(Arg, Attr); else if (ArgName == "VariadicEnumArgument") Ptr = llvm::make_unique<VariadicEnumArgument>(Arg, Attr); else if (ArgName == "VariadicExprArgument") @@ -1162,7 +1173,7 @@ writePrettyPrintFunction(Record &R, OS << " case " << I << " : {\n" - " OS << \"" + Prefix.str() + Spelling.str(); + " OS << \"" << Prefix << Spelling; if (Variety == "Pragma") { OS << " \";\n"; @@ -1190,7 +1201,7 @@ writePrettyPrintFunction(Record &R, if (!Args.empty()) OS << ")"; - OS << Suffix.str() + "\";\n"; + OS << Suffix + "\";\n"; OS << " break;\n" @@ -1207,7 +1218,7 @@ writePrettyPrintFunction(Record &R, static unsigned getSpellingListIndex(const std::vector<FlattenedSpelling> &SpellingList, const FlattenedSpelling &Spelling) { - assert(SpellingList.size() && "Spelling list is empty!"); + assert(!SpellingList.empty() && "Spelling list is empty!"); for (unsigned Index = 0; Index < SpellingList.size(); ++Index) { const FlattenedSpelling &S = SpellingList[Index]; @@ -1231,7 +1242,7 @@ static void writeAttrAccessorDefinition(const Record &R, raw_ostream &OS) { std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Accessor); std::vector<FlattenedSpelling> SpellingList = GetFlattenedSpellings(R); - assert(SpellingList.size() && + assert(!SpellingList.empty() && "Attribute with empty spelling list can't have accessors!"); OS << " bool " << Name << "() const { return SpellingListIndex == "; @@ -1297,7 +1308,11 @@ CreateSemanticSpellings(const std::vector<FlattenedSpelling> &Spellings, Uniques.insert(EnumName); if (I != Spellings.begin()) Ret += ",\n"; - Ret += " " + EnumName; + // Duplicate spellings are not considered part of the semantic spelling + // enumeration, but the spelling index and semantic spelling values are + // meant to be equivalent, so we must specify a concrete value for each + // enumerator. + Ret += " " + EnumName + " = " + llvm::utostr(Idx); } Ret += "\n };\n\n"; return Ret; @@ -1513,7 +1528,9 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) { OS << "unsigned SI\n"; OS << " )\n"; - OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n"; + OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI, " + << R.getValueAsBit("LateParsed") << ", " + << R.getValueAsBit("DuplicatesAllowedWhileMerging") << ")\n"; for (auto const &ai : Args) { OS << " , "; @@ -1545,7 +1562,9 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) { OS << "unsigned SI\n"; OS << " )\n"; - OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n"; + OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI, " + << R.getValueAsBit("LateParsed") << ", " + << R.getValueAsBit("DuplicatesAllowedWhileMerging") << ")\n"; for (auto const &ai : Args) { OS << " , "; @@ -1564,10 +1583,10 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) { OS << " }\n\n"; } - OS << " " << R.getName() << "Attr *clone(ASTContext &C) const override;\n"; + OS << " " << R.getName() << "Attr *clone(ASTContext &C) const;\n"; OS << " void printPretty(raw_ostream &OS,\n" - << " const PrintingPolicy &Policy) const override;\n"; - OS << " const char *getSpelling() const override;\n"; + << " const PrintingPolicy &Policy) const;\n"; + OS << " const char *getSpelling() const;\n"; if (!ElideSpelling) { assert(!SemanticToSyntacticMap.empty() && "Empty semantic mapping list"); @@ -1596,13 +1615,6 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) { OS << " static bool classof(const Attr *A) { return A->getKind() == " << "attr::" << R.getName() << "; }\n"; - bool LateParsed = R.getValueAsBit("LateParsed"); - OS << " bool isLateParsed() const override { return " - << LateParsed << "; }\n"; - - if (R.getValueAsBit("DuplicatesAllowedWhileMerging")) - OS << " bool duplicatesAllowed() const override { return true; }\n\n"; - OS << "};\n\n"; } @@ -1645,6 +1657,36 @@ void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) { writePrettyPrintFunction(R, Args, OS); writeGetSpellingFunction(R, OS); } + + // Instead of relying on virtual dispatch we just create a huge dispatch + // switch. This is both smaller and faster than virtual functions. + auto EmitFunc = [&](const char *Method) { + OS << " switch (getKind()) {\n"; + for (const auto *Attr : Attrs) { + const Record &R = *Attr; + if (!R.getValueAsBit("ASTNode")) + continue; + + OS << " case attr::" << R.getName() << ":\n"; + OS << " return cast<" << R.getName() << "Attr>(this)->" << Method + << ";\n"; + } + OS << " case attr::NUM_ATTRS:\n"; + OS << " break;\n"; + OS << " }\n"; + OS << " llvm_unreachable(\"Unexpected attribute kind!\");\n"; + OS << "}\n\n"; + }; + + OS << "const char *Attr::getSpelling() const {\n"; + EmitFunc("getSpelling()"); + + OS << "Attr *Attr::clone(ASTContext &C) const {\n"; + EmitFunc("clone(C)"); + + OS << "void Attr::printPretty(raw_ostream &OS, " + "const PrintingPolicy &Policy) const {\n"; + EmitFunc("printPretty(OS, Policy)"); } } // end namespace clang @@ -2185,7 +2227,8 @@ static std::string CalculateDiagnostic(const Record &S) { Namespace = 1U << 11, Field = 1U << 12, CXXMethod = 1U << 13, - ObjCProtocol = 1U << 14 + ObjCProtocol = 1U << 14, + Enum = 1U << 15 }; uint32_t SubMask = 0; @@ -2219,6 +2262,7 @@ static std::string CalculateDiagnostic(const Record &S) { .Case("Namespace", Namespace) .Case("Field", Field) .Case("CXXMethod", CXXMethod) + .Case("Enum", Enum) .Default(0); if (!V) { // Something wasn't in our mapping, so be helpful and let the developer @@ -2237,6 +2281,7 @@ static std::string CalculateDiagnostic(const Record &S) { case Var: return "ExpectedVariable"; case Param: return "ExpectedParameter"; case Class: return "ExpectedClass"; + case Enum: return "ExpectedEnum"; case CXXMethod: // FIXME: Currently, this maps to ExpectedMethod based on existing code, // but should map to something a bit more accurate at some point. @@ -2390,6 +2435,8 @@ static std::string GenerateLangOptRequirements(const Record &R, std::string FnName = "check", Test; for (auto I = LangOpts.begin(), E = LangOpts.end(); I != E; ++I) { std::string Part = (*I)->getValueAsString("Name"); + if ((*I)->getValueAsBit("Negated")) + Test += "!"; Test += "S.LangOpts." + Part; if (I + 1 != E) Test += " || "; @@ -2748,17 +2795,9 @@ static void WriteCategoryHeader(const Record *DocCategory, // If there is content, print that as well. std::string ContentStr = DocCategory->getValueAsString("Content"); - if (!ContentStr.empty()) { - // Trim leading and trailing newlines and spaces. - StringRef Content(ContentStr); - while (Content.startswith("\r") || Content.startswith("\n") || - Content.startswith(" ") || Content.startswith("\t")) - Content = Content.substr(1); - while (Content.endswith("\r") || Content.endswith("\n") || - Content.endswith(" ") || Content.endswith("\t")) - Content = Content.substr(0, Content.size() - 1); - OS << Content; - } + // Trim leading and trailing newlines and spaces. + OS << StringRef(ContentStr).trim(); + OS << "\n\n"; } @@ -2880,14 +2919,7 @@ static void WriteDocumentation(const DocumentationData &Doc, std::string ContentStr = Doc.Documentation->getValueAsString("Content"); // Trim leading and trailing newlines and spaces. - StringRef Content(ContentStr); - while (Content.startswith("\r") || Content.startswith("\n") || - Content.startswith(" ") || Content.startswith("\t")) - Content = Content.substr(1); - while (Content.endswith("\r") || Content.endswith("\n") || - Content.endswith(" ") || Content.endswith("\t")) - Content = Content.substr(0, Content.size() - 1); - OS << Content; + OS << StringRef(ContentStr).trim(); OS << "\n\n\n"; } |