diff options
Diffstat (limited to 'contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp | 431 |
1 files changed, 380 insertions, 51 deletions
diff --git a/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp b/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp index 521f604..7c8603f 100644 --- a/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -47,7 +47,7 @@ static std::string ReadPCHRecord(StringRef type) { .EndsWith("Decl *", "GetLocalDeclAs<" + std::string(type, 0, type.size()-1) + ">(F, Record[Idx++])") .Case("QualType", "getLocalType(F, Record[Idx++])") - .Case("Expr *", "ReadSubExpr()") + .Case("Expr *", "ReadExpr(F)") .Case("IdentifierInfo *", "GetIdentifierInfo(F, Record, Idx)") .Case("SourceLocation", "ReadSourceLocation(F, Record, Idx)") .Default("Record[Idx++]"); @@ -125,6 +125,9 @@ namespace { virtual void writePCHReadDecls(raw_ostream &OS) const = 0; virtual void writePCHWrite(raw_ostream &OS) const = 0; virtual void writeValue(raw_ostream &OS) const = 0; + virtual void writeDump(raw_ostream &OS) const = 0; + virtual void writeDumpChildren(raw_ostream &OS) const {} + virtual void writeHasChildren(raw_ostream &OS) const { OS << "false"; } }; class SimpleArgument : public Argument { @@ -181,6 +184,28 @@ namespace { OS << "\" << get" << getUpperName() << "() << \""; } } + void writeDump(raw_ostream &OS) const { + if (type == "FunctionDecl *") { + OS << " OS << \" \";\n"; + OS << " dumpBareDeclRef(SA->get" << getUpperName() << "());\n"; + } else if (type == "IdentifierInfo *") { + OS << " OS << \" \" << SA->get" << getUpperName() + << "()->getName();\n"; + } else if (type == "QualType") { + OS << " OS << \" \" << SA->get" << getUpperName() + << "().getAsString();\n"; + } else if (type == "SourceLocation") { + OS << " OS << \" \";\n"; + OS << " SA->get" << getUpperName() << "().print(OS, *SM);\n"; + } else if (type == "bool") { + OS << " if (SA->get" << getUpperName() << "()) OS << \" " + << getUpperName() << "\";\n"; + } else if (type == "int" || type == "unsigned") { + OS << " OS << \" \" << SA->get" << getUpperName() << "();\n"; + } else { + llvm_unreachable("Unknown SimpleArgument type!"); + } + } }; class StringArgument : public Argument { @@ -241,6 +266,10 @@ namespace { void writeValue(raw_ostream &OS) const { OS << "\\\"\" << get" << getUpperName() << "() << \"\\\""; } + void writeDump(raw_ostream &OS) const { + OS << " OS << \" \\\"\" << SA->get" << getUpperName() + << "() << \"\\\"\";\n"; + } }; class AlignedArgument : public Argument { @@ -353,6 +382,19 @@ namespace { << " " << getLowerName() << "Expr->printPretty(OS, 0, Policy);\n" << " OS << \""; } + void writeDump(raw_ostream &OS) const { + } + void writeDumpChildren(raw_ostream &OS) const { + OS << " if (SA->is" << getUpperName() << "Expr()) {\n"; + OS << " lastChild();\n"; + OS << " dumpStmt(SA->get" << getUpperName() << "Expr());\n"; + OS << " } else\n"; + OS << " dumpType(SA->get" << getUpperName() + << "Type()->getType());\n"; + } + void writeHasChildren(raw_ostream &OS) const { + OS << "SA->is" << getUpperName() << "Expr()"; + } }; class VariadicArgument : public Argument { @@ -408,7 +450,7 @@ namespace { } void writePCHReadDecls(raw_ostream &OS) const { OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n"; - OS << " llvm::SmallVector<" << type << ", 4> " << getLowerName() + OS << " SmallVector<" << type << ", 4> " << getLowerName() << ";\n"; OS << " " << getLowerName() << ".reserve(" << getLowerName() << "Size);\n"; @@ -439,17 +481,30 @@ namespace { << " }\n"; OS << " 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 << " OS << \" \" << *I;\n"; + } }; class EnumArgument : public Argument { std::string type; - std::vector<StringRef> values, enums; + std::vector<StringRef> values, enums, uniques; public: EnumArgument(Record &Arg, StringRef Attr) : Argument(Arg, Attr), type(Arg.getValueAsString("Type")), values(getValueAsListOfStrings(Arg, "Values")), - enums(getValueAsListOfStrings(Arg, "Enums")) - {} + 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()); + // FIXME: Emit a proper error + assert(!uniques.empty()); + } void writeAccessors(raw_ostream &OS) const { OS << " " << type << " get" << getUpperName() << "() const {\n"; @@ -469,16 +524,8 @@ namespace { OS << type << " " << getUpperName(); } void writeDeclarations(raw_ostream &OS) const { - // Calculate the various enum values - std::vector<StringRef> uniques(enums); - std::sort(uniques.begin(), uniques.end()); - uniques.erase(std::unique(uniques.begin(), uniques.end()), - uniques.end()); - // FIXME: Emit a proper error - assert(!uniques.empty()); - - std::vector<StringRef>::iterator i = uniques.begin(), - e = uniques.end(); + std::vector<StringRef>::const_iterator i = uniques.begin(), + e = uniques.end(); // The last one needs to not have a comma. --e; @@ -505,6 +552,16 @@ namespace { void writeValue(raw_ostream &OS) const { OS << "\" << get" << getUpperName() << "() << \""; } + void writeDump(raw_ostream &OS) const { + OS << " switch(SA->get" << getUpperName() << "()) {\n"; + for (std::vector<StringRef>::const_iterator I = uniques.begin(), + E = uniques.end(); I != E; ++I) { + OS << " case " << getAttrName() << "Attr::" << *I << ":\n"; + OS << " OS << \" " << *I << "\";\n"; + OS << " break;\n"; + } + OS << " }\n"; + } }; class VersionArgument : public Argument { @@ -552,6 +609,9 @@ namespace { void writeValue(raw_ostream &OS) const { OS << getLowerName() << "=\" << get" << getUpperName() << "() << \""; } + void writeDump(raw_ostream &OS) const { + OS << " OS << \" \" << SA->get" << getUpperName() << "();\n"; + } }; class ExprArgument : public SimpleArgument { @@ -575,6 +635,15 @@ namespace { << "Result.takeAs<Expr>();\n"; OS << " }\n"; } + + void writeDump(raw_ostream &OS) const { + } + + void writeDumpChildren(raw_ostream &OS) const { + OS << " lastChild();\n"; + OS << " dumpStmt(SA->get" << getUpperName() << "());\n"; + } + void writeHasChildren(raw_ostream &OS) const { OS << "true"; } }; class VariadicExprArgument : public VariadicArgument { @@ -607,6 +676,24 @@ namespace { OS << " }\n"; OS << " }\n"; } + + void writeDump(raw_ostream &OS) const { + } + + void writeDumpChildren(raw_ostream &OS) const { + OS << " for (" << getAttrName() << "Attr::" << getLowerName() + << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->" + << getLowerName() << "_end(); I != E; ++I) {\n"; + OS << " if (I + 1 == E)\n"; + OS << " lastChild();\n"; + OS << " dumpStmt(*I);\n"; + OS << " }\n"; + } + + void writeHasChildren(raw_ostream &OS) const { + OS << "SA->" << getLowerName() << "_begin() != " + << "SA->" << getLowerName() << "_end()"; + } }; } @@ -663,11 +750,136 @@ 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 if (Variety == "Keyword") { + Prefix = " "; + Suffix = ""; + } else { + llvm_unreachable("Unknown 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"; +} + +/// \brief Return the index of a spelling in a spelling list. +static unsigned getSpellingListIndex(const std::vector<Record*> &SpellingList, + const Record &Spelling) { + assert(SpellingList.size() && "Spelling list is empty!"); + + for (unsigned Index = 0; Index < SpellingList.size(); ++Index) { + Record *S = SpellingList[Index]; + if (S->getValueAsString("Variety") != Spelling.getValueAsString("Variety")) + continue; + if (S->getValueAsString("Variety") == "CXX11" && + S->getValueAsString("Namespace") != + Spelling.getValueAsString("Namespace")) + continue; + if (S->getValueAsString("Name") != Spelling.getValueAsString("Name")) + continue; + + return Index; + } + + llvm_unreachable("Unknown spelling!"); +} + +static void writeAttrAccessorDefinition(Record &R, raw_ostream &OS) { + std::vector<Record*> Accessors = R.getValueAsListOfDefs("Accessors"); + for (std::vector<Record*>::const_iterator I = Accessors.begin(), + E = Accessors.end(); I != E; ++I) { + Record *Accessor = *I; + std::string Name = Accessor->getValueAsString("Name"); + std::vector<Record*> Spellings = Accessor->getValueAsListOfDefs( + "Spellings"); + std::vector<Record*> SpellingList = R.getValueAsListOfDefs("Spellings"); + assert(SpellingList.size() && + "Attribute with empty spelling list can't have accessors!"); + + OS << " bool " << Name << "() const { return SpellingListIndex == "; + for (unsigned Index = 0; Index < Spellings.size(); ++Index) { + OS << getSpellingListIndex(SpellingList, *Spellings[Index]); + if (Index != Spellings.size() -1) + OS << " ||\n SpellingListIndex == "; + else + OS << "; }\n"; + } + } +} + namespace clang { // Emits the class definitions for attributes. void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) { - OS << "// This file is generated by TableGen. Do not edit.\n\n"; + emitSourceFileHeader("Attribute classes' definitions", OS); + OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n"; OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n"; @@ -711,9 +923,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 << " , "; @@ -730,9 +945,11 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) { OS << " }\n\n"; OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n"; - OS << " virtual void printPretty(llvm::raw_ostream &OS," + OS << " virtual void printPretty(raw_ostream &OS,\n" << " const PrintingPolicy &Policy) const;\n"; + writeAttrAccessorDefinition(R, OS); + for (ai = Args.begin(); ai != ae; ++ai) { (*ai)->writeAccessors(OS); OS << "\n\n"; @@ -756,7 +973,7 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) { // Emits the class method definitions for attributes. void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) { - OS << "// This file is generated by TableGen. Do not edit.\n\n"; + emitSourceFileHeader("Attribute classes' member function definitions", OS); std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ri, re; @@ -769,7 +986,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())); @@ -784,26 +1000,9 @@ void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) { OS << ", "; (*ai)->writeCloneArgs(OS); } - OS << ");\n}\n\n"; + OS << ", getSpellingListIndex());\n}\n\n"; - OS << "void " << R.getName() << "Attr::printPretty(" - << "llvm::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); } } @@ -830,7 +1029,7 @@ namespace clang { // Emits the enumeration list for attributes. void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) { - OS << "// This file is generated by TableGen. Do not edit.\n\n"; + emitSourceFileHeader("List of all attributes that Clang recognizes", OS); OS << "#ifndef LAST_ATTR\n"; OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n"; @@ -853,10 +1052,20 @@ 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 << "#endif\n\n"; + + OS << "#ifndef LAST_MS_INHERITABLE_ATTR\n"; + OS << "#define LAST_MS_INHERITABLE_ATTR(NAME)" + " MS_INHERITABLE_ATTR(NAME)\n"; + OS << "#endif\n\n"; + Record *InhClass = Records.getClass("InheritableAttr"); Record *InhParamClass = Records.getClass("InheritableParamAttr"); + Record *MSInheritanceClass = Records.getClass("MSInheritanceAttr"); std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), - NonInhAttrs, InhAttrs, InhParamAttrs; + NonInhAttrs, InhAttrs, InhParamAttrs, MSInhAttrs; for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(); i != e; ++i) { if (!(*i)->getValueAsBit("ASTNode")) @@ -864,6 +1073,8 @@ void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) { if ((*i)->isSubClassOf(InhParamClass)) InhParamAttrs.push_back(*i); + else if ((*i)->isSubClassOf(MSInheritanceClass)) + MSInhAttrs.push_back(*i); else if ((*i)->isSubClassOf(InhClass)) InhAttrs.push_back(*i); else @@ -871,19 +1082,22 @@ void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) { } EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs); + EmitAttrList(OS, "MS_INHERITABLE_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 LAST_INHERITABLE_ATTR\n"; OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n"; + OS << "#undef LAST_MS_INHERITABLE_ATTR\n"; OS << "#undef ATTR\n"; } // Emits the code to read an attribute from a precompiled header. void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) { - OS << "// This file is generated by TableGen. Do not edit.\n\n"; + emitSourceFileHeader("Attribute deserialization code", OS); Record *InhClass = Records.getClass("InheritableAttr"); std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), @@ -927,6 +1141,8 @@ void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) { // Emits the code to write an attribute to a precompiled header. void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) { + emitSourceFileHeader("Attribute serialization code", OS); + Record *InhClass = Records.getClass("InheritableAttr"); std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args; std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae; @@ -956,7 +1172,8 @@ void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) { // Emits the list of spellings for attributes. void EmitClangAttrSpellingList(RecordKeeper &Records, raw_ostream &OS) { - OS << "// This file is generated by TableGen. Do not edit.\n\n"; + emitSourceFileHeader("llvm::StringSwitch code to match all known attributes", + OS); std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); @@ -972,9 +1189,70 @@ void EmitClangAttrSpellingList(RecordKeeper &Records, raw_ostream &OS) { } +void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) { + emitSourceFileHeader("Code to translate different attribute spellings " + "into internal identifiers", OS); + + 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) + .Case("Keyword", 3) + .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"; + emitSourceFileHeader("llvm::StringSwitch code to match late parsed " + "attributes", OS); std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); @@ -1002,7 +1280,7 @@ void EmitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS) { // Emits code to instantiate dependent attributes on templates. void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) { - OS << "// This file is generated by TableGen. Do not edit.\n\n"; + emitSourceFileHeader("Template instantiation code for attributes", OS); std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); @@ -1075,8 +1353,8 @@ void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) { // Emits the list of parsed attributes. void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) { - OS << "// This file is generated by TableGen. Do not edit.\n\n"; - + 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"; @@ -1113,9 +1391,8 @@ void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) { // Emits the kind list of parsed attributes void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { - OS << "// This file is generated by TableGen. Do not edit.\n\n"; - OS << "\n"; - + emitSourceFileHeader("Attribute name matcher", OS); + std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); std::vector<StringMatcher::StringPair> Matches; @@ -1163,4 +1440,56 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { << "}\n"; } +// Emits the code to dump an attribute. +void EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS) { + emitSourceFileHeader("Attribute dumper", OS); + + OS << + " switch (A->getKind()) {\n" + " default:\n" + " llvm_unreachable(\"Unknown attribute kind!\");\n" + " break;\n"; + std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args; + for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); + I != E; ++I) { + Record &R = **I; + if (!R.getValueAsBit("ASTNode")) + continue; + OS << " case attr::" << R.getName() << ": {\n"; + Args = R.getValueAsListOfDefs("Args"); + if (!Args.empty()) { + OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName() + << "Attr>(A);\n"; + for (std::vector<Record*>::iterator I = Args.begin(), E = Args.end(); + I != E; ++I) + createArgument(**I, R.getName())->writeDump(OS); + + // Code for detecting the last child. + OS << " bool OldMoreChildren = hasMoreChildren();\n"; + OS << " bool MoreChildren = OldMoreChildren;\n"; + + for (std::vector<Record*>::iterator I = Args.begin(), E = Args.end(); + I != E; ++I) { + // More code for detecting the last child. + OS << " MoreChildren = OldMoreChildren"; + for (std::vector<Record*>::iterator Next = I + 1; Next != E; ++Next) { + OS << " || "; + createArgument(**Next, R.getName())->writeHasChildren(OS); + } + OS << ";\n"; + OS << " setMoreChildren(MoreChildren);\n"; + + createArgument(**I, R.getName())->writeDumpChildren(OS); + } + + // Reset the last child. + OS << " setMoreChildren(OldMoreChildren);\n"; + } + OS << + " break;\n" + " }\n"; + } + OS << " }\n"; +} + } // end namespace clang |