john.brawn updated this revision to Diff 239295.
john.brawn retitled this revision from "Move ParsedAttrInfos into a registry 
and point to one in AttributeList" to "Move ParsedAttrInfos into a registry and 
point to one in ParsedAttr".
john.brawn added reviewers: erichkeane, aaron.ballman, rjmccall.
john.brawn set the repository for this revision to rG LLVM Github Monorepo.
john.brawn added a subscriber: cfe-commits.
john.brawn added a comment.
Herald added a project: clang.

Resurrecting this old patch, with a bunch of changes due to the changes around 
AttributeCommonInfo. This is the second of four patches to make it possible for 
clang plugins to define attributes.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D31338/new/

https://reviews.llvm.org/D31338

Files:
  clang/include/clang/Sema/CMakeLists.txt
  clang/include/clang/Sema/ParsedAttr.h
  clang/lib/Basic/Attributes.cpp
  clang/lib/Sema/ParsedAttr.cpp
  clang/utils/TableGen/ClangAttrEmitter.cpp
  clang/utils/TableGen/TableGen.cpp
  clang/utils/TableGen/TableGenBackends.h

Index: clang/utils/TableGen/TableGenBackends.h
===================================================================
--- clang/utils/TableGen/TableGenBackends.h
+++ clang/utils/TableGen/TableGenBackends.h
@@ -55,8 +55,6 @@
                                  llvm::raw_ostream &OS);
 void EmitClangAttrParsedAttrImpl(llvm::RecordKeeper &Records,
                                  llvm::raw_ostream &OS);
-void EmitClangAttrParsedAttrKinds(llvm::RecordKeeper &Records,
-                                  llvm::raw_ostream &OS);
 void EmitClangAttrTextNodeDump(llvm::RecordKeeper &Records,
                                llvm::raw_ostream &OS);
 void EmitClangAttrNodeTraverse(llvm::RecordKeeper &Records,
Index: clang/utils/TableGen/TableGen.cpp
===================================================================
--- clang/utils/TableGen/TableGen.cpp
+++ clang/utils/TableGen/TableGen.cpp
@@ -39,7 +39,6 @@
   GenClangAttrTemplateInstantiate,
   GenClangAttrParsedAttrList,
   GenClangAttrParsedAttrImpl,
-  GenClangAttrParsedAttrKinds,
   GenClangAttrTextNodeDump,
   GenClangAttrNodeTraverse,
   GenClangBasicReader,
@@ -122,9 +121,6 @@
         clEnumValN(GenClangAttrParsedAttrImpl,
                    "gen-clang-attr-parsed-attr-impl",
                    "Generate the clang parsed attribute helpers"),
-        clEnumValN(GenClangAttrParsedAttrKinds,
-                   "gen-clang-attr-parsed-attr-kinds",
-                   "Generate a clang parsed attribute kinds"),
         clEnumValN(GenClangAttrTextNodeDump, "gen-clang-attr-text-node-dump",
                    "Generate clang attribute text node dumper"),
         clEnumValN(GenClangAttrNodeTraverse, "gen-clang-attr-node-traverse",
@@ -257,9 +253,6 @@
   case GenClangAttrParsedAttrImpl:
     EmitClangAttrParsedAttrImpl(Records, OS);
     break;
-  case GenClangAttrParsedAttrKinds:
-    EmitClangAttrParsedAttrKinds(Records, OS);
-    break;
   case GenClangAttrTextNodeDump:
     EmitClangAttrTextNodeDump(Records, OS);
     break;
Index: clang/utils/TableGen/ClangAttrEmitter.cpp
===================================================================
--- clang/utils/TableGen/ClangAttrEmitter.cpp
+++ clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -158,12 +158,14 @@
 typedef std::vector<std::pair<std::string, const Record *>> ParsedAttrMap;
 
 static ParsedAttrMap getParsedAttrList(const RecordKeeper &Records,
-                                       ParsedAttrMap *Dupes = nullptr) {
+                                       ParsedAttrMap *Dupes = nullptr,
+                                       bool IncludeIgnored = false) {
   std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
   std::set<std::string> Seen;
   ParsedAttrMap R;
   for (const auto *Attr : Attrs) {
-    if (Attr->getValueAsBit("SemaHandler")) {
+    if (Attr->getValueAsBit("SemaHandler") ||
+        (IncludeIgnored && Attr->getValueAsBit("Ignored"))) {
       std::string AN;
       if (Attr->isSubClassOf("TargetSpecificAttr") &&
           !Attr->isValueUnset("ParseKind")) {
@@ -3590,9 +3592,10 @@
       getPragmaAttributeSupport(Records);
 
   // Get the list of parsed attributes, and accept the optional list of
-  // duplicates due to the ParseKind.
+  // duplicates due to the ParseKind. We also want to include ignored
+  // attributes as we want them to be successfully matched.
   ParsedAttrMap Dupes;
-  ParsedAttrMap Attrs = getParsedAttrList(Records, &Dupes);
+  ParsedAttrMap Attrs = getParsedAttrList(Records, &Dupes, true);
 
   // Generate the appertainsTo diagnostic methods and write their names into
   // another mapping. At the same time, generate the AttrInfoMap object
@@ -3608,10 +3611,18 @@
     // the spellings are identical, and custom parsing rules match, etc.
 
     // We need to generate struct instances based off ParsedAttrInfo from
-    // ParsedAttr.cpp.
+    // ParsedAttr.h.
     const Record &Attr = *I->second;
-    SS << "struct ParsedAttrInfo" << I->first << " : public ParsedAttrInfo {\n";
-    SS << "  ParsedAttrInfo" << I->first << "() {\n";
+    const std::string &AttrName = I->first;
+    std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
+    std::string AttrInfoName = "AttrInfo" + AttrName;
+    SS << "struct " << AttrInfoName << " : public ParsedAttrInfo {\n";
+    SS << "  " << AttrInfoName << "() {\n";
+    if (Attr.getValueAsBit("Ignored")) {
+      SS << "    AttrKind = ParsedAttr::IgnoredAttribute;\n";
+    } else {
+      SS << "    AttrKind = ParsedAttr::AT_" << AttrName << ";\n";
+    }
     emitArgInfo(Attr, SS);
     SS << "    HasCustomParsing = ";
     SS << Attr.getValueAsBit("HasCustomParsing") << ";\n";
@@ -3626,6 +3637,20 @@
     SS << IsKnownToGCC(Attr) << ";\n";
     SS << "    IsSupportedByPragmaAttribute = ";
     SS << PragmaAttributeSupport.isAttributedSupported(*I->second) << ";\n";
+    for (const auto &S : Spellings) {
+      const std::string &RawSpelling = S.name();
+      std::string Spelling;
+      if (S.variety() == "CXX11" || S.variety() == "C2x") {
+        Spelling += S.nameSpace();
+        Spelling += "::";
+      }
+      if (S.variety() == "GNU")
+        Spelling += NormalizeGNUAttrSpelling(RawSpelling);
+      else
+        Spelling += RawSpelling;
+      SS << "    Spellings.push_back({AttributeCommonInfo::AS_" << S.variety();
+      SS << ",\"" << Spelling << "\"});\n";
+    }
     SS << "  }\n";
     GenerateAppertainsTo(Attr, SS, OS);
     GenerateLangOptRequirements(Attr, SS);
@@ -3633,120 +3658,15 @@
     GenerateSpellingIndexToSemanticSpelling(Attr, SS);
     PragmaAttributeSupport.generateStrictConformsTo(*I->second, SS);
     SS << "};\n";
-    SS << "ParsedAttrInfo" << I->first;
-    SS << " parsedAttrInfo" << I->first << "Instance;\n\n";
+    SS << "static ParsedAttrInfoRegistry::Add<" << AttrInfoName << "> ";
+    SS << AttrInfoName << "Instance(\"" << AttrName << "\",\"\");\n";
   }
   OS << SS.str();
 
-  OS << "static const ParsedAttrInfo *AttrInfoMap[ParsedAttr::UnknownAttribute "
-        "+ 1] = {\n";
-  for (auto I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {
-    OS << "&parsedAttrInfo" << I->first << "Instance,\n";
-  }
-  OS << "};\n\n";
-
   // Generate the attribute match rules.
   emitAttributeMatchRules(PragmaAttributeSupport, OS);
 }
 
-// Emits the kind list of parsed attributes
-void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
-  emitSourceFileHeader("Attribute name matcher", OS);
-
-  std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
-  std::vector<StringMatcher::StringPair> GNU, Declspec, Microsoft, CXX11,
-      Keywords, Pragma, C2x;
-  std::set<std::string> Seen;
-  for (const auto *A : Attrs) {
-    const Record &Attr = *A;
-
-    bool SemaHandler = Attr.getValueAsBit("SemaHandler");
-    bool Ignored = Attr.getValueAsBit("Ignored");
-    if (SemaHandler || Ignored) {
-      // Attribute spellings can be shared between target-specific attributes,
-      // and can be shared between syntaxes for the same attribute. For
-      // instance, an attribute can be spelled GNU<"interrupt"> for an ARM-
-      // specific attribute, or MSP430-specific attribute. Additionally, an
-      // attribute can be spelled GNU<"dllexport"> and Declspec<"dllexport">
-      // for the same semantic attribute. Ultimately, we need to map each of
-      // these to a single AttributeCommonInfo::Kind value, but the
-      // StringMatcher class cannot handle duplicate match strings. So we
-      // generate a list of string to match based on the syntax, and emit
-      // multiple string matchers depending on the syntax used.
-      std::string AttrName;
-      if (Attr.isSubClassOf("TargetSpecificAttr") &&
-          !Attr.isValueUnset("ParseKind")) {
-        AttrName = Attr.getValueAsString("ParseKind");
-        if (Seen.find(AttrName) != Seen.end())
-          continue;
-        Seen.insert(AttrName);
-      } else
-        AttrName = NormalizeAttrName(StringRef(Attr.getName())).str();
-
-      std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
-      for (const auto &S : Spellings) {
-        const std::string &RawSpelling = S.name();
-        std::vector<StringMatcher::StringPair> *Matches = nullptr;
-        std::string Spelling;
-        const std::string &Variety = S.variety();
-        if (Variety == "CXX11") {
-          Matches = &CXX11;
-          Spelling += S.nameSpace();
-          Spelling += "::";
-        } else if (Variety == "C2x") {
-          Matches = &C2x;
-          Spelling += S.nameSpace();
-          Spelling += "::";
-        } else if (Variety == "GNU")
-          Matches = &GNU;
-        else if (Variety == "Declspec")
-          Matches = &Declspec;
-        else if (Variety == "Microsoft")
-          Matches = &Microsoft;
-        else if (Variety == "Keyword")
-          Matches = &Keywords;
-        else if (Variety == "Pragma")
-          Matches = &Pragma;
-
-        assert(Matches && "Unsupported spelling variety found");
-
-        if (Variety == "GNU")
-          Spelling += NormalizeGNUAttrSpelling(RawSpelling);
-        else
-          Spelling += RawSpelling;
-
-        if (SemaHandler)
-          Matches->push_back(StringMatcher::StringPair(
-              Spelling, "return AttributeCommonInfo::AT_" + AttrName + ";"));
-        else
-          Matches->push_back(StringMatcher::StringPair(
-              Spelling, "return AttributeCommonInfo::IgnoredAttribute;"));
-      }
-    }
-  }
-
-  OS << "static AttributeCommonInfo::Kind getAttrKind(StringRef Name, ";
-  OS << "AttributeCommonInfo::Syntax Syntax) {\n";
-  OS << "  if (AttributeCommonInfo::AS_GNU == Syntax) {\n";
-  StringMatcher("Name", GNU, OS).Emit();
-  OS << "  } else if (AttributeCommonInfo::AS_Declspec == Syntax) {\n";
-  StringMatcher("Name", Declspec, OS).Emit();
-  OS << "  } else if (AttributeCommonInfo::AS_Microsoft == Syntax) {\n";
-  StringMatcher("Name", Microsoft, OS).Emit();
-  OS << "  } else if (AttributeCommonInfo::AS_CXX11 == Syntax) {\n";
-  StringMatcher("Name", CXX11, OS).Emit();
-  OS << "  } else if (AttributeCommonInfo::AS_C2x == Syntax) {\n";
-  StringMatcher("Name", C2x, OS).Emit();
-  OS << "  } else if (AttributeCommonInfo::AS_Keyword == Syntax || ";
-  OS << "AttributeCommonInfo::AS_ContextSensitiveKeyword == Syntax) {\n";
-  StringMatcher("Name", Keywords, OS).Emit();
-  OS << "  } else if (AttributeCommonInfo::AS_Pragma == Syntax) {\n";
-  StringMatcher("Name", Pragma, OS).Emit();
-  OS << "  }\n";
-  OS << "  return AttributeCommonInfo::UnknownAttribute;\n"
-     << "}\n";
-}
-
 // Emits the code to dump an attribute.
 void EmitClangAttrTextNodeDump(RecordKeeper &Records, raw_ostream &OS) {
   emitSourceFileHeader("Attribute text node dumper", OS);
Index: clang/lib/Sema/ParsedAttr.cpp
===================================================================
--- clang/lib/Sema/ParsedAttr.cpp
+++ clang/lib/Sema/ParsedAttr.cpp
@@ -100,64 +100,24 @@
   pool.Attrs.clear();
 }
 
-struct ParsedAttrInfo {
-  unsigned NumArgs : 4;
-  unsigned OptArgs : 4;
-  unsigned HasCustomParsing : 1;
-  unsigned IsTargetSpecific : 1;
-  unsigned IsType : 1;
-  unsigned IsStmt : 1;
-  unsigned IsKnownToGCC : 1;
-  unsigned IsSupportedByPragmaAttribute : 1;
-
-  virtual bool diagAppertainsToDecl(Sema &S, const ParsedAttr &Attr,
-                                    const Decl *) const {
-    return true;
-  }
-  virtual bool diagLangOpts(Sema &S, const ParsedAttr &Attr) const {
-    return true;
-  }
-  virtual bool existsInTarget(const TargetInfo &Target) const {
-    return true;
-  }
-  virtual unsigned
-  spellingIndexToSemanticSpelling(const ParsedAttr &Attr) const {
-    return UINT_MAX;
-  }
-  virtual void getPragmaAttributeMatchRules(
-    llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &Rules,
-    const LangOptions &LangOpts) const {
-  }
-};
-
 namespace {
 
 #include "clang/Sema/AttrParsedAttrImpl.inc"
 
 } // namespace
 
-static ParsedAttrInfo DefaultParsedAttrInfo;
-static const ParsedAttrInfo &getInfo(const ParsedAttr &A) {
-  // If we have a ParsedAttrInfo for this ParsedAttr then return that,
-  // otherwise return a default ParsedAttrInfo.
-  const ParsedAttrInfo *Info = AttrInfoMap[A.getKind()];
-  if (Info)
-    return *Info;
-  return DefaultParsedAttrInfo;
-}
-
-unsigned ParsedAttr::getMinArgs() const { return getInfo(*this).NumArgs; }
+unsigned ParsedAttr::getMinArgs() const { return getInfo().NumArgs; }
 
 unsigned ParsedAttr::getMaxArgs() const {
-  return getMinArgs() + getInfo(*this).OptArgs;
+  return getMinArgs() + getInfo().OptArgs;
 }
 
 bool ParsedAttr::hasCustomParsing() const {
-  return getInfo(*this).HasCustomParsing;
+  return getInfo().HasCustomParsing;
 }
 
 bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
-  return getInfo(*this).diagAppertainsToDecl(S, *this, D);
+  return getInfo().diagAppertainsToDecl(S, *this, D);
 }
 
 bool ParsedAttr::appliesToDecl(const Decl *D,
@@ -169,33 +129,33 @@
     const LangOptions &LangOpts,
     SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
     const {
-  return getInfo(*this).getPragmaAttributeMatchRules(MatchRules, LangOpts);
+  return getInfo().getPragmaAttributeMatchRules(MatchRules, LangOpts);
 }
 
 bool ParsedAttr::diagnoseLangOpts(Sema &S) const {
-  return getInfo(*this).diagLangOpts(S, *this);
+  return getInfo().diagLangOpts(S, *this);
 }
 
 bool ParsedAttr::isTargetSpecificAttr() const {
-  return getInfo(*this).IsTargetSpecific;
+  return getInfo().IsTargetSpecific;
 }
 
-bool ParsedAttr::isTypeAttr() const { return getInfo(*this).IsType; }
+bool ParsedAttr::isTypeAttr() const { return getInfo().IsType; }
 
-bool ParsedAttr::isStmtAttr() const { return getInfo(*this).IsStmt; }
+bool ParsedAttr::isStmtAttr() const { return getInfo().IsStmt; }
 
 bool ParsedAttr::existsInTarget(const TargetInfo &Target) const {
-  return getInfo(*this).existsInTarget(Target);
+  return getInfo().existsInTarget(Target);
 }
 
-bool ParsedAttr::isKnownToGCC() const { return getInfo(*this).IsKnownToGCC; }
+bool ParsedAttr::isKnownToGCC() const { return getInfo().IsKnownToGCC; }
 
 bool ParsedAttr::isSupportedByPragmaAttribute() const {
-  return getInfo(*this).IsSupportedByPragmaAttribute;
+  return getInfo().IsSupportedByPragmaAttribute;
 }
 
 unsigned ParsedAttr::getSemanticSpelling() const {
-  return getInfo(*this).spellingIndexToSemanticSpelling(*this);
+  return getInfo().spellingIndexToSemanticSpelling(*this);
 }
 
 bool ParsedAttr::hasVariadicArg() const {
@@ -203,5 +163,5 @@
   // claim that as being variadic. If we someday get an attribute that
   // legitimately bumps up against that maximum, we can use another bit to track
   // whether it's truly variadic or not.
-  return getInfo(*this).OptArgs == 15;
+  return getInfo().OptArgs == 15;
 }
Index: clang/lib/Basic/Attributes.cpp
===================================================================
--- clang/lib/Basic/Attributes.cpp
+++ clang/lib/Basic/Attributes.cpp
@@ -2,9 +2,12 @@
 #include "clang/Basic/AttrSubjectMatchRules.h"
 #include "clang/Basic/AttributeCommonInfo.h"
 #include "clang/Basic/IdentifierTable.h"
+#include "clang/Sema/ParsedAttr.h"
 #include "llvm/ADT/StringSwitch.h"
 using namespace clang;
 
+LLVM_INSTANTIATE_REGISTRY(ParsedAttrInfoRegistry)
+
 int clang::hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope,
                         const IdentifierInfo *Attr, const TargetInfo &Target,
                         const LangOptions &LangOpts) {
@@ -72,12 +75,10 @@
   return ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"));
 }
 
-#include "clang/Sema/AttrParsedAttrKinds.inc"
-
-AttributeCommonInfo::Kind
-AttributeCommonInfo::getParsedKind(const IdentifierInfo *Name,
-                                   const IdentifierInfo *ScopeName,
-                                   Syntax SyntaxUsed) {
+std::unique_ptr<ParsedAttrInfo>
+ParsedAttrInfo::get(const IdentifierInfo *Name,
+                    const IdentifierInfo *ScopeName,
+                    AttributeCommonInfo::Syntax SyntaxUsed) {
   StringRef AttrName = Name->getName();
 
   SmallString<64> FullName;
@@ -88,11 +89,51 @@
 
   // Ensure that in the case of C++11 attributes, we look for '::foo' if it is
   // unscoped.
-  if (ScopeName || SyntaxUsed == AS_CXX11 || SyntaxUsed == AS_C2x)
+  if (ScopeName || SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
+      SyntaxUsed == AttributeCommonInfo::AS_C2x)
     FullName += "::";
   FullName += AttrName;
 
-  return ::getAttrKind(FullName, SyntaxUsed);
+  if (SyntaxUsed == AttributeCommonInfo::AS_ContextSensitiveKeyword)
+    SyntaxUsed = AttributeCommonInfo::AS_Keyword;
+
+  // Search for a ParsedAttrInfo whose name and syntax match
+  for (ParsedAttrInfoRegistry::iterator it = ParsedAttrInfoRegistry::begin(),
+                                        ie = ParsedAttrInfoRegistry::end();
+       it != ie; ++it) {
+    std::unique_ptr<ParsedAttrInfo> P = it->instantiate();
+    for (auto &S : P->Spellings) {
+      if (S.Syntax == SyntaxUsed && FullName.equals(S.Spelling)) {
+        return P;
+      }
+    }
+  }
+
+  // If we failed to find a match then the attribute is unknown
+  return std::make_unique<ParsedAttrInfo>();
+}
+
+std::unique_ptr<ParsedAttrInfo>
+ParsedAttrInfo::get(AttributeCommonInfo::Kind K) {
+  // Search for a ParsedAttrInfo whose kind matches
+  for (ParsedAttrInfoRegistry::iterator it = ParsedAttrInfoRegistry::begin(),
+                                        ie = ParsedAttrInfoRegistry::end();
+       it != ie; ++it) {
+    std::unique_ptr<ParsedAttrInfo> P = it->instantiate();
+    if (P->AttrKind == K) {
+      return P;
+    }
+  }
+
+  // If we failed to find a match then the attribute is unknown
+  return std::make_unique<ParsedAttrInfo>();
+}
+
+AttributeCommonInfo::Kind
+AttributeCommonInfo::getParsedKind(const IdentifierInfo *Name,
+                                   const IdentifierInfo *ScopeName,
+                                   Syntax SyntaxUsed) {
+  return Kind(ParsedAttrInfo::get(Name, ScopeName, SyntaxUsed)->AttrKind);
 }
 
 unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const {
Index: clang/include/clang/Sema/ParsedAttr.h
===================================================================
--- clang/include/clang/Sema/ParsedAttr.h
+++ clang/include/clang/Sema/ParsedAttr.h
@@ -24,6 +24,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/TinyPtrVector.h"
 #include "llvm/Support/Allocator.h"
+#include "llvm/Support/Registry.h"
 #include "llvm/Support/VersionTuple.h"
 #include <cassert>
 #include <cstddef>
@@ -37,6 +38,74 @@
 class Expr;
 class IdentifierInfo;
 class LangOptions;
+class ParsedAttr;
+class Sema;
+
+struct ParsedAttrInfo {
+  /// Corresponds to the Kind enum
+  unsigned AttrKind : 16;
+  /// The number of required arguments of this attribute
+  unsigned NumArgs : 4;
+  /// The number of optional arguments of this attributes
+  unsigned OptArgs : 4;
+  /// True if the parsing does not match the semantic content
+  unsigned HasCustomParsing : 1;
+  /// True if this attribute is only available for certain targets
+  unsigned IsTargetSpecific : 1;
+  /// True if this attribute applies to types
+  unsigned IsType : 1;
+  /// True if this attribute applies to statements
+  unsigned IsStmt : 1;
+  /// True if this attribute has any spellings that are known to gcc
+  unsigned IsKnownToGCC : 1;
+  /// True if this attribute is supported by #pragma clang attribute
+  unsigned IsSupportedByPragmaAttribute : 1;
+  // The syntaxes supported by this attribute and how they're spelt
+  struct Spelling {
+    AttributeCommonInfo::Syntax Syntax;
+    std::string Spelling;
+  };
+  std::vector<Spelling> Spellings;
+
+  ParsedAttrInfo()
+      : AttrKind(AttributeCommonInfo::UnknownAttribute), NumArgs(0), OptArgs(0),
+        HasCustomParsing(0), IsTargetSpecific(0), IsType(0), IsStmt(0),
+        IsKnownToGCC(0), IsSupportedByPragmaAttribute(0) {}
+
+  virtual ~ParsedAttrInfo() {}
+
+  /// Check if this attribute appertains to D, and issue a diagnostic if not
+  virtual bool diagAppertainsToDecl(Sema &S, const ParsedAttr &Attr,
+                                    const Decl *D) const {
+    return true;
+  }
+  /// Check if this attribute is allowed by the language we are compiling, and
+  /// issue a diagnostic if not
+  virtual bool diagLangOpts(Sema &S, const ParsedAttr &Attr) const {
+    return true;
+  }
+  /// Check if this attribute is allowed when compiling for the given target
+  virtual bool existsInTarget(const TargetInfo &Target) const {
+    return true;
+  }
+  /// Convert the spelling index of Attr to a semantic spelling enum value
+  virtual unsigned
+  spellingIndexToSemanticSpelling(const ParsedAttr &Attr) const {
+    return UINT_MAX;
+  }
+  /// Populate Rules with the match rules of this attribute
+  virtual void getPragmaAttributeMatchRules(
+      llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &Rules,
+      const LangOptions &LangOpts) const {
+  }
+
+  static std::unique_ptr<ParsedAttrInfo> get(AttributeCommonInfo::Kind);
+  static std::unique_ptr<ParsedAttrInfo>
+  get(const IdentifierInfo *Name, const IdentifierInfo *ScopeName,
+      AttributeCommonInfo::Syntax SyntaxUsed);
+};
+
+typedef llvm::Registry<ParsedAttrInfo> ParsedAttrInfoRegistry;
 
 /// Represents information about a change in availability for
 /// an entity, which is part of the encoding of the 'availability'
@@ -181,6 +250,8 @@
 
   const Expr *MessageExpr;
 
+  std::unique_ptr<ParsedAttrInfo> Info;
+
   ArgsUnion *getArgsBuffer() { return getTrailingObjects<ArgsUnion>(); }
   ArgsUnion const *getArgsBuffer() const {
     return getTrailingObjects<ArgsUnion>();
@@ -207,7 +278,8 @@
         EllipsisLoc(ellipsisLoc), NumArgs(numArgs), Invalid(false),
         UsedAsTypeAttr(false), IsAvailability(false),
         IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
-        HasProcessingCache(false), IsPragmaClangAttribute(false) {
+        HasProcessingCache(false), IsPragmaClangAttribute(false),
+        Info(ParsedAttrInfo::get(getParsedKind())) {
     if (numArgs)
       memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion));
   }
@@ -225,7 +297,8 @@
         NumArgs(1), Invalid(false), UsedAsTypeAttr(false), IsAvailability(true),
         IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
         HasProcessingCache(false), IsPragmaClangAttribute(false),
-        UnavailableLoc(unavailable), MessageExpr(messageExpr) {
+        UnavailableLoc(unavailable), MessageExpr(messageExpr),
+        Info(ParsedAttrInfo::get(getParsedKind())) {
     ArgsUnion PVal(Parm);
     memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
     new (getAvailabilityData()) detail::AvailabilityData(
@@ -242,7 +315,8 @@
         NumArgs(3), Invalid(false), UsedAsTypeAttr(false),
         IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false),
         HasParsedType(false), HasProcessingCache(false),
-        IsPragmaClangAttribute(false) {
+        IsPragmaClangAttribute(false),
+        Info(ParsedAttrInfo::get(getParsedKind())) {
     ArgsUnion *Args = getArgsBuffer();
     Args[0] = Parm1;
     Args[1] = Parm2;
@@ -259,7 +333,8 @@
         NumArgs(1), Invalid(false), UsedAsTypeAttr(false),
         IsAvailability(false), IsTypeTagForDatatype(true), IsProperty(false),
         HasParsedType(false), HasProcessingCache(false),
-        IsPragmaClangAttribute(false) {
+        IsPragmaClangAttribute(false),
+        Info(ParsedAttrInfo::get(getParsedKind())) {
     ArgsUnion PVal(ArgKind);
     memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
     detail::TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot();
@@ -277,7 +352,8 @@
         NumArgs(0), Invalid(false), UsedAsTypeAttr(false),
         IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false),
         HasParsedType(true), HasProcessingCache(false),
-        IsPragmaClangAttribute(false) {
+        IsPragmaClangAttribute(false),
+        Info(ParsedAttrInfo::get(getParsedKind())) {
     new (&getTypeBuffer()) ParsedType(typeArg);
   }
 
@@ -291,7 +367,8 @@
         NumArgs(0), Invalid(false), UsedAsTypeAttr(false),
         IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(true),
         HasParsedType(false), HasProcessingCache(false),
-        IsPragmaClangAttribute(false) {
+        IsPragmaClangAttribute(false),
+        Info(ParsedAttrInfo::get(getParsedKind())) {
     new (&getPropertyDataBuffer()) detail::PropertyData(getterId, setterId);
   }
 
@@ -535,6 +612,7 @@
   }
 
   AttributeCommonInfo::Kind getKind() const { return getParsedKind(); }
+  ParsedAttrInfo &getInfo() const { return *Info; }
 };
 
 class AttributePool;
Index: clang/include/clang/Sema/CMakeLists.txt
===================================================================
--- clang/include/clang/Sema/CMakeLists.txt
+++ clang/include/clang/Sema/CMakeLists.txt
@@ -8,11 +8,6 @@
   SOURCE ../Basic/Attr.td
   TARGET ClangAttrParsedAttrList)
 
-clang_tablegen(AttrParsedAttrKinds.inc -gen-clang-attr-parsed-attr-kinds
-  -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
-  SOURCE ../Basic/Attr.td
-  TARGET ClangAttrParsedAttrKinds)
-
 clang_tablegen(AttrSpellingListIndex.inc -gen-clang-attr-spelling-index
   -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
   SOURCE ../Basic/Attr.td
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to