r262275 - Infrastructure improvements to Clang attribute TableGen.
Sean Silva via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 29 17:44:26 PST 2016
This seems to be causing a substantial amount of warning spew from MSVC:
http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast/builds/955
I think our recommended "portable" method of using llvm_unreachable is
outside the switch, instead of in the default case:
http://llvm.org/docs/CodingStandards.html#don-t-use-default-labels-in-fully-covered-switches-over-enumerations
-- Sean Silva
On Mon, Feb 29, 2016 at 4:18 PM, John McCall via cfe-commits <
cfe-commits at lists.llvm.org> wrote:
> Author: rjmccall
> Date: Mon Feb 29 18:18:05 2016
> New Revision: 262275
>
> URL: http://llvm.org/viewvc/llvm-project?rev=262275&view=rev
> Log:
> Infrastructure improvements to Clang attribute TableGen.
>
> This should make it easier to add new Attr subclasses.
>
> Modified:
> cfe/trunk/include/clang/AST/Attr.h
> cfe/trunk/include/clang/Basic/AttrKinds.h
> cfe/trunk/lib/AST/ASTDumper.cpp
> cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
>
> Modified: cfe/trunk/include/clang/AST/Attr.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Attr.h?rev=262275&r1=262274&r2=262275&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Attr.h (original)
> +++ cfe/trunk/include/clang/AST/Attr.h Mon Feb 29 18:18:05 2016
> @@ -129,7 +129,8 @@ public:
>
> // Implement isa/cast/dyncast/etc.
> static bool classof(const Attr *A) {
> - return A->getKind() <= attr::LAST_INHERITABLE;
> + return A->getKind() >= attr::FirstInheritableAttr &&
> + A->getKind() <= attr::LastInheritableAttr;
> }
> };
>
> @@ -143,9 +144,8 @@ protected:
> public:
> // Implement isa/cast/dyncast/etc.
> static bool classof(const Attr *A) {
> - // Relies on relative order of enum emission with respect to MS
> inheritance
> - // attrs.
> - return A->getKind() <= attr::LAST_INHERITABLE_PARAM;
> + return A->getKind() >= attr::FirstInheritableParamAttr &&
> + A->getKind() <= attr::LastInheritableParamAttr;
> }
> };
>
>
> Modified: cfe/trunk/include/clang/Basic/AttrKinds.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttrKinds.h?rev=262275&r1=262274&r2=262275&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/AttrKinds.h (original)
> +++ cfe/trunk/include/clang/Basic/AttrKinds.h Mon Feb 29 18:18:05 2016
> @@ -22,10 +22,10 @@ namespace attr {
> // \brief A list of all the recognized kinds of attributes.
> enum Kind {
> #define ATTR(X) X,
> -#define LAST_INHERITABLE_ATTR(X) X, LAST_INHERITABLE = X,
> -#define LAST_INHERITABLE_PARAM_ATTR(X) X, LAST_INHERITABLE_PARAM = X,
> +#define ATTR_RANGE(CLASS, FIRST_NAME, LAST_NAME) \
> + First##CLASS = FIRST_NAME, \
> + Last##CLASS = LAST_NAME,
> #include "clang/Basic/AttrList.inc"
> - NUM_ATTRS
> };
>
> } // end namespace attr
>
> Modified: cfe/trunk/lib/AST/ASTDumper.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDumper.cpp?rev=262275&r1=262274&r2=262275&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/ASTDumper.cpp (original)
> +++ cfe/trunk/lib/AST/ASTDumper.cpp Mon Feb 29 18:18:05 2016
> @@ -819,8 +819,6 @@ void ASTDumper::dumpAttr(const Attr *A)
> switch (A->getKind()) {
> #define ATTR(X) case attr::X: OS << #X; break;
> #include "clang/Basic/AttrList.inc"
> - default:
> - llvm_unreachable("unexpected attribute kind");
> }
> OS << "Attr";
> }
>
> Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=262275&r1=262274&r2=262275&view=diff
>
> ==============================================================================
> --- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)
> +++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Mon Feb 29 18:18:05 2016
> @@ -1718,8 +1718,6 @@ void EmitClangAttrImpl(RecordKeeper &Rec
> 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";
> @@ -1738,20 +1736,10 @@ void EmitClangAttrImpl(RecordKeeper &Rec
>
> } // end namespace clang
>
> -static void EmitAttrList(raw_ostream &OS, StringRef Class,
> +static void emitAttrList(raw_ostream &OS, StringRef Class,
> const std::vector<Record*> &AttrList) {
> - auto i = AttrList.cbegin(), e = AttrList.cend();
> -
> - if (i != e) {
> - // Move the end iterator back to emit the last attribute.
> - for(--e; i != e; ++i) {
> - if (!(*i)->getValueAsBit("ASTNode"))
> - continue;
> -
> - OS << Class << "(" << (*i)->getName() << ")\n";
> - }
> -
> - OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n";
> + for (auto Cur : AttrList) {
> + OS << Class << "(" << Cur->getName() << ")\n";
> }
> }
>
> @@ -1764,71 +1752,216 @@ static bool AttrHasPragmaSpelling(const
> }) != Spellings.end();
> }
>
> -namespace clang {
> -// Emits the enumeration list for attributes.
> -void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) {
> - emitSourceFileHeader("List of all attributes that Clang recognizes",
> OS);
> +namespace {
> + struct AttrClassDescriptor {
> + const char * const MacroName;
> + const char * const TableGenName;
> + };
> +}
>
> - OS << "#ifndef LAST_ATTR\n";
> - OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
> - OS << "#endif\n\n";
> +static const AttrClassDescriptor AttrClassDescriptors[] = {
> + { "ATTR", "Attr" },
> + { "INHERITABLE_ATTR", "InheritableAttr" },
> + { "INHERITABLE_PARAM_ATTR", "InheritableParamAttr" }
> +};
> +
> +static void emitDefaultDefine(raw_ostream &OS, StringRef name,
> + const char *superName) {
> + OS << "#ifndef " << name << "\n";
> + OS << "#define " << name << "(NAME) ";
> + if (superName) OS << superName << "(NAME)";
> + OS << "\n#endif\n\n";
> +}
> +
> +namespace {
> + /// A class of attributes.
> + struct AttrClass {
> + const AttrClassDescriptor &Descriptor;
> + Record *TheRecord;
> + AttrClass *SuperClass = nullptr;
> + std::vector<AttrClass*> SubClasses;
> + std::vector<Record*> Attrs;
> +
> + AttrClass(const AttrClassDescriptor &Descriptor, Record *R)
> + : Descriptor(Descriptor), TheRecord(R) {}
> +
> + void emitDefaultDefines(raw_ostream &OS) const {
> + // Default the macro unless this is a root class (i.e. Attr).
> + if (SuperClass) {
> + emitDefaultDefine(OS, Descriptor.MacroName,
> + SuperClass->Descriptor.MacroName);
> + }
> + }
>
> - OS << "#ifndef INHERITABLE_ATTR\n";
> - OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n";
> - OS << "#endif\n\n";
> + void emitUndefs(raw_ostream &OS) const {
> + OS << "#undef " << Descriptor.MacroName << "\n";
> + }
>
> - OS << "#ifndef LAST_INHERITABLE_ATTR\n";
> - OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
> - OS << "#endif\n\n";
> + void emitAttrList(raw_ostream &OS) const {
> + for (auto SubClass : SubClasses) {
> + SubClass->emitAttrList(OS);
> + }
>
> - OS << "#ifndef INHERITABLE_PARAM_ATTR\n";
> - OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n";
> - OS << "#endif\n\n";
> + ::emitAttrList(OS, Descriptor.MacroName, Attrs);
> + }
>
> - OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n";
> - OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)"
> - " INHERITABLE_PARAM_ATTR(NAME)\n";
> - OS << "#endif\n\n";
> + void classifyAttrOnRoot(Record *Attr) {
> + bool result = classifyAttr(Attr);
> + assert(result && "failed to classify on root"); (void) result;
> + }
>
> - OS << "#ifndef PRAGMA_SPELLING_ATTR\n";
> - OS << "#define PRAGMA_SPELLING_ATTR(NAME)\n";
> - OS << "#endif\n\n";
> + void emitAttrRange(raw_ostream &OS) const {
> + OS << "ATTR_RANGE(" << Descriptor.TableGenName
> + << ", " << getFirstAttr()->getName()
> + << ", " << getLastAttr()->getName() << ")\n";
> + }
>
> - OS << "#ifndef LAST_PRAGMA_SPELLING_ATTR\n";
> - OS << "#define LAST_PRAGMA_SPELLING_ATTR(NAME)
> PRAGMA_SPELLING_ATTR(NAME)\n";
> - OS << "#endif\n\n";
> + private:
> + bool classifyAttr(Record *Attr) {
> + // Check all the subclasses.
> + for (auto SubClass : SubClasses) {
> + if (SubClass->classifyAttr(Attr))
> + return true;
> + }
>
> - Record *InhClass = Records.getClass("InheritableAttr");
> - Record *InhParamClass = Records.getClass("InheritableParamAttr");
> - std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"),
> - NonInhAttrs, InhAttrs, InhParamAttrs, PragmaAttrs;
> + // It's not more specific than this class, but it might still
> belong here.
> + if (Attr->isSubClassOf(TheRecord)) {
> + Attrs.push_back(Attr);
> + return true;
> + }
> +
> + return false;
> + }
> +
> + Record *getFirstAttr() const {
> + if (!SubClasses.empty())
> + return SubClasses.front()->getFirstAttr();
> + return Attrs.front();
> + }
> +
> + Record *getLastAttr() const {
> + if (!Attrs.empty())
> + return Attrs.back();
> + return SubClasses.back()->getLastAttr();
> + }
> + };
> +
> + /// The entire hierarchy of attribute classes.
> + class AttrClassHierarchy {
> + std::vector<std::unique_ptr<AttrClass>> Classes;
> + public:
> + AttrClassHierarchy(RecordKeeper &Records) {
> + // Find records for all the classes.
> + for (auto &Descriptor : AttrClassDescriptors) {
> + Record *ClassRecord = Records.getClass(Descriptor.TableGenName);
> + AttrClass *Class = new AttrClass(Descriptor, ClassRecord);
> + Classes.emplace_back(Class);
> + }
> +
> + // Link up the hierarchy.
> + for (auto &Class : Classes) {
> + if (AttrClass *SuperClass = findSuperClass(Class->TheRecord)) {
> + Class->SuperClass = SuperClass;
> + SuperClass->SubClasses.push_back(Class.get());
> + }
> + }
> +
> +#ifndef NDEBUG
> + for (auto i = Classes.begin(), e = Classes.end(); i != e; ++i) {
> + assert((i == Classes.begin()) == ((*i)->SuperClass == nullptr) &&
> + "only the first class should be a root class!");
> + }
> +#endif
> + }
> +
> + void emitDefaultDefines(raw_ostream &OS) const {
> + for (auto &Class : Classes) {
> + Class->emitDefaultDefines(OS);
> + }
> + }
> +
> + void emitUndefs(raw_ostream &OS) const {
> + for (auto &Class : Classes) {
> + Class->emitUndefs(OS);
> + }
> + }
> +
> + void emitAttrLists(raw_ostream &OS) const {
> + // Just start from the root class.
> + Classes[0]->emitAttrList(OS);
> + }
> +
> + void emitAttrRanges(raw_ostream &OS) const {
> + for (auto &Class : Classes)
> + Class->emitAttrRange(OS);
> + }
> +
> + void classifyAttr(Record *Attr) {
> + // Add the attribute to the root class.
> + Classes[0]->classifyAttrOnRoot(Attr);
> + }
> +
> + private:
> + AttrClass *findClassByRecord(Record *R) const {
> + for (auto &Class : Classes) {
> + if (Class->TheRecord == R)
> + return Class.get();
> + }
> + return nullptr;
> + }
> +
> + AttrClass *findSuperClass(Record *R) const {
> + // TableGen flattens the superclass list, so we just need to walk it
> + // in reverse.
> + auto SuperClasses = R->getSuperClasses();
> + for (signed i = 0, e = SuperClasses.size(); i != e; ++i) {
> + auto SuperClass = findClassByRecord(SuperClasses[e - i -
> 1].first);
> + if (SuperClass) return SuperClass;
> + }
> + return nullptr;
> + }
> + };
> +}
> +
> +namespace clang {
> +// Emits the enumeration list for attributes.
> +void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) {
> + emitSourceFileHeader("List of all attributes that Clang recognizes",
> OS);
> +
> + AttrClassHierarchy Hierarchy(Records);
> +
> + // Add defaulting macro definitions.
> + Hierarchy.emitDefaultDefines(OS);
> + emitDefaultDefine(OS, "PRAGMA_SPELLING_ATTR", nullptr);
> +
> + std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
> + std::vector<Record *> PragmaAttrs;
> for (auto *Attr : Attrs) {
> if (!Attr->getValueAsBit("ASTNode"))
> continue;
>
> + // Add the attribute to the ad-hoc groups.
> if (AttrHasPragmaSpelling(Attr))
> PragmaAttrs.push_back(Attr);
>
> - if (Attr->isSubClassOf(InhParamClass))
> - InhParamAttrs.push_back(Attr);
> - else if (Attr->isSubClassOf(InhClass))
> - InhAttrs.push_back(Attr);
> - else
> - NonInhAttrs.push_back(Attr);
> + // Place it in the hierarchy.
> + Hierarchy.classifyAttr(Attr);
> }
>
> - EmitAttrList(OS, "PRAGMA_SPELLING_ATTR", PragmaAttrs);
> - EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs);
> - EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs);
> - EmitAttrList(OS, "ATTR", NonInhAttrs);
> -
> - OS << "#undef LAST_ATTR\n";
> - OS << "#undef INHERITABLE_ATTR\n";
> - OS << "#undef LAST_INHERITABLE_ATTR\n";
> - OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n";
> - OS << "#undef LAST_PRAGMA_ATTR\n";
> + // Emit the main attribute list.
> + Hierarchy.emitAttrLists(OS);
> +
> + // Emit the ad hoc groups.
> + emitAttrList(OS, "PRAGMA_SPELLING_ATTR", PragmaAttrs);
> +
> + // Emit the attribute ranges.
> + OS << "#ifdef ATTR_RANGE\n";
> + Hierarchy.emitAttrRanges(OS);
> + OS << "#undef ATTR_RANGE\n";
> + OS << "#endif\n";
> +
> + Hierarchy.emitUndefs(OS);
> OS << "#undef PRAGMA_SPELLING_ATTR\n";
> - OS << "#undef ATTR\n";
> }
>
> // Emits the code to read an attribute from a precompiled header.
> @@ -1841,8 +1974,6 @@ void EmitClangAttrPCHRead(RecordKeeper &
> std::vector<std::unique_ptr<Argument>> Args;
>
> OS << " switch (Kind) {\n";
> - OS << " default:\n";
> - OS << " llvm_unreachable(\"Unknown attribute!\");\n";
> for (const auto *Attr : Attrs) {
> const Record &R = *Attr;
> if (!R.getValueAsBit("ASTNode"))
> @@ -1882,9 +2013,6 @@ void EmitClangAttrPCHWrite(RecordKeeper
> std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
> Args;
>
> OS << " switch (A->getKind()) {\n";
> - OS << " default:\n";
> - OS << " llvm_unreachable(\"Unknown attribute kind!\");\n";
> - OS << " break;\n";
> for (const auto *Attr : Attrs) {
> const Record &R = *Attr;
> if (!R.getValueAsBit("ASTNode"))
> @@ -2075,11 +2203,7 @@ void EmitClangAttrSpellingListIndex(Reco
> emitSourceFileHeader("Code to translate different attribute spellings "
> "into internal identifiers", OS);
>
> - OS <<
> - " switch (AttrKind) {\n"
> - " default:\n"
> - " llvm_unreachable(\"Unknown attribute kind!\");\n"
> - " break;\n";
> + OS << " switch (AttrKind) {\n";
>
> ParsedAttrMap Attrs = getParsedAttrList(Records);
> for (const auto &I : Attrs) {
> @@ -2159,9 +2283,7 @@ void EmitClangAttrASTVisitor(RecordKeepe
> << " if (!A)\n"
> << " return true;\n"
> << "\n"
> - << " switch (A->getKind()) {\n"
> - << " default:\n"
> - << " return true;\n";
> + << " switch (A->getKind()) {\n";
>
> for (const auto *Attr : Attrs) {
> const Record &R = *Attr;
> @@ -2188,9 +2310,7 @@ void EmitClangAttrTemplateInstantiate(Re
> << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext
> &C, "
> << "Sema &S,\n"
> << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n"
> - << " switch (At->getKind()) {\n"
> - << " default:\n"
> - << " break;\n";
> + << " switch (At->getKind()) {\n";
>
> for (const auto *Attr : Attrs) {
> const Record &R = *Attr;
> @@ -2788,11 +2908,7 @@ void EmitClangAttrParsedAttrKinds(Record
> 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";
> + OS << " switch (A->getKind()) {\n";
> std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
> Args;
> for (const auto *Attr : Attrs) {
> const Record &R = *Attr;
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160229/046b7ac6/attachment-0001.html>
More information about the cfe-commits
mailing list