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