summaryrefslogtreecommitdiff
path: root/utils/TableGen/ClangAttrEmitter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/TableGen/ClangAttrEmitter.cpp')
-rw-r--r--utils/TableGen/ClangAttrEmitter.cpp144
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);