Implement Attr dumping in terms of visitors

Remove now-vestigial dumpType and dumpBareDeclRef methods. The old
tablegen generated code used to expect them to be present, but the new
generated code has no such requirement.

Reviewers: aaron.ballman

Subscribers: mgorny, cfe-commits

Differential Revision: https://reviews.llvm.org/D55492

llvm-svn: 350958
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp
index 70dfacc..874ad2d 100644
--- a/clang/utils/TableGen/ClangAttrEmitter.cpp
+++ b/clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -603,14 +603,15 @@
       OS << "    OS << \"";
     }
 
-    void writeDump(raw_ostream &OS) const override {}
+    void writeDump(raw_ostream &OS) const override {
+      OS << "    if (!SA->is" << getUpperName() << "Expr())\n";
+      OS << "      dumpType(SA->get" << getUpperName()
+         << "Type()->getType());\n";
+    }
 
     void writeDumpChildren(raw_ostream &OS) const override {
       OS << "    if (SA->is" << getUpperName() << "Expr())\n";
       OS << "      dumpStmt(SA->get" << getUpperName() << "Expr());\n";
-      OS << "    else\n";
-      OS << "      dumpType(SA->get" << getUpperName()
-         << "Type()->getType());\n";
     }
 
     void writeHasChildren(raw_ostream &OS) const override {
@@ -2932,15 +2933,15 @@
     OS << "case AttrSyntax::" << Variety << ": {\n";
     // C++11-style attributes are further split out based on the Scope.
     for (auto I = List.cbegin(), E = List.cend(); I != E; ++I) {
-      if (I != List.cbegin())

-        OS << " else ";

-      if (I->first.empty())

-        OS << "if (ScopeName == \"\") {\n";

-      else

-        OS << "if (ScopeName == \"" << I->first << "\") {\n";

-      OS << "  return llvm::StringSwitch<int>(Name)\n";

-      GenerateHasAttrSpellingStringSwitch(I->second, OS, Spelling, I->first);

-      OS << "}";

+      if (I != List.cbegin())
+        OS << " else ";
+      if (I->first.empty())
+        OS << "if (ScopeName == \"\") {\n";
+      else
+        OS << "if (ScopeName == \"" << I->first << "\") {\n";
+      OS << "  return llvm::StringSwitch<int>(Name)\n";
+      GenerateHasAttrSpellingStringSwitch(I->second, OS, Spelling, I->first);
+      OS << "}";
     }
     OS << "\n} break;\n";
   };
@@ -3697,39 +3698,67 @@
 }
 
 // Emits the code to dump an attribute.
-void EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS) {
-  emitSourceFileHeader("Attribute dumper", OS);
+void EmitClangAttrTextNodeDump(RecordKeeper &Records, raw_ostream &OS) {
+  emitSourceFileHeader("Attribute text node dumper", OS);
 
-  OS << "  switch (A->getKind()) {\n";
   std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
   for (const auto *Attr : Attrs) {
     const Record &R = *Attr;
     if (!R.getValueAsBit("ASTNode"))
       continue;
-    OS << "  case attr::" << R.getName() << ": {\n";
 
     // If the attribute has a semantically-meaningful name (which is determined
     // by whether there is a Spelling enumeration for it), then write out the
     // spelling used for the attribute.
+
+    std::string FunctionContent;
+    llvm::raw_string_ostream SS(FunctionContent);
+
     std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
     if (Spellings.size() > 1 && !SpellingNamesAreCommon(Spellings))
-      OS << "    OS << \" \" << A->getSpelling();\n";
+      SS << "    OS << \" \" << A->getSpelling();\n";
 
     Args = R.getValueAsListOfDefs("Args");
-    if (!Args.empty()) {
-      OS << "    const auto *SA = cast<" << R.getName()
-         << "Attr>(A);\n";
-      for (const auto *Arg : Args)
-        createArgument(*Arg, R.getName())->writeDump(OS);
+    for (const auto *Arg : Args)
+      createArgument(*Arg, R.getName())->writeDump(SS);
 
-      for (const auto *AI : Args)
-        createArgument(*AI, R.getName())->writeDumpChildren(OS);
+    if (SS.tell()) {
+      OS << "  void Visit" << R.getName() << "Attr(const " << R.getName()
+         << "Attr *A) {\n";
+      if (!Args.empty())
+        OS << "    const auto *SA = cast<" << R.getName()
+           << "Attr>(A); (void)SA;\n";
+      OS << SS.str();
+      OS << "  }\n";
     }
-    OS <<
-      "    break;\n"
-      "  }\n";
   }
-  OS << "  }\n";
+}
+
+void EmitClangAttrNodeTraverse(RecordKeeper &Records, raw_ostream &OS) {
+  emitSourceFileHeader("Attribute text node traverser", OS);
+
+  std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
+  for (const auto *Attr : Attrs) {
+    const Record &R = *Attr;
+    if (!R.getValueAsBit("ASTNode"))
+      continue;
+
+    std::string FunctionContent;
+    llvm::raw_string_ostream SS(FunctionContent);
+
+    Args = R.getValueAsListOfDefs("Args");
+    for (const auto *Arg : Args)
+      createArgument(*Arg, R.getName())->writeDumpChildren(SS);
+    if (SS.tell()) {
+      OS << "  void Visit" << R.getName() << "Attr(const " << R.getName()
+         << "Attr *A) {\n";
+      if (!Args.empty())
+        OS << "    const auto *SA = cast<" << R.getName()
+           << "Attr>(A); (void)SA;\n";
+      OS << SS.str();
+      OS << "  }\n";
+    }
+  }
 }
 
 void EmitClangAttrParserStringSwitches(RecordKeeper &Records,
diff --git a/clang/utils/TableGen/TableGen.cpp b/clang/utils/TableGen/TableGen.cpp
index c02fa3d..f40d7f1 100644
--- a/clang/utils/TableGen/TableGen.cpp
+++ b/clang/utils/TableGen/TableGen.cpp
@@ -40,7 +40,8 @@
   GenClangAttrParsedAttrList,
   GenClangAttrParsedAttrImpl,
   GenClangAttrParsedAttrKinds,
-  GenClangAttrDump,
+  GenClangAttrTextNodeDump,
+  GenClangAttrNodeTraverse,
   GenClangDiagsDefs,
   GenClangDiagGroups,
   GenClangDiagsIndexName,
@@ -112,8 +113,10 @@
         clEnumValN(GenClangAttrParsedAttrKinds,
                    "gen-clang-attr-parsed-attr-kinds",
                    "Generate a clang parsed attribute kinds"),
-        clEnumValN(GenClangAttrDump, "gen-clang-attr-dump",
-                   "Generate clang attribute dumper"),
+        clEnumValN(GenClangAttrTextNodeDump, "gen-clang-attr-text-node-dump",
+                   "Generate clang attribute text node dumper"),
+        clEnumValN(GenClangAttrNodeTraverse, "gen-clang-attr-node-traverse",
+                   "Generate clang attribute traverser"),
         clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs",
                    "Generate Clang diagnostics definitions"),
         clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups",
@@ -221,8 +224,11 @@
   case GenClangAttrParsedAttrKinds:
     EmitClangAttrParsedAttrKinds(Records, OS);
     break;
-  case GenClangAttrDump:
-    EmitClangAttrDump(Records, OS);
+  case GenClangAttrTextNodeDump:
+    EmitClangAttrTextNodeDump(Records, OS);
+    break;
+  case GenClangAttrNodeTraverse:
+    EmitClangAttrNodeTraverse(Records, OS);
     break;
   case GenClangDiagsDefs:
     EmitClangDiagsDefs(Records, OS, ClangComponent);
diff --git a/clang/utils/TableGen/TableGenBackends.h b/clang/utils/TableGen/TableGenBackends.h
index f23f351..410d010 100644
--- a/clang/utils/TableGen/TableGenBackends.h
+++ b/clang/utils/TableGen/TableGenBackends.h
@@ -45,7 +45,10 @@
 void EmitClangAttrParsedAttrList(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
 void EmitClangAttrParsedAttrImpl(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
 void EmitClangAttrParsedAttrKinds(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
-void EmitClangAttrDump(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
+void EmitClangAttrTextNodeDump(llvm::RecordKeeper &Records,
+                               llvm::raw_ostream &OS);
+void EmitClangAttrNodeTraverse(llvm::RecordKeeper &Records,
+                               llvm::raw_ostream &OS);
 
 void EmitClangDiagsDefs(llvm::RecordKeeper &Records, llvm::raw_ostream &OS,
                         const std::string &Component);