r262275 - Infrastructure improvements to Clang attribute TableGen.

Sean Silva via cfe-commits cfe-commits at lists.llvm.org
Mon Feb 29 18:38:47 PST 2016


All green on the two latest commits. Thanks!
http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast/builds/961

-- Sean Silva

On Mon, Feb 29, 2016 at 6:14 PM, John McCall <rjmccall at apple.com> wrote:

> On Feb 29, 2016, at 5:44 PM, Sean Silva <chisophugis at 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
>
> 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
>
>
> 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 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/fc50b511/attachment-0001.html>


More information about the cfe-commits mailing list