[clang] [Clang][TableGen] Change ClangAttrEmitter to use const Record * (PR #110584)

via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 30 18:53:30 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Rahul Joshi (jurahul)

<details>
<summary>Changes</summary>

This is a part of effort to have better const correctness in TableGen backends:

https://discourse.llvm.org/t/psa-planned-changes-to-tablegen-getallderiveddefinitions-api-potential-downstream-breakages/81089



---

Patch is 23.76 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/110584.diff


2 Files Affected:

- (modified) clang/utils/TableGen/ASTTableGen.h (+2-2) 
- (modified) clang/utils/TableGen/ClangAttrEmitter.cpp (+64-66) 


``````````diff
diff --git a/clang/utils/TableGen/ASTTableGen.h b/clang/utils/TableGen/ASTTableGen.h
index 143d779a8a64f8..827fce9e213cba 100644
--- a/clang/utils/TableGen/ASTTableGen.h
+++ b/clang/utils/TableGen/ASTTableGen.h
@@ -319,8 +319,8 @@ class PropertyType : public WrappedRecord {
     return get()->getValueAsString(UnpackOptionalCodeFieldName);
   }
 
-  std::vector<llvm::Record*> getBufferElementTypes() const {
-    return get()->getValueAsListOfDefs(BufferElementTypesFieldName);
+  std::vector<const llvm::Record *> getBufferElementTypes() const {
+    return get()->getValueAsListOfConstDefs(BufferElementTypesFieldName);
   }
 
   static llvm::StringRef getTableGenNodeClassName() {
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp
index 7f950c3b08a4b0..e5d92b343b3dde 100644
--- a/clang/utils/TableGen/ClangAttrEmitter.cpp
+++ b/clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -99,10 +99,9 @@ static bool isVariadicStringLiteralArgument(const Record *Arg);
 
 static std::vector<FlattenedSpelling>
 GetFlattenedSpellings(const Record &Attr) {
-  std::vector<Record *> Spellings = Attr.getValueAsListOfDefs("Spellings");
   std::vector<FlattenedSpelling> Ret;
 
-  for (const auto &Spelling : Spellings) {
+  for (const auto &Spelling : Attr.getValueAsListOfDefs("Spellings")) {
     StringRef Variety = Spelling->getValueAsString("Variety");
     StringRef Name = Spelling->getValueAsString("Name");
     if (Variety == "GCC") {
@@ -1747,7 +1746,8 @@ getSpellingListIndex(const std::vector<FlattenedSpelling> &SpellingList,
 }
 
 static void writeAttrAccessorDefinition(const Record &R, raw_ostream &OS) {
-  std::vector<Record*> Accessors = R.getValueAsListOfDefs("Accessors");
+  std::vector<const Record *> Accessors =
+      R.getValueAsListOfConstDefs("Accessors");
   if (Accessors.empty())
     return;
 
@@ -1962,20 +1962,21 @@ struct AttributeSubjectMatchRule {
 
   bool isSubRule() const { return Constraint != nullptr; }
 
-  std::vector<Record *> getSubjects() const {
+  std::vector<const Record *> getSubjects() const {
     return (Constraint ? Constraint : MetaSubject)
-        ->getValueAsListOfDefs("Subjects");
+        ->getValueAsListOfConstDefs("Subjects");
   }
 
-  std::vector<Record *> getLangOpts() const {
+  std::vector<const Record *> getLangOpts() const {
     if (Constraint) {
       // Lookup the options in the sub-rule first, in case the sub-rule
       // overrides the rules options.
-      std::vector<Record *> Opts = Constraint->getValueAsListOfDefs("LangOpts");
+      std::vector<const Record *> Opts =
+          Constraint->getValueAsListOfConstDefs("LangOpts");
       if (!Opts.empty())
         return Opts;
     }
-    return MetaSubject->getValueAsListOfDefs("LangOpts");
+    return MetaSubject->getValueAsListOfConstDefs("LangOpts");
   }
 
   // Abstract rules are used only for sub-rules
@@ -2103,9 +2104,8 @@ PragmaClangAttributeSupport::PragmaClangAttributeSupport(
                                        const Record *MetaSubject,
                                        const Record *Constraint) {
     Rules.emplace_back(MetaSubject, Constraint);
-    std::vector<Record *> ApplicableSubjects =
-        SubjectContainer->getValueAsListOfDefs("Subjects");
-    for (const auto *Subject : ApplicableSubjects) {
+    for (const Record *Subject :
+         SubjectContainer->getValueAsListOfConstDefs("Subjects")) {
       bool Inserted =
           SubjectsToRules
               .try_emplace(Subject, RuleOrAggregateRuleSet::getRule(
@@ -2121,9 +2121,8 @@ PragmaClangAttributeSupport::PragmaClangAttributeSupport(
   for (const auto *MetaSubject :
        Records.getAllDerivedDefinitions("AttrSubjectMatcherRule")) {
     MapFromSubjectsToRules(MetaSubject, MetaSubject, /*Constraints=*/nullptr);
-    std::vector<Record *> Constraints =
-        MetaSubject->getValueAsListOfDefs("Constraints");
-    for (const auto *Constraint : Constraints)
+    for (const Record *Constraint :
+         MetaSubject->getValueAsListOfDefs("Constraints"))
       MapFromSubjectsToRules(Constraint, MetaSubject, Constraint);
   }
 
@@ -2131,7 +2130,7 @@ PragmaClangAttributeSupport::PragmaClangAttributeSupport(
       Records.getAllDerivedDefinitions(DeclNodeClassName);
   for (const auto *Aggregate :
        Records.getAllDerivedDefinitions("AttrSubjectMatcherAggregateRule")) {
-    Record *SubjectDecl = Aggregate->getValueAsDef("Subject");
+    const Record *SubjectDecl = Aggregate->getValueAsDef("Subject");
 
     // Gather sub-classes of the aggregate subject that act as attribute
     // subject rules.
@@ -2218,9 +2217,8 @@ bool PragmaClangAttributeSupport::isAttributedSupported(
   if (Attribute.isValueUnset("Subjects"))
     return false;
   const Record *SubjectObj = Attribute.getValueAsDef("Subjects");
-  std::vector<Record *> Subjects = SubjectObj->getValueAsListOfDefs("Subjects");
   bool HasAtLeastOneValidSubject = false;
-  for (const auto *Subject : Subjects) {
+  for (const auto *Subject : SubjectObj->getValueAsListOfDefs("Subjects")) {
     if (!isSupportedPragmaClangAttributeSubject(*Subject))
       continue;
     if (!SubjectsToRules.contains(Subject))
@@ -2230,7 +2228,7 @@ bool PragmaClangAttributeSupport::isAttributedSupported(
   return HasAtLeastOneValidSubject;
 }
 
-static std::string GenerateTestExpression(ArrayRef<Record *> LangOpts) {
+static std::string GenerateTestExpression(ArrayRef<const Record *> LangOpts) {
   std::string Test;
 
   for (auto *E : LangOpts) {
@@ -2271,8 +2269,7 @@ PragmaClangAttributeSupport::generateStrictConformsTo(const Record &Attr,
      << AttributeSubjectMatchRule::EnumName
      << ", bool>> &MatchRules, const LangOptions &LangOpts) const override {\n";
   const Record *SubjectObj = Attr.getValueAsDef("Subjects");
-  std::vector<Record *> Subjects = SubjectObj->getValueAsListOfDefs("Subjects");
-  for (const auto *Subject : Subjects) {
+  for (const auto *Subject : SubjectObj->getValueAsListOfDefs("Subjects")) {
     if (!isSupportedPragmaClangAttributeSubject(*Subject))
       continue;
     auto It = SubjectsToRules.find(Subject);
@@ -2281,7 +2278,7 @@ PragmaClangAttributeSupport::generateStrictConformsTo(const Record &Attr,
     for (const auto &Rule : It->getSecond().getAggregateRuleSet()) {
       // The rule might be language specific, so only subtract it from the given
       // rules if the specific language options are specified.
-      std::vector<Record *> LangOpts = Rule.getLangOpts();
+      std::vector<const Record *> LangOpts = Rule.getLangOpts();
       OS << "  MatchRules.push_back(std::make_pair(" << Rule.getEnumValue()
          << ", /*IsSupported=*/" << GenerateTestExpression(LangOpts)
          << "));\n";
@@ -2506,7 +2503,7 @@ static void emitClangAttrTypeArgList(const RecordKeeper &Records,
   std::map<std::string, FSIVecTy> FSIMap;
   for (const auto *Attr : Records.getAllDerivedDefinitions("Attr")) {
     // Determine whether the first argument is a type.
-    std::vector<Record *> Args = Attr->getValueAsListOfDefs("Args");
+    std::vector<const Record *> Args = Attr->getValueAsListOfConstDefs("Args");
     if (Args.empty())
       continue;
 
@@ -2584,7 +2581,7 @@ static void emitClangAttrVariadicIdentifierArgList(const RecordKeeper &Records,
   std::map<std::string, FSIVecTy> FSIMap;
   for (const auto *A : Records.getAllDerivedDefinitions("Attr")) {
     // Determine whether the first argument is a variadic identifier.
-    std::vector<Record *> Args = A->getValueAsListOfDefs("Args");
+    std::vector<const Record *> Args = A->getValueAsListOfConstDefs("Args");
     if (Args.empty() || !isVariadicIdentifierArgument(Args[0]))
       continue;
     generateFlattenedSpellingInfo(*A, FSIMap);
@@ -2600,7 +2597,7 @@ emitClangAttrUnevaluatedStringLiteralList(const RecordKeeper &Records,
                                           raw_ostream &OS) {
   OS << "#if defined(CLANG_ATTR_STRING_LITERAL_ARG_LIST)\n";
 
-  auto MakeMask = [](ArrayRef<Record *> Args) {
+  auto MakeMask = [](ArrayRef<const Record *> Args) {
     uint32_t Bits = 0;
     assert(Args.size() <= 32 && "unsupported number of arguments in attribute");
     for (uint32_t N = 0; N < Args.size(); ++N) {
@@ -2617,7 +2614,7 @@ emitClangAttrUnevaluatedStringLiteralList(const RecordKeeper &Records,
   std::map<std::string, FSIVecTy> FSIMap;
   for (const auto *Attr : Records.getAllDerivedDefinitions("Attr")) {
     // Determine whether there are any string arguments.
-    uint32_t ArgMask = MakeMask(Attr->getValueAsListOfDefs("Args"));
+    uint32_t ArgMask = MakeMask(Attr->getValueAsListOfConstDefs("Args"));
     if (!ArgMask)
       continue;
     generateFlattenedSpellingInfo(*Attr, FSIMap, ArgMask);
@@ -2633,7 +2630,7 @@ static void emitClangAttrIdentifierArgList(const RecordKeeper &Records,
   std::map<std::string, FSIVecTy> FSIMap;
   for (const auto *Attr : Records.getAllDerivedDefinitions("Attr")) {
     // Determine whether the first argument is an identifier.
-    std::vector<Record *> Args = Attr->getValueAsListOfDefs("Args");
+    std::vector<const Record *> Args = Attr->getValueAsListOfConstDefs("Args");
     if (Args.empty() || !isIdentifierArgument(Args[0]))
       continue;
     generateFlattenedSpellingInfo(*Attr, FSIMap);
@@ -2651,8 +2648,8 @@ static void emitClangAttrStrictIdentifierArgList(const RecordKeeper &Records,
     if (!Attr->getValueAsBit("StrictEnumParameters"))
       continue;
     // Check that there is really an identifier argument.
-    std::vector<Record *> Args = Attr->getValueAsListOfDefs("Args");
-    if (none_of(Args, [&](Record *R) { return isIdentifierArgument(R); }))
+    std::vector<const Record *> Args = Attr->getValueAsListOfConstDefs("Args");
+    if (none_of(Args, [&](const Record *R) { return isIdentifierArgument(R); }))
       continue;
     generateFlattenedSpellingInfo(*Attr, FSIMap);
   }
@@ -2673,7 +2670,7 @@ static void emitClangAttrThisIsaIdentifierArgList(const RecordKeeper &Records,
   std::map<std::string, FSIVecTy> FSIMap;
   for (const auto *A : Records.getAllDerivedDefinitions("Attr")) {
     // Determine whether the first argument is a variadic identifier.
-    std::vector<Record *> Args = A->getValueAsListOfDefs("Args");
+    std::vector<const Record *> Args = A->getValueAsListOfConstDefs("Args");
     if (Args.empty() || !keywordThisIsaIdentifierInArgument(Args[0]))
       continue;
     generateFlattenedSpellingInfo(*A, FSIMap);
@@ -2766,7 +2763,8 @@ static void emitAttributes(const RecordKeeper &Records, raw_ostream &OS,
     else
       OS << "\n// " << R.getName() << "Attr implementation\n\n";
 
-    std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
+    std::vector<const Record *> ArgRecords =
+        R.getValueAsListOfConstDefs("Args");
     std::vector<std::unique_ptr<Argument>> Args;
     Args.reserve(ArgRecords.size());
 
@@ -3389,7 +3387,7 @@ namespace {
     AttrClassHierarchy(const RecordKeeper &Records) {
       // Find records for all the classes.
       for (auto &Descriptor : AttrClassDescriptors) {
-        Record *ClassRecord = Records.getClass(Descriptor.TableGenName);
+        const Record *ClassRecord = Records.getClass(Descriptor.TableGenName);
         AttrClass *Class = new AttrClass(Descriptor, ClassRecord);
         Classes.emplace_back(Class);
       }
@@ -3519,8 +3517,8 @@ void EmitClangAttrSubjectMatchRuleList(const RecordKeeper &Records,
 void EmitClangAttrPCHRead(const RecordKeeper &Records, raw_ostream &OS) {
   emitSourceFileHeader("Attribute deserialization code", OS, Records);
 
-  Record *InhClass = Records.getClass("InheritableAttr");
-  std::vector<Record *> ArgRecords;
+  const Record *InhClass = Records.getClass("InheritableAttr");
+  std::vector<const Record *> ArgRecords;
   std::vector<std::unique_ptr<Argument>> Args;
   std::unique_ptr<VariadicExprArgument> DelayedArgs;
 
@@ -3541,7 +3539,7 @@ void EmitClangAttrPCHRead(const RecordKeeper &Records, raw_ostream &OS) {
           std::make_unique<VariadicExprArgument>("DelayedArgs", R.getName());
       DelayedArgs->writePCHReadDecls(OS);
     }
-    ArgRecords = R.getValueAsListOfDefs("Args");
+    ArgRecords = R.getValueAsListOfConstDefs("Args");
     Args.clear();
     for (const auto *Arg : ArgRecords) {
       Args.emplace_back(createArgument(*Arg, R.getName()));
@@ -3573,14 +3571,14 @@ void EmitClangAttrPCHRead(const RecordKeeper &Records, raw_ostream &OS) {
 void EmitClangAttrPCHWrite(const RecordKeeper &Records, raw_ostream &OS) {
   emitSourceFileHeader("Attribute serialization code", OS, Records);
 
-  Record *InhClass = Records.getClass("InheritableAttr");
+  const Record *InhClass = Records.getClass("InheritableAttr");
   OS << "  switch (A->getKind()) {\n";
   for (const auto *Attr : Records.getAllDerivedDefinitions("Attr")) {
     const Record &R = *Attr;
     if (!R.getValueAsBit("ASTNode"))
       continue;
     OS << "  case attr::" << R.getName() << ": {\n";
-    std::vector<Record *> Args = R.getValueAsListOfDefs("Args");
+    std::vector<const Record *> Args = R.getValueAsListOfConstDefs("Args");
     if (R.isSubClassOf(InhClass) || !Args.empty())
       OS << "    const auto *SA = cast<" << R.getName()
          << "Attr>(A);\n";
@@ -3731,9 +3729,8 @@ static void GenerateHasAttrSpellingStringSwitch(
       GenerateTargetSpecificAttrChecks(R, Arches, Test, nullptr);
     } else if (!Attr->getValueAsListOfDefs("TargetSpecificSpellings").empty()) {
       // Add target checks if this spelling is target-specific.
-      const std::vector<Record *> TargetSpellings =
-          Attr->getValueAsListOfDefs("TargetSpecificSpellings");
-      for (const auto &TargetSpelling : TargetSpellings) {
+      for (const auto &TargetSpelling :
+           Attr->getValueAsListOfDefs("TargetSpecificSpellings")) {
         // Find spelling that matches current scope and name.
         for (const auto &Spelling : GetFlattenedSpellings(*TargetSpelling)) {
           if (Scope == Spelling.nameSpace() && Name == Spelling.name()) {
@@ -3772,7 +3769,7 @@ void EmitClangRegularKeywordAttributeInfo(const RecordKeeper &Records,
     for (const auto &S : GetFlattenedSpellings(*R)) {
       if (!isRegularKeywordAttribute(S))
         continue;
-      std::vector<Record *> Args = R->getValueAsListOfDefs("Args");
+      std::vector<const Record *> Args = R->getValueAsListOfConstDefs("Args");
       bool HasArgs = any_of(
           Args, [](const Record *Arg) { return !Arg->getValueAsBit("Fake"); });
 
@@ -3938,8 +3935,7 @@ void EmitClangAttrASTVisitor(const RecordKeeper &Records, raw_ostream &OS) {
        << "  if (!getDerived().Visit" << R.getName() << "Attr(A))\n"
        << "    return false;\n";
 
-    std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
-    for (const auto *Arg : ArgRecords)
+    for (const auto *Arg : R.getValueAsListOfDefs("Args"))
       createArgument(*Arg, R.getName())->writeASTVisitorTraversal(OS);
 
     if (Attr->getValueAsBit("AcceptsExprPack"))
@@ -4003,7 +3999,8 @@ void EmitClangAttrTemplateInstantiateHelper(ArrayRef<const Record *> Attrs,
       continue;
     }
 
-    std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
+    std::vector<const Record *> ArgRecords =
+        R.getValueAsListOfConstDefs("Args");
     std::vector<std::unique_ptr<Argument>> Args;
     Args.reserve(ArgRecords.size());
 
@@ -4073,10 +4070,9 @@ static void emitArgInfo(const Record &R, raw_ostream &OS) {
   // This function will count the number of arguments specified for the
   // attribute and emit the number of required arguments followed by the
   // number of optional arguments.
-  std::vector<Record *> Args = R.getValueAsListOfDefs("Args");
   unsigned ArgCount = 0, OptCount = 0, ArgMemberCount = 0;
   bool HasVariadic = false;
-  for (const auto *Arg : Args) {
+  for (const auto *Arg : R.getValueAsListOfDefs("Args")) {
     // If the arg is fake, it's the user's job to supply it: general parsing
     // logic shouldn't need to know anything about it.
     if (Arg->getValueAsBit("Fake"))
@@ -4116,8 +4112,7 @@ static std::string CalculateDiagnostic(const Record &S) {
     return ("\"" + Twine(CustomDiag) + "\"").str();
 
   std::vector<std::string> DiagList;
-  std::vector<Record *> Subjects = S.getValueAsListOfDefs("Subjects");
-  for (const auto *Subject : Subjects) {
+  for (const auto *Subject : S.getValueAsListOfDefs("Subjects")) {
     const Record &R = *Subject;
     // Get the diagnostic text from the Decl or Stmt node given.
     std::string V = GetDiagnosticSpelling(R);
@@ -4182,7 +4177,7 @@ static void GenerateCustomAppertainsTo(const Record &Subject, raw_ostream &OS) {
     return;
 
   // This only works with non-root Decls.
-  Record *Base = Subject.getValueAsDef(BaseFieldName);
+  const Record *Base = Subject.getValueAsDef(BaseFieldName);
 
   // Not currently support custom subjects within custom subjects.
   if (Base->isSubClassOf("SubsetSubject")) {
@@ -4209,7 +4204,8 @@ static void GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) {
     return;
 
   const Record *SubjectObj = Attr.getValueAsDef("Subjects");
-  std::vector<Record *> Subjects = SubjectObj->getValueAsListOfDefs("Subjects");
+  std::vector<const Record *> Subjects =
+      SubjectObj->getValueAsListOfConstDefs("Subjects");
 
   // If the list of subjects is empty, it is assumed that the attribute
   // appertains to everything.
@@ -4222,7 +4218,7 @@ static void GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) {
   // FIXME: subset subjects are added to the declaration list until there are
   // enough statement attributes with custom subject needs to warrant
   // the implementation effort.
-  std::vector<Record *> DeclSubjects, StmtSubjects;
+  std::vector<const Record *> DeclSubjects, StmtSubjects;
   copy_if(Subjects, std::back_inserter(DeclSubjects), [](const Record *R) {
     return R->isSubClassOf("SubsetSubject") || !R->isSubClassOf("StmtNode");
   });
@@ -4340,8 +4336,8 @@ static void GenerateMutualExclusionsChecks(const Record &Attr,
   // diagMutualExclusion() check.
   for (const Record *Exclusion :
        Records.getAllDerivedDefinitions("MutualExclusions")) {
-    std::vector<Record *> MutuallyExclusiveAttrs =
-        Exclusion->getValueAsListOfDefs("Exclusions");
+    std::vector<const Record *> MutuallyExclusiveAttrs =
+        Exclusion->getValueAsListOfConstDefs("Exclusions");
     auto IsCurAttr = [Attr](const Record *R) {
       return R->getName() == Attr.getName();
     };
@@ -4460,7 +4456,7 @@ emitAttributeMatchRules(PragmaClangAttributeSupport &PragmaAttributeSupport,
       OS << "    return false;\n";
       continue;
     }
-    std::vector<Record *> Subjects = Rule.getSubjects();
+    std::vector<const Record *> Subjects = Rule.getSubjects();
     assert(!Subjects.empty() && "Missing subjects");
     OS << "  case " << Rule.getEnumValue() << ":\n";
     OS << "    return ";
@@ -4487,7 +4483,8 @@ static void GenerateLangOptRequirements(const Record &R,
                                         raw_ostream &OS) {
   // If the attribute has an empty or unset list of language requirements,
   // use the default handler.
-  std::vector<Record *> LangOpts = R.getValueAsListOfDefs("LangOpts");
+  std::vector<const Record *> LangOpts =
+      R.getValueAsListOfConstDefs("LangOpts");
   if (LangOpts.empty())
     return;
 
@@ -4539,7 +4536,7 @@ static void GenerateTargetRequirements(const Record &Attr,
 
 static void
 GenerateSpellingTargetRequirements(const Record &Attr,
-                                   const std::vector<Record *> &TargetSpellings,
+                                   ArrayRef<const Record *> TargetSpellings,
                                    raw_ostream &OS) {
   // If there are no target specific spellings, use the default target handler.
   if (TargetSpellings.empty())
@@ -4632,7 +4629,7 @@ static bool isParamExpr(const Record *Arg) {
 void GenerateIsParamExpr(const Record &Attr, raw_ostream &OS) {
   OS << "bool isParamExpr(size_t N) const override {\n";
   OS << "  return ";
-  auto Args = Attr.getValueAsListOfDefs("Args");
+  auto Args = Attr.getValueAsListOfConstDefs("Args");
   for (size_t I = 0; I < Args.size(); ++I)
     if (isParamExpr(Args[I]))
       OS << "(N == " << I << ") || ";
@@ -4698,7 +4695,7 @@ void EmitClangAttrParsedAttrImpl(const RecordKeeper &Records, raw_ostream &OS) {
     if (Attr.isValueUnset("Subjects"))
       continue;
     const Record *SubjectObj = Att...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/110584


More information about the cfe-commits mailing list