vsapsai created this revision.
vsapsai added reviewers: aaron.ballman, ChuanqiXu, erichkeane.
Herald added a subscriber: ributzka.
Herald added a project: All.
vsapsai requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

In this change deliberately keeping the tests intact to make sure
TableGen implementation works the same way as the manual one.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D138859

Files:
  clang/include/clang/AST/Attr.h
  clang/include/clang/Basic/Attr.td
  clang/lib/AST/AttrImpl.cpp
  clang/lib/AST/ODRHash.cpp
  clang/utils/TableGen/ClangAttrEmitter.cpp

Index: clang/utils/TableGen/ClangAttrEmitter.cpp
===================================================================
--- clang/utils/TableGen/ClangAttrEmitter.cpp
+++ clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -249,6 +249,7 @@
     virtual void writeDump(raw_ostream &OS) const = 0;
     virtual void writeDumpChildren(raw_ostream &OS) const {}
     virtual void writeHasChildren(raw_ostream &OS) const { OS << "false"; }
+    virtual void writeODRHashing(raw_ostream &OS) const {}
 
     virtual bool isEnumArg() const { return false; }
     virtual bool isVariadicEnumArg() const { return false; }
@@ -647,6 +648,20 @@
     void writeHasChildren(raw_ostream &OS) const override {
       OS << "SA->is" << getUpperName() << "Expr()";
     }
+
+    void writeODRHashing(raw_ostream &OS) const override {
+      OS << "  ID.AddBoolean(is" << getUpperName() << "Expr());\n";
+      OS << "  if (is" << getUpperName() << "Expr()) {\n";
+      OS << "    const Expr *" << getUpperName() << "Expr = "
+         << "get" << getUpperName() << "Expr();\n";
+      OS << "    ID.AddBoolean(" << getUpperName() << "Expr);\n";
+      OS << "    if (" << getUpperName() << "Expr)\n"
+         << "      Hash.AddStmt(" << getUpperName() << "Expr);\n";
+      OS << "  } else {\n";
+      OS << "    ID.AddString(get" << getUpperName()
+         << "Type()->getType().getAsString());\n";
+      OS << "  }\n";
+    }
   };
 
   class VariadicArgument : public Argument {
@@ -1006,6 +1021,10 @@
          << "  llvm_unreachable(\"No enumerator with that value\");\n"
          << "}\n";
     }
+
+    void writeODRHashing(raw_ostream &OS) const override {
+      OS << "  ID.AddInteger(get" << getUpperName() << "());\n";
+    }
   };
 
   class VariadicEnumArgument: public VariadicArgument {
@@ -1230,6 +1249,14 @@
     }
 
     void writeHasChildren(raw_ostream &OS) const override { OS << "true"; }
+
+    void writeODRHashing(raw_ostream &OS) const override {
+      OS << "  const Expr *" << getUpperName() << "Expr = "
+         << "get" << getUpperName() << "();\n";
+      OS << "  ID.AddBoolean(" << getUpperName() << "Expr);\n";
+      OS << "  if (" << getUpperName() << "Expr)\n"
+         << "    Hash.AddStmt(" << getUpperName() << "Expr);\n";
+    }
   };
 
   class VariadicExprArgument : public VariadicArgument {
@@ -1624,6 +1651,27 @@
   OS << "}\n\n";
 }
 
+static void
+writeProcessODRHashFunction(const Record &R,
+                            const std::vector<std::unique_ptr<Argument>> &Args,
+                            raw_ostream &OS) {
+  OS << "void " << R.getName() << "Attr::processODRHash(\n"
+     << "    llvm::FoldingSetNodeID &ID, ODRHash &Hash) const {\n";
+  if (!R.getValueAsBit("IsODRHashable")) {
+    OS << "  // Not ODR-hashable\n}\n\n";
+    return;
+  }
+
+  OS << "  ID.AddInteger(Attr::getKind());\n";
+  for (const auto &Arg : Args) {
+    if (Arg->isFake())
+      continue;
+    Arg->writeODRHashing(OS);
+  }
+  // End of the processODRHash function.
+  OS << "}\n\n";
+}
+
 /// Return the index of a spelling in a spelling list.
 static unsigned
 getSpellingListIndex(const std::vector<FlattenedSpelling> &SpellingList,
@@ -2683,7 +2731,8 @@
       }
       OS << "\n  : " << SuperName << "(Ctx, CommonInfo, ";
       OS << "attr::" << R.getName() << ", "
-         << (R.getValueAsBit("LateParsed") ? "true" : "false");
+         << (R.getValueAsBit("LateParsed") ? "true" : "false") << ", "
+         << (R.getValueAsBit("IsODRHashable") ? "true" : "false");
       if (Inheritable) {
         OS << ", "
            << (R.getValueAsBit("InheritEvenIfAlreadyPresent") ? "true"
@@ -2746,6 +2795,8 @@
       OS << "  void printPretty(raw_ostream &OS,\n"
          << "                   const PrintingPolicy &Policy) const;\n";
       OS << "  const char *getSpelling() const;\n";
+      OS << "  void processODRHash(llvm::FoldingSetNodeID &ID,\n"
+         << "                      class ODRHash &Hash) const;\n";
     }
 
     if (!ElideSpelling) {
@@ -2820,6 +2871,7 @@
 
       writePrettyPrintFunction(R, Args, OS);
       writeGetSpellingFunction(R, OS);
+      writeProcessODRHashFunction(R, Args, OS);
     }
   }
 }
@@ -2870,6 +2922,10 @@
   OS << "void Attr::printPretty(raw_ostream &OS, "
         "const PrintingPolicy &Policy) const {\n";
   EmitFunc("printPretty(OS, Policy)");
+
+  OS << "void Attr::processODRHash(llvm::FoldingSetNodeID &ID, "
+     << "class ODRHash &Hash) const {";
+  EmitFunc("processODRHash(ID, Hash)");
 }
 
 static void emitAttrList(raw_ostream &OS, StringRef Class,
Index: clang/lib/AST/ODRHash.cpp
===================================================================
--- clang/lib/AST/ODRHash.cpp
+++ clang/lib/AST/ODRHash.cpp
@@ -539,7 +539,7 @@
     return;
 
   llvm::copy_if(D->attrs(), std::back_inserter(HashableAttrs),
-                [](const Attr *A) { return !A->isImplicit(); });
+                [](const Attr *A) { return A->isODRHashable(); });
 }
 
 void ODRHash::AddAttrs(const Decl *D) {
@@ -551,39 +551,7 @@
 }
 
 void ODRHash::AddAttr(const Attr *A) {
-  ID.AddInteger(A->getKind());
-
-  // FIXME: This should be auto-generated as part of Attr.td
-  switch (A->getKind()) {
-  case attr::Aligned: {
-    auto *M = cast<AlignedAttr>(A);
-    ID.AddBoolean(M->isAlignmentExpr());
-    if (M->isAlignmentExpr()) {
-      Expr *AlignmentExpr = M->getAlignmentExpr();
-      ID.AddBoolean(AlignmentExpr);
-      if (AlignmentExpr)
-        AddStmt(AlignmentExpr);
-    } else {
-      ID.AddString(M->getAlignmentType()->getType().getAsString());
-    }
-    break;
-  }
-  case attr::AlignValue: {
-    auto *M = cast<AlignValueAttr>(A);
-    Expr *AlignmentExpr = M->getAlignment();
-    ID.AddBoolean(AlignmentExpr);
-    if (AlignmentExpr)
-      AddStmt(AlignmentExpr);
-    break;
-  }
-  case attr::EnumExtensibility: {
-    auto *M = cast<EnumExtensibilityAttr>(A);
-    ID.AddInteger(M->getExtensibility());
-    break;
-  }
-  default:
-    break;
-  }
+  A->processODRHash(ID, *this);
 }
 
 void ODRHash::AddSubDecl(const Decl *D) {
Index: clang/lib/AST/AttrImpl.cpp
===================================================================
--- clang/lib/AST/AttrImpl.cpp
+++ clang/lib/AST/AttrImpl.cpp
@@ -13,6 +13,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Attr.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/ODRHash.h"
 #include "clang/AST/Type.h"
 using namespace clang;
 
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -549,6 +549,8 @@
   list<Accessor> Accessors = [];
   // Set to true for attributes with arguments which require delayed parsing.
   bit LateParsed = 0;
+  // Set to true for attributes that should participate in ODR hashing.
+  bit IsODRHashable = 0;
   // Set to false to prevent an attribute from being propagated from a template
   // to the instantiation.
   bit Clone = 1;
@@ -669,6 +671,7 @@
   let Args = [VariadicStringArgument<"Tags">];
   let Subjects = SubjectList<[Struct, Var, Function, Namespace], ErrorDiag>;
   let MeaningfulToClassTemplateDefinition = 1;
+  let IsODRHashable = 1;
   let Documentation = [AbiTagsDocs];
 }
 
@@ -710,6 +713,7 @@
                    Accessor<"isAlignas", [Keyword<"alignas">,
                                           Keyword<"_Alignas">]>,
                    Accessor<"isDeclspec",[Declspec<"align">]>];
+  let IsODRHashable = 1;
   let Documentation = [Undocumented];
 }
 
@@ -730,6 +734,7 @@
   ];
   let Args = [ExprArgument<"Alignment">];
   let Subjects = SubjectList<[Var, TypedefName]>;
+  let IsODRHashable = 1;
   let Documentation = [AlignValueDocs];
 }
 
@@ -1497,6 +1502,7 @@
   let Subjects = SubjectList<[Enum]>;
   let Args = [EnumArgument<"Extensibility", "Kind",
               ["closed", "open"], ["Closed", "Open"]>];
+  let IsODRHashable = 1;
   let Documentation = [EnumExtensibilityDocs];
 }
 
@@ -1719,6 +1725,7 @@
 def Naked : InheritableAttr {
   let Spellings = [GCC<"naked">, Declspec<"naked">];
   let Subjects = SubjectList<[Function]>;
+  let IsODRHashable = 1;
   let Documentation = [Undocumented];
 }
 
@@ -2320,6 +2327,7 @@
 def OptimizeNone : InheritableAttr {
   let Spellings = [Clang<"optnone">];
   let Subjects = SubjectList<[Function, ObjCMethod]>;
+  let IsODRHashable = 1;
   let Documentation = [OptnoneDocs];
 }
 
@@ -2361,6 +2369,7 @@
 def Packed : InheritableAttr {
   let Spellings = [GCC<"packed">];
 //  let Subjects = [Tag, Field];
+  let IsODRHashable = 1;
   let Documentation = [Undocumented];
 }
 
@@ -2861,6 +2870,7 @@
                    C2x<"", "maybe_unused", 202106>];
   let Subjects = SubjectList<[Var, ObjCIvar, Type, Enum, EnumConstant, Label,
                               Field, ObjCMethod, FunctionLike]>;
+  let IsODRHashable = 1;
   let Documentation = [WarnMaybeUnusedDocs];
 }
 
Index: clang/include/clang/AST/Attr.h
===================================================================
--- clang/include/clang/AST/Attr.h
+++ clang/include/clang/AST/Attr.h
@@ -50,6 +50,7 @@
   // FIXME: These are properties of the attribute kind, not state for this
   // instance of the attribute.
   unsigned IsLateParsed : 1;
+  unsigned IsODRHashable : 1;
   unsigned InheritEvenIfAlreadyPresent : 1;
 
   void *operator new(size_t bytes) noexcept {
@@ -71,10 +72,10 @@
 
 protected:
   Attr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
-       attr::Kind AK, bool IsLateParsed)
+       attr::Kind AK, bool IsLateParsed, bool IsODRHashable)
       : AttributeCommonInfo(CommonInfo), AttrKind(AK), Inherited(false),
         IsPackExpansion(false), Implicit(false), IsLateParsed(IsLateParsed),
-        InheritEvenIfAlreadyPresent(false) {}
+        IsODRHashable(IsODRHashable), InheritEvenIfAlreadyPresent(false) {}
 
 public:
   attr::Kind getKind() const { return static_cast<attr::Kind>(AttrKind); }
@@ -101,17 +102,25 @@
 
   bool isLateParsed() const { return IsLateParsed; }
 
+  bool isODRHashable() const { return IsODRHashable; }
+
   // Pretty print this attribute.
   void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const;
 
+  /// Hash the attribute and its salient arguments.
+  ///
+  /// It is an implementation detail and for obtaining a hash you should use
+  /// ODRHash, specifically ODRHash::AddAttr.
+  void processODRHash(llvm::FoldingSetNodeID &ID, class ODRHash &Hash) const;
+
   static StringRef getDocumentation(attr::Kind);
 };
 
 class TypeAttr : public Attr {
 protected:
   TypeAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
-           attr::Kind AK, bool IsLateParsed)
-      : Attr(Context, CommonInfo, AK, IsLateParsed) {}
+           attr::Kind AK, bool IsLateParsed, bool IsODRHashable)
+      : Attr(Context, CommonInfo, AK, IsLateParsed, IsODRHashable) {}
 
 public:
   static bool classof(const Attr *A) {
@@ -123,8 +132,8 @@
 class StmtAttr : public Attr {
 protected:
   StmtAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
-           attr::Kind AK, bool IsLateParsed)
-      : Attr(Context, CommonInfo, AK, IsLateParsed) {}
+           attr::Kind AK, bool IsLateParsed, bool IsODRHashable)
+      : Attr(Context, CommonInfo, AK, IsLateParsed, IsODRHashable) {}
 
 public:
   static bool classof(const Attr *A) {
@@ -136,9 +145,9 @@
 class InheritableAttr : public Attr {
 protected:
   InheritableAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
-                  attr::Kind AK, bool IsLateParsed,
+                  attr::Kind AK, bool IsLateParsed, bool IsODRHashable,
                   bool InheritEvenIfAlreadyPresent)
-      : Attr(Context, CommonInfo, AK, IsLateParsed) {
+      : Attr(Context, CommonInfo, AK, IsLateParsed, IsODRHashable) {
     this->InheritEvenIfAlreadyPresent = InheritEvenIfAlreadyPresent;
   }
 
@@ -161,9 +170,9 @@
 class DeclOrStmtAttr : public InheritableAttr {
 protected:
   DeclOrStmtAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
-                 attr::Kind AK, bool IsLateParsed,
+                 attr::Kind AK, bool IsLateParsed, bool IsODRHashable,
                  bool InheritEvenIfAlreadyPresent)
-      : InheritableAttr(Context, CommonInfo, AK, IsLateParsed,
+      : InheritableAttr(Context, CommonInfo, AK, IsLateParsed, IsODRHashable,
                         InheritEvenIfAlreadyPresent) {}
 
 public:
@@ -177,8 +186,9 @@
 protected:
   InheritableParamAttr(ASTContext &Context,
                        const AttributeCommonInfo &CommonInfo, attr::Kind AK,
-                       bool IsLateParsed, bool InheritEvenIfAlreadyPresent)
-      : InheritableAttr(Context, CommonInfo, AK, IsLateParsed,
+                       bool IsLateParsed, bool IsODRHashable,
+                       bool InheritEvenIfAlreadyPresent)
+      : InheritableAttr(Context, CommonInfo, AK, IsLateParsed, IsODRHashable,
                         InheritEvenIfAlreadyPresent) {}
 
 public:
@@ -192,9 +202,9 @@
 class HLSLAnnotationAttr : public InheritableAttr {
 protected:
   HLSLAnnotationAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
-                     attr::Kind AK, bool IsLateParsed,
+                     attr::Kind AK, bool IsLateParsed, bool IsODRHashable,
                      bool InheritEvenIfAlreadyPresent)
-      : InheritableAttr(Context, CommonInfo, AK, IsLateParsed,
+      : InheritableAttr(Context, CommonInfo, AK, IsLateParsed, IsODRHashable,
                         InheritEvenIfAlreadyPresent) {}
 
 public:
@@ -210,10 +220,10 @@
 class ParameterABIAttr : public InheritableParamAttr {
 protected:
   ParameterABIAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
-                   attr::Kind AK, bool IsLateParsed,
+                   attr::Kind AK, bool IsLateParsed, bool IsODRHashable,
                    bool InheritEvenIfAlreadyPresent)
       : InheritableParamAttr(Context, CommonInfo, AK, IsLateParsed,
-                             InheritEvenIfAlreadyPresent) {}
+                             IsODRHashable, InheritEvenIfAlreadyPresent) {}
 
 public:
   ParameterABI getABI() const {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to