diff options
Diffstat (limited to 'contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp | 395 |
1 files changed, 342 insertions, 53 deletions
diff --git a/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp b/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp index eaf10a6..653d7b7 100644 --- a/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -13,6 +13,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/StringMatcher.h" #include "llvm/TableGen/TableGenBackend.h" @@ -46,7 +47,7 @@ static std::string ReadPCHRecord(StringRef type) { return StringSwitch<std::string>(type) .EndsWith("Decl *", "GetLocalDeclAs<" + std::string(type, 0, type.size()-1) + ">(F, Record[Idx++])") - .Case("QualType", "getLocalType(F, Record[Idx++])") + .Case("TypeSourceInfo *", "GetTypeSourceInfo(F, Record, Idx)") .Case("Expr *", "ReadExpr(F)") .Case("IdentifierInfo *", "GetIdentifierInfo(F, Record, Idx)") .Case("SourceLocation", "ReadSourceLocation(F, Record, Idx)") @@ -58,7 +59,8 @@ static std::string WritePCHRecord(StringRef type, StringRef name) { return StringSwitch<std::string>(type) .EndsWith("Decl *", "AddDeclRef(" + std::string(name) + ", Record);\n") - .Case("QualType", "AddTypeRef(" + std::string(name) + ", Record);\n") + .Case("TypeSourceInfo *", + "AddTypeSourceInfo(" + std::string(name) + ", Record);\n") .Case("Expr *", "AddStmt(" + std::string(name) + ");\n") .Case("IdentifierInfo *", "AddIdentifierRef(" + std::string(name) + ", Record);\n") @@ -95,11 +97,12 @@ namespace { class Argument { std::string lowerName, upperName; StringRef attrName; + bool isOpt; public: Argument(Record &Arg, StringRef Attr) : lowerName(Arg.getValueAsString("Name")), upperName(lowerName), - attrName(Attr) { + attrName(Attr), isOpt(false) { if (!lowerName.empty()) { lowerName[0] = std::tolower(lowerName[0]); upperName[0] = std::toupper(upperName[0]); @@ -111,6 +114,9 @@ namespace { StringRef getUpperName() const { return upperName; } StringRef getAttrName() const { return attrName; } + bool isOptional() const { return isOpt; } + void setOptional(bool set) { isOpt = set; } + // These functions print the argument contents formatted in different ways. virtual void writeAccessors(raw_ostream &OS) const = 0; virtual void writeAccessorDefinitions(raw_ostream &OS) const {} @@ -119,6 +125,7 @@ namespace { virtual void writeTemplateInstantiation(raw_ostream &OS) const {} virtual void writeCtorBody(raw_ostream &OS) const {} virtual void writeCtorInitializers(raw_ostream &OS) const = 0; + virtual void writeCtorDefaultInitializers(raw_ostream &OS) const = 0; virtual void writeCtorParameters(raw_ostream &OS) const = 0; virtual void writeDeclarations(raw_ostream &OS) const = 0; virtual void writePCHReadArgs(raw_ostream &OS) const = 0; @@ -128,6 +135,9 @@ namespace { virtual void writeDump(raw_ostream &OS) const = 0; virtual void writeDumpChildren(raw_ostream &OS) const {} virtual void writeHasChildren(raw_ostream &OS) const { OS << "false"; } + + virtual bool isEnumArg() const { return false; } + virtual bool isVariadicEnumArg() const { return false; } }; class SimpleArgument : public Argument { @@ -154,6 +164,9 @@ namespace { void writeCtorInitializers(raw_ostream &OS) const { OS << getLowerName() << "(" << getUpperName() << ")"; } + void writeCtorDefaultInitializers(raw_ostream &OS) const { + OS << getLowerName() << "()"; + } void writeCtorParameters(raw_ostream &OS) const { OS << type << " " << getUpperName(); } @@ -173,10 +186,11 @@ namespace { } void writeValue(raw_ostream &OS) const { if (type == "FunctionDecl *") { - OS << "\" << get" << getUpperName() << "()->getNameInfo().getAsString() << \""; + OS << "\" << get" << getUpperName() + << "()->getNameInfo().getAsString() << \""; } else if (type == "IdentifierInfo *") { OS << "\" << get" << getUpperName() << "()->getName() << \""; - } else if (type == "QualType") { + } else if (type == "TypeSourceInfo *") { OS << "\" << get" << getUpperName() << "().getAsString() << \""; } else if (type == "SourceLocation") { OS << "\" << get" << getUpperName() << "().getRawEncoding() << \""; @@ -191,7 +205,7 @@ namespace { } else if (type == "IdentifierInfo *") { OS << " OS << \" \" << SA->get" << getUpperName() << "()->getName();\n"; - } else if (type == "QualType") { + } else if (type == "TypeSourceInfo *") { OS << " OS << \" \" << SA->get" << getUpperName() << "().getAsString();\n"; } else if (type == "SourceLocation") { @@ -246,6 +260,9 @@ namespace { << getLowerName() << "(new (Ctx, 1) char[" << getLowerName() << "Length])"; } + void writeCtorDefaultInitializers(raw_ostream &OS) const { + OS << getLowerName() << "Length(0)," << getLowerName() << "(0)"; + } void writeCtorParameters(raw_ostream &OS) const { OS << "llvm::StringRef " << getUpperName(); } @@ -347,6 +364,9 @@ namespace { void writeCtorInitializers(raw_ostream &OS) const { OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)"; } + void writeCtorDefaultInitializers(raw_ostream &OS) const { + OS << "is" << getLowerName() << "Expr(false)"; + } void writeCtorParameters(raw_ostream &OS) const { OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName(); } @@ -440,6 +460,9 @@ namespace { << getLowerName() << "(new (Ctx, 16) " << getType() << "[" << getLowerName() << "Size])"; } + void writeCtorDefaultInitializers(raw_ostream &OS) const { + OS << getLowerName() << "Size(0), " << getLowerName() << "(0)"; + } void writeCtorParameters(raw_ostream &OS) const { OS << getType() << " *" << getUpperName() << ", unsigned " << getUpperName() << "Size"; @@ -454,7 +477,7 @@ namespace { << ";\n"; OS << " " << getLowerName() << ".reserve(" << getLowerName() << "Size);\n"; - OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n"; + OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n"; std::string read = ReadPCHRecord(type); OS << " " << getLowerName() << ".push_back(" << read << ");\n"; @@ -506,6 +529,8 @@ namespace { assert(!uniques.empty()); } + bool isEnumArg() const { return true; } + void writeAccessors(raw_ostream &OS) const { OS << " " << type << " get" << getUpperName() << "() const {\n"; OS << " return " << getLowerName() << ";\n"; @@ -520,6 +545,9 @@ namespace { void writeCtorInitializers(raw_ostream &OS) const { OS << getLowerName() << "(" << getUpperName() << ")"; } + void writeCtorDefaultInitializers(raw_ostream &OS) const { + OS << getLowerName() << "(" << type << "(0))"; + } void writeCtorParameters(raw_ostream &OS) const { OS << type << " " << getUpperName(); } @@ -562,6 +590,109 @@ namespace { } OS << " }\n"; } + + void writeConversion(raw_ostream &OS) const { + OS << " static bool ConvertStrTo" << type << "(StringRef Val, "; + OS << type << " &Out) {\n"; + OS << " Optional<" << type << "> R = llvm::StringSwitch<Optional<"; + OS << type << "> >(Val)\n"; + for (size_t I = 0; I < enums.size(); ++I) { + OS << " .Case(\"" << values[I] << "\", "; + OS << getAttrName() << "Attr::" << enums[I] << ")\n"; + } + OS << " .Default(Optional<" << type << ">());\n"; + OS << " if (R) {\n"; + OS << " Out = *R;\n return true;\n }\n"; + OS << " return false;\n"; + OS << " }\n"; + } + }; + + class VariadicEnumArgument: public VariadicArgument { + std::string type, QualifiedTypeName; + std::vector<StringRef> values, enums, uniques; + public: + VariadicEnumArgument(Record &Arg, StringRef Attr) + : VariadicArgument(Arg, Attr, Arg.getValueAsString("Type")), + type(Arg.getValueAsString("Type")), + values(getValueAsListOfStrings(Arg, "Values")), + enums(getValueAsListOfStrings(Arg, "Enums")), + uniques(enums) + { + // Calculate the various enum values + std::sort(uniques.begin(), uniques.end()); + uniques.erase(std::unique(uniques.begin(), uniques.end()), uniques.end()); + + QualifiedTypeName = getAttrName().str() + "Attr::" + type; + + // FIXME: Emit a proper error + assert(!uniques.empty()); + } + + bool isVariadicEnumArg() const { return true; } + + void writeDeclarations(raw_ostream &OS) const { + std::vector<StringRef>::const_iterator i = uniques.begin(), + e = uniques.end(); + // The last one needs to not have a comma. + --e; + + OS << "public:\n"; + OS << " enum " << type << " {\n"; + for (; i != e; ++i) + OS << " " << *i << ",\n"; + OS << " " << *e << "\n"; + OS << " };\n"; + OS << "private:\n"; + + VariadicArgument::writeDeclarations(OS); + } + void writeDump(raw_ostream &OS) const { + OS << " for (" << getAttrName() << "Attr::" << getLowerName() + << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->" + << getLowerName() << "_end(); I != E; ++I) {\n"; + OS << " switch(*I) {\n"; + for (std::vector<StringRef>::const_iterator UI = uniques.begin(), + UE = uniques.end(); UI != UE; ++UI) { + OS << " case " << getAttrName() << "Attr::" << *UI << ":\n"; + OS << " OS << \" " << *UI << "\";\n"; + OS << " break;\n"; + } + OS << " }\n"; + OS << " }\n"; + } + void writePCHReadDecls(raw_ostream &OS) const { + OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n"; + OS << " SmallVector<" << QualifiedTypeName << ", 4> " << getLowerName() + << ";\n"; + OS << " " << getLowerName() << ".reserve(" << getLowerName() + << "Size);\n"; + OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n"; + OS << " " << getLowerName() << ".push_back(" << "static_cast<" + << QualifiedTypeName << ">(Record[Idx++]));\n"; + } + void writePCHWrite(raw_ostream &OS) const{ + OS << " Record.push_back(SA->" << getLowerName() << "_size());\n"; + OS << " for (" << getAttrName() << "Attr::" << getLowerName() + << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->" + << getLowerName() << "_end(); i != e; ++i)\n"; + OS << " " << WritePCHRecord(QualifiedTypeName, "(*i)"); + } + void writeConversion(raw_ostream &OS) const { + OS << " static bool ConvertStrTo" << type << "(StringRef Val, "; + OS << type << " &Out) {\n"; + OS << " Optional<" << type << "> R = llvm::StringSwitch<Optional<"; + OS << type << "> >(Val)\n"; + for (size_t I = 0; I < enums.size(); ++I) { + OS << " .Case(\"" << values[I] << "\", "; + OS << getAttrName() << "Attr::" << enums[I] << ")\n"; + } + OS << " .Default(Optional<" << type << ">());\n"; + OS << " if (R) {\n"; + OS << " Out = *R;\n return true;\n }\n"; + OS << " return false;\n"; + OS << " }\n"; + } }; class VersionArgument : public Argument { @@ -590,6 +721,9 @@ namespace { void writeCtorInitializers(raw_ostream &OS) const { OS << getLowerName() << "(" << getUpperName() << ")"; } + void writeCtorDefaultInitializers(raw_ostream &OS) const { + OS << getLowerName() << "()"; + } void writeCtorParameters(raw_ostream &OS) const { OS << "VersionTuple " << getUpperName(); } @@ -695,6 +829,29 @@ namespace { << "SA->" << getLowerName() << "_end()"; } }; + + class TypeArgument : public SimpleArgument { + public: + TypeArgument(Record &Arg, StringRef Attr) + : SimpleArgument(Arg, Attr, "TypeSourceInfo *") + {} + + void writeAccessors(raw_ostream &OS) const { + OS << " QualType get" << getUpperName() << "() const {\n"; + OS << " return " << getLowerName() << "->getType();\n"; + OS << " }"; + OS << " " << getType() << " get" << getUpperName() << "Loc() const {\n"; + OS << " return " << getLowerName() << ";\n"; + OS << " }"; + } + void writeTemplateInstantiationArgs(raw_ostream &OS) const { + OS << "A->get" << getUpperName() << "Loc()"; + } + void writePCHWrite(raw_ostream &OS) const { + OS << " " << WritePCHRecord( + getType(), "SA->get" + std::string(getUpperName()) + "Loc()"); + } + }; } static Argument *createArgument(Record &Arg, StringRef Attr, @@ -716,14 +873,15 @@ static Argument *createArgument(Record &Arg, StringRef Attr, "bool"); else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int"); else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr); - else if (ArgName == "TypeArgument") - Ptr = new SimpleArgument(Arg, Attr, "QualType"); + else if (ArgName == "TypeArgument") Ptr = new TypeArgument(Arg, Attr); else if (ArgName == "UnsignedArgument") Ptr = new SimpleArgument(Arg, Attr, "unsigned"); else if (ArgName == "SourceLocArgument") Ptr = new SimpleArgument(Arg, Attr, "SourceLocation"); else if (ArgName == "VariadicUnsignedArgument") Ptr = new VariadicArgument(Arg, Attr, "unsigned"); + else if (ArgName == "VariadicEnumArgument") + Ptr = new VariadicEnumArgument(Arg, Attr); else if (ArgName == "VariadicExprArgument") Ptr = new VariadicExprArgument(Arg, Attr); else if (ArgName == "VersionArgument") @@ -738,6 +896,10 @@ static Argument *createArgument(Record &Arg, StringRef Attr, break; } } + + if (Ptr && Arg.getValueAsBit("Optional")) + Ptr->setOptional(true); + return Ptr; } @@ -892,7 +1054,15 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) { if (!R.getValueAsBit("ASTNode")) continue; - const std::string &SuperName = R.getSuperClasses().back()->getName(); + const std::vector<Record *> Supers = R.getSuperClasses(); + assert(!Supers.empty() && "Forgot to specify a superclass for the attr"); + std::string SuperName; + for (std::vector<Record *>::const_reverse_iterator I = Supers.rbegin(), + E = Supers.rend(); I != E; ++I) { + const Record &R = **I; + if (R.getName() != "TargetSpecificAttr" && SuperName.empty()) + SuperName = R.getName(); + } OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n"; @@ -918,10 +1088,13 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) { OS << "\n public:\n"; OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n"; + bool HasOpt = false; for (ai = Args.begin(); ai != ae; ++ai) { OS << " , "; (*ai)->writeCtorParameters(OS); OS << "\n"; + if ((*ai)->isOptional()) + HasOpt = true; } OS << " , "; @@ -944,6 +1117,41 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) { } OS << " }\n\n"; + // If there are optional arguments, write out a constructor that elides the + // optional arguments as well. + if (HasOpt) { + OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n"; + for (ai = Args.begin(); ai != ae; ++ai) { + if (!(*ai)->isOptional()) { + OS << " , "; + (*ai)->writeCtorParameters(OS); + OS << "\n"; + } + } + + OS << " , "; + OS << "unsigned SI = 0\n"; + + OS << " )\n"; + OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n"; + + for (ai = Args.begin(); ai != ae; ++ai) { + OS << " , "; + (*ai)->writeCtorDefaultInitializers(OS); + OS << "\n"; + } + + OS << " {\n"; + + for (ai = Args.begin(); ai != ae; ++ai) { + if (!(*ai)->isOptional()) { + (*ai)->writeCtorBody(OS); + OS << "\n"; + } + } + OS << " }\n\n"; + } + OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n"; OS << " virtual void printPretty(raw_ostream &OS,\n" << " const PrintingPolicy &Policy) const;\n"; @@ -953,6 +1161,14 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) { for (ai = Args.begin(); ai != ae; ++ai) { (*ai)->writeAccessors(OS); OS << "\n\n"; + + if ((*ai)->isEnumArg()) { + EnumArgument *EA = (EnumArgument *)*ai; + EA->writeConversion(OS); + } else if ((*ai)->isVariadicEnumArg()) { + VariadicEnumArgument *VEA = (VariadicEnumArgument *)*ai; + VEA->writeConversion(OS); + } } OS << R.getValueAsString("AdditionalMembers"); @@ -971,44 +1187,69 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) { OS << "#endif\n"; } -// Emits the all-arguments-are-expressions property for attributes. -void EmitClangAttrExprArgsList(RecordKeeper &Records, raw_ostream &OS) { - emitSourceFileHeader("llvm::StringSwitch code to match attributes with " - "expression arguments", OS); +static bool isIdentifierArgument(Record *Arg) { + return !Arg->getSuperClasses().empty() && + llvm::StringSwitch<bool>(Arg->getSuperClasses().back()->getName()) + .Case("IdentifierArgument", true) + .Case("EnumArgument", true) + .Default(false); +} - std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); +/// \brief Emits the first-argument-is-type property for attributes. +void EmitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) { + emitSourceFileHeader("llvm::StringSwitch code to match attributes with a " + "type argument", OS); - for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); + std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"); + + for (std::vector<Record *>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) { Record &Attr = **I; - // Determine whether the first argument is something that is always - // an expression. + // Determine whether the first argument is a type. std::vector<Record *> Args = Attr.getValueAsListOfDefs("Args"); - if (Args.empty() || Args[0]->getSuperClasses().empty()) + if (Args.empty()) continue; - // Check whether this is one of the argument kinds that implies an - // expression. - // FIXME: Aligned is weird. - if (!llvm::StringSwitch<bool>(Args[0]->getSuperClasses().back()->getName()) - .Case("AlignedArgument", true) - .Case("BoolArgument", true) - .Case("DefaultIntArgument", true) - .Case("IntArgument", true) - .Case("ExprArgument", true) - .Case("UnsignedArgument", true) - .Case("VariadicUnsignedArgument", true) - .Case("VariadicExprArgument", true) - .Default(false)) + if (Args[0]->getSuperClasses().back()->getName() != "TypeArgument") continue; + // All these spellings take a single type argument. std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); + std::set<std::string> Emitted; + for (std::vector<Record*>::const_iterator I = Spellings.begin(), + E = Spellings.end(); I != E; ++I) { + if (Emitted.insert((*I)->getValueAsString("Name")).second) + OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", " + << "true" << ")\n"; + } + } +} + +// Emits the first-argument-is-identifier property for attributes. +void EmitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &OS) { + emitSourceFileHeader("llvm::StringSwitch code to match attributes with " + "an identifier argument", OS); + std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); + + for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); + I != E; ++I) { + Record &Attr = **I; + + // Determine whether the first argument is an identifier. + std::vector<Record *> Args = Attr.getValueAsListOfDefs("Args"); + if (Args.empty() || !isIdentifierArgument(Args[0])) + continue; + + // All these spellings take an identifier argument. + std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); + std::set<std::string> Emitted; for (std::vector<Record*>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) { - OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", " - << "true" << ")\n"; + if (Emitted.insert((*I)->getValueAsString("Name")).second) + OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", " + << "true" << ")\n"; } } } @@ -1094,13 +1335,13 @@ void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) { " INHERITABLE_PARAM_ATTR(NAME)\n"; OS << "#endif\n\n"; - OS << "#ifndef MS_INHERITABLE_ATTR\n"; - OS << "#define MS_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n"; + OS << "#ifndef MS_INHERITANCE_ATTR\n"; + OS << "#define MS_INHERITANCE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n"; OS << "#endif\n\n"; - OS << "#ifndef LAST_MS_INHERITABLE_ATTR\n"; - OS << "#define LAST_MS_INHERITABLE_ATTR(NAME)" - " MS_INHERITABLE_ATTR(NAME)\n"; + OS << "#ifndef LAST_MS_INHERITANCE_ATTR\n"; + OS << "#define LAST_MS_INHERITANCE_ATTR(NAME)" + " MS_INHERITANCE_ATTR(NAME)\n"; OS << "#endif\n\n"; Record *InhClass = Records.getClass("InheritableAttr"); @@ -1124,16 +1365,16 @@ void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) { } EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs); - EmitAttrList(OS, "MS_INHERITABLE_ATTR", MSInhAttrs); + EmitAttrList(OS, "MS_INHERITANCE_ATTR", MSInhAttrs); EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs); EmitAttrList(OS, "ATTR", NonInhAttrs); OS << "#undef LAST_ATTR\n"; OS << "#undef INHERITABLE_ATTR\n"; - OS << "#undef MS_INHERITABLE_ATTR\n"; + OS << "#undef MS_INHERITANCE_ATTR\n"; OS << "#undef LAST_INHERITABLE_ATTR\n"; OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n"; - OS << "#undef LAST_MS_INHERITABLE_ATTR\n"; + OS << "#undef LAST_MS_INHERITANCE_ATTR\n"; OS << "#undef ATTR\n"; } @@ -1393,16 +1634,11 @@ void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) { << "} // end namespace clang\n"; } -// Emits the list of parsed attributes. -void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) { - emitSourceFileHeader("List of all attributes that Clang recognizes", OS); +typedef std::vector<std::pair<std::string, Record *> > ParsedAttrMap; - OS << "#ifndef PARSED_ATTR\n"; - OS << "#define PARSED_ATTR(NAME) NAME\n"; - OS << "#endif\n\n"; - +static ParsedAttrMap getParsedAttrList(const RecordKeeper &Records) { std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); - + ParsedAttrMap R; for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) { Record &Attr = **I; @@ -1419,16 +1655,69 @@ void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) { std::string AttrName = (*I)->getValueAsString("Name"); StringRef Spelling = NormalizeAttrName(AttrName); - - OS << "PARSED_ATTR(" << Spelling << ")\n"; + R.push_back(std::make_pair(Spelling.str(), &Attr)); } } else { StringRef AttrName = Attr.getName(); AttrName = NormalizeAttrName(AttrName); - OS << "PARSED_ATTR(" << AttrName << ")\n"; + R.push_back(std::make_pair(AttrName.str(), *I)); } } } + return R; +} + +// Emits the list of parsed attributes. +void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) { + emitSourceFileHeader("List of all attributes that Clang recognizes", OS); + + OS << "#ifndef PARSED_ATTR\n"; + OS << "#define PARSED_ATTR(NAME) NAME\n"; + OS << "#endif\n\n"; + + ParsedAttrMap Names = getParsedAttrList(Records); + for (ParsedAttrMap::iterator I = Names.begin(), E = Names.end(); I != E; + ++I) { + OS << "PARSED_ATTR(" << I->first << ")\n"; + } +} + +static void emitArgInfo(const Record &R, raw_ostream &OS) { + // This function will count the number of arguments specified for the + // attribute and emit the number of required arguments followed by the + // number of optional arguments. + std::vector<Record *> Args = R.getValueAsListOfDefs("Args"); + unsigned ArgCount = 0, OptCount = 0; + for (std::vector<Record *>::const_iterator I = Args.begin(), E = Args.end(); + I != E; ++I) { + const Record &Arg = **I; + Arg.getValueAsBit("Optional") ? ++OptCount : ++ArgCount; + } + OS << ArgCount << ", " << OptCount; +} + +/// Emits the parsed attribute helpers +void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) { + emitSourceFileHeader("Parsed attribute helpers", OS); + + ParsedAttrMap Attrs = getParsedAttrList(Records); + + OS << "static const ParsedAttrInfo AttrInfoMap[AttributeList::UnknownAttribute + 1] = {\n"; + for (ParsedAttrMap::iterator I = Attrs.begin(), E = Attrs.end(); I != E; + ++I) { + // We need to generate struct instances based off ParsedAttrInfo from + // AttributeList.cpp. + OS << " { "; + emitArgInfo(*I->second, OS); + OS << ", " << I->second->getValueAsBit("HasCustomParsing"); + OS << " }"; + + if (I + 1 != E) + OS << ","; + + OS << " // AT_" << I->first << "\n"; + } + OS << "};\n\n"; } // Emits the kind list of parsed attributes |