diff options
Diffstat (limited to 'utils/TableGen/ClangAttrEmitter.cpp')
| -rw-r--r-- | utils/TableGen/ClangAttrEmitter.cpp | 144 |
1 files changed, 81 insertions, 63 deletions
diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp index 50102af33a5a..d65794e86374 100644 --- a/utils/TableGen/ClangAttrEmitter.cpp +++ b/utils/TableGen/ClangAttrEmitter.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/STLExtras.h" @@ -120,12 +121,8 @@ static std::string WritePCHRecord(StringRef type, StringRef name) { // underscores. For example, __foo, foo__, __foo__ would // become foo. static StringRef NormalizeAttrName(StringRef AttrName) { - if (AttrName.startswith("__")) - AttrName = AttrName.substr(2, AttrName.size()); - - if (AttrName.endswith("__")) - AttrName = AttrName.substr(0, AttrName.size() - 2); - + AttrName.consume_front("__"); + AttrName.consume_back("__"); return AttrName; } @@ -299,7 +296,13 @@ namespace { OS << "\" << get" << getUpperName() << "()->getNameInfo().getAsString() << \""; } else if (type == "IdentifierInfo *") { - OS << "\" << get" << getUpperName() << "()->getName() << \""; + OS << "\";\n"; + if (isOptional()) + OS << " if (get" << getUpperName() << "()) "; + else + OS << " "; + OS << "OS << get" << getUpperName() << "()->getName();\n"; + OS << " OS << \""; } else if (type == "TypeSourceInfo *") { OS << "\" << get" << getUpperName() << "().getAsString() << \""; } else { @@ -717,13 +720,10 @@ namespace { std::vector<std::string> uniqueEnumsInOrder(const std::vector<std::string> &enums) { std::vector<std::string> uniques; - std::set<std::string> unique_set(enums.begin(), enums.end()); + SmallDenseSet<StringRef, 8> unique_set; for (const auto &i : enums) { - auto set_i = unique_set.find(i); - if (set_i != unique_set.end()) { + if (unique_set.insert(i).second) uniques.push_back(i); - unique_set.erase(set_i); - } } return uniques; } @@ -835,7 +835,7 @@ namespace { OS << " static const char *Convert" << type << "ToStr(" << type << " Val) {\n" << " switch(Val) {\n"; - std::set<std::string> Uniques; + SmallDenseSet<StringRef, 8> Uniques; for (size_t I = 0; I < enums.size(); ++I) { if (Uniques.insert(enums[I]).second) OS << " case " << getAttrName() << "Attr::" << enums[I] @@ -943,7 +943,7 @@ namespace { OS << " static const char *Convert" << type << "ToStr(" << type << " Val) {\n" << " switch(Val) {\n"; - std::set<std::string> Uniques; + SmallDenseSet<StringRef, 8> Uniques; for (size_t I = 0; I < enums.size(); ++I) { if (Uniques.insert(enums[I]).second) OS << " case " << getAttrName() << "Attr::" << enums[I] @@ -1312,6 +1312,9 @@ writePrettyPrintFunction(Record &R, } else if (Variety == "Declspec") { Prefix = " __declspec("; Suffix = ")"; + } else if (Variety == "Microsoft") { + Prefix = "["; + Suffix = "]"; } else if (Variety == "Keyword") { Prefix = " "; Suffix = ""; @@ -1344,11 +1347,8 @@ writePrettyPrintFunction(Record &R, // Fake arguments aren't part of the parsed form and should not be // pretty-printed. - bool hasNonFakeArgs = false; - for (const auto &arg : Args) { - if (arg->isFake()) continue; - hasNonFakeArgs = true; - } + bool hasNonFakeArgs = llvm::any_of( + Args, [](const std::unique_ptr<Argument> &A) { return !A->isFake(); }); // FIXME: always printing the parenthesis isn't the correct behavior for // attributes which have optional arguments that were not provided. For @@ -1408,18 +1408,20 @@ getSpellingListIndex(const std::vector<FlattenedSpelling> &SpellingList, static void writeAttrAccessorDefinition(const Record &R, raw_ostream &OS) { std::vector<Record*> Accessors = R.getValueAsListOfDefs("Accessors"); + if (Accessors.empty()) + return; + + const std::vector<FlattenedSpelling> SpellingList = GetFlattenedSpellings(R); + assert(!SpellingList.empty() && + "Attribute with empty spelling list can't have accessors!"); for (const auto *Accessor : Accessors) { std::string Name = Accessor->getValueAsString("Name"); - std::vector<FlattenedSpelling> Spellings = - GetFlattenedSpellings(*Accessor); - std::vector<FlattenedSpelling> SpellingList = GetFlattenedSpellings(R); - assert(!SpellingList.empty() && - "Attribute with empty spelling list can't have accessors!"); + std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Accessor); OS << " bool " << Name << "() const { return SpellingListIndex == "; for (unsigned Index = 0; Index < Spellings.size(); ++Index) { OS << getSpellingListIndex(SpellingList, Spellings[Index]); - if (Index != Spellings.size() -1) + if (Index != Spellings.size() - 1) OS << " ||\n SpellingListIndex == "; else OS << "; }\n"; @@ -1521,6 +1523,16 @@ static void emitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS) OS << "#endif // CLANG_ATTR_LATE_PARSED_LIST\n\n"; } +template <typename Fn> +static void forEachUniqueSpelling(const Record &Attr, Fn &&F) { + std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr); + SmallDenseSet<StringRef, 8> Seen; + for (const FlattenedSpelling &S : Spellings) { + if (Seen.insert(S.name()).second) + F(S); + } +} + /// \brief Emits the first-argument-is-type property for attributes. static void emitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) { OS << "#if defined(CLANG_ATTR_TYPE_ARG_LIST)\n"; @@ -1536,12 +1548,9 @@ static void emitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) { continue; // All these spellings take a single type argument. - std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr); - std::set<std::string> Emitted; - for (const auto &S : Spellings) { - if (Emitted.insert(S.name()).second) - OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n"; - } + forEachUniqueSpelling(*Attr, [&](const FlattenedSpelling &S) { + OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n"; + }); } OS << "#endif // CLANG_ATTR_TYPE_ARG_LIST\n\n"; } @@ -1558,12 +1567,9 @@ static void emitClangAttrArgContextList(RecordKeeper &Records, raw_ostream &OS) continue; // All these spellings take are parsed unevaluated. - std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr); - std::set<std::string> Emitted; - for (const auto &S : Spellings) { - if (Emitted.insert(S.name()).second) - OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n"; - } + forEachUniqueSpelling(Attr, [&](const FlattenedSpelling &S) { + OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n"; + }); } OS << "#endif // CLANG_ATTR_ARG_CONTEXT_LIST\n\n"; } @@ -1589,12 +1595,9 @@ static void emitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &O continue; // All these spellings take an identifier argument. - std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr); - std::set<std::string> Emitted; - for (const auto &S : Spellings) { - if (Emitted.insert(S.name()).second) - OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n"; - } + forEachUniqueSpelling(*Attr, [&](const FlattenedSpelling &S) { + OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n"; + }); } OS << "#endif // CLANG_ATTR_IDENTIFIER_ARG_LIST\n\n"; } @@ -1882,8 +1885,7 @@ static void emitAttrList(raw_ostream &OS, StringRef Class, // Determines if an attribute has a Pragma spelling. static bool AttrHasPragmaSpelling(const Record *R) { std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*R); - return std::find_if(Spellings.begin(), Spellings.end(), - [](const FlattenedSpelling &S) { + return llvm::find_if(Spellings, [](const FlattenedSpelling &S) { return S.variety() == "Pragma"; }) != Spellings.end(); } @@ -2295,7 +2297,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, Pragma; + std::vector<Record *> Declspec, Microsoft, GNU, Pragma; std::map<std::string, std::vector<Record *>> CXX; // Walk over the list of all attributes, and split them out based on the @@ -2308,6 +2310,8 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) { GNU.push_back(R); else if (Variety == "Declspec") Declspec.push_back(R); + else if (Variety == "Microsoft") + Microsoft.push_back(R); else if (Variety == "CXX11") CXX[SI.nameSpace()].push_back(R); else if (Variety == "Pragma") @@ -2323,6 +2327,9 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) { OS << "case AttrSyntax::Declspec:\n"; OS << " return llvm::StringSwitch<int>(Name)\n"; GenerateHasAttrSpellingStringSwitch(Declspec, OS, "Declspec"); + OS << "case AttrSyntax::Microsoft:\n"; + OS << " return llvm::StringSwitch<int>(Name)\n"; + GenerateHasAttrSpellingStringSwitch(Microsoft, OS, "Microsoft"); OS << "case AttrSyntax::Pragma:\n"; OS << " return llvm::StringSwitch<int>(Name)\n"; GenerateHasAttrSpellingStringSwitch(Pragma, OS, "Pragma"); @@ -2361,8 +2368,9 @@ void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) { .Case("GNU", 0) .Case("CXX11", 1) .Case("Declspec", 2) - .Case("Keyword", 3) - .Case("Pragma", 4) + .Case("Microsoft", 3) + .Case("Keyword", 4) + .Case("Pragma", 5) .Default(0) << " && Scope == \"" << Spellings[I].nameSpace() << "\")\n" << " return " << I << ";\n"; @@ -2532,6 +2540,10 @@ static void emitArgInfo(const Record &R, std::stringstream &OS) { unsigned ArgCount = 0, OptCount = 0; bool HasVariadic = false; for (const auto *Arg : Args) { + // If the arg is fake, it's the user's job to supply it: general parsing + // logic shouldn't need to know anything about it. + if (Arg->getValueAsBit("Fake")) + continue; Arg->getValueAsBit("Optional") ? ++OptCount : ++ArgCount; if (!HasVariadic && isArgVariadic(*Arg, R.getName())) HasVariadic = true; @@ -2675,7 +2687,7 @@ static std::string CalculateDiagnostic(const Record &S) { } static std::string GetSubjectWithSuffix(const Record *R) { - std::string B = R->getName(); + const std::string &B = R->getName(); if (B == "DeclBase") return "Decl"; return B + "Decl"; @@ -2683,7 +2695,7 @@ static std::string GetSubjectWithSuffix(const Record *R) { static std::string GenerateCustomAppertainsTo(const Record &Subject, raw_ostream &OS) { - std::string FnName = "is" + Subject.getName(); + std::string FnName = "is" + Subject.getName().str(); // If this code has already been generated, simply return the previous // instance of it. @@ -2732,7 +2744,7 @@ static std::string GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) { // Otherwise, generate an appertainsTo check specific to this attribute which // checks all of the given subjects against the Decl passed in. Return the // name of that check to the caller. - std::string FnName = "check" + Attr.getName() + "AppertainsTo"; + std::string FnName = "check" + Attr.getName().str() + "AppertainsTo"; std::stringstream SS; SS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr, "; SS << "const Decl *D) {\n"; @@ -2790,8 +2802,10 @@ 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")) + if ((*I)->getValueAsBit("Negated")) { + FnName += "Not"; Test += "!"; + } Test += "S.LangOpts." + Part; if (I + 1 != E) Test += " || "; @@ -2853,7 +2867,7 @@ static std::string GenerateTargetRequirements(const Record &Attr, if (I.first == APK) { std::vector<std::string> DA = I.second->getValueAsDef("Target") ->getValueAsListOfStrings("Arches"); - std::copy(DA.begin(), DA.end(), std::back_inserter(Arches)); + std::move(DA.begin(), DA.end(), std::back_inserter(Arches)); } } } @@ -2901,7 +2915,7 @@ static std::string GenerateSpellingIndexToSemanticSpelling(const Record &Attr, // Generate the enumeration we will use for the mapping. SemanticSpellingMap SemanticToSyntacticMap; std::string Enum = CreateSemanticSpellings(Spellings, SemanticToSyntacticMap); - std::string Name = Attr.getName() + "AttrSpellingMap"; + std::string Name = Attr.getName().str() + "AttrSpellingMap"; OS << "static unsigned " << Name << "(const AttributeList &Attr) {\n"; OS << Enum; @@ -2915,12 +2929,9 @@ static std::string GenerateSpellingIndexToSemanticSpelling(const Record &Attr, static bool IsKnownToGCC(const Record &Attr) { // Look at the spellings for this subject; if there are any spellings which // claim to be known to GCC, the attribute is known to GCC. - std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr); - for (const auto &I : Spellings) { - if (I.knownToGCC()) - return true; - } - return false; + return llvm::any_of( + GetFlattenedSpellings(Attr), + [](const FlattenedSpelling &S) { return S.knownToGCC(); }); } /// Emits the parsed attribute helpers @@ -2982,7 +2993,8 @@ 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, Pragma; + std::vector<StringMatcher::StringPair> GNU, Declspec, Microsoft, CXX11, + Keywords, Pragma; std::set<std::string> Seen; for (const auto *A : Attrs) { const Record &Attr = *A; @@ -3024,6 +3036,8 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { Matches = &GNU; else if (Variety == "Declspec") Matches = &Declspec; + else if (Variety == "Microsoft") + Matches = &Microsoft; else if (Variety == "Keyword") Matches = &Keywords; else if (Variety == "Pragma") @@ -3048,6 +3062,8 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { StringMatcher("Name", GNU, OS).Emit(); OS << " } else if (AttributeList::AS_Declspec == Syntax) {\n"; StringMatcher("Name", Declspec, OS).Emit(); + OS << " } else if (AttributeList::AS_Microsoft == Syntax) {\n"; + StringMatcher("Name", Microsoft, OS).Emit(); OS << " } else if (AttributeList::AS_CXX11 == Syntax) {\n"; StringMatcher("Name", CXX11, OS).Emit(); OS << " } else if (AttributeList::AS_Keyword == Syntax || "; @@ -3131,8 +3147,9 @@ enum SpellingKind { GNU = 1 << 0, CXX11 = 1 << 1, Declspec = 1 << 2, - Keyword = 1 << 3, - Pragma = 1 << 4 + Microsoft = 1 << 3, + Keyword = 1 << 4, + Pragma = 1 << 5 }; static void WriteDocumentation(const DocumentationData &Doc, @@ -3180,6 +3197,7 @@ static void WriteDocumentation(const DocumentationData &Doc, .Case("GNU", GNU) .Case("CXX11", CXX11) .Case("Declspec", Declspec) + .Case("Microsoft", Microsoft) .Case("Keyword", Keyword) .Case("Pragma", Pragma); |
