> On Feb 29, 2016, at 5:44 PM, Sean Silva <chisophu...@gmail.com> wrote: > 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 > > <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 > > <http://llvm.org/docs/CodingStandards.html#don-t-use-default-labels-in-fully-covered-switches-over-enumerations> Sorry, should be fixed in r262288. I’ll be back in a few hours, feel free to revert if it doesn’t clear up.
John. > > -- Sean Silva > > On Mon, Feb 29, 2016 at 4:18 PM, John McCall via cfe-commits > <cfe-commits@lists.llvm.org <mailto:cfe-commits@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 > <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 > > <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 > > <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 > > <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 > > <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@lists.llvm.org <mailto:cfe-commits@lists.llvm.org> > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits > <http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits> >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits