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