[NFC] Add a tablegen node for the root of the AST node hierarchies.
This is useful for the property databases we want to add for abstract
serialization, since root classes can have interesting properties.
diff --git a/clang/utils/TableGen/ClangASTEmitters.h b/clang/utils/TableGen/ClangASTEmitters.h
new file mode 100644
index 0000000..942c85f
--- /dev/null
+++ b/clang/utils/TableGen/ClangASTEmitters.h
@@ -0,0 +1,39 @@
+//=== ClangASTEmitters.h - Definitions for AST node emitters ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_AST_EMITTERS
+#define CLANG_AST_EMITTERS
+
+#include "llvm/TableGen/Record.h"
+#include "llvm/ADT/STLExtras.h"
+
+// These are spellings in the tblgen files.
+
+// The field name for the base-node property.
+// Fortunately, this is common across all the hierarchies.
+#define BaseFieldName "Base"
+
+// Comment node hierarchy.
+#define CommentNodeClassName "CommentNode"
+
+// Decl node hierarchy.
+#define DeclNodeClassName "DeclNode"
+#define DeclContextNodeClassName "DeclContext"
+
+// Stmt node hierarchy.
+#define StmtNodeClassName "StmtNode"
+
+// Type node hierarchy.
+#define TypeNodeClassName "TypeNode"
+#define AlwaysDependentClassName "AlwaysDependent"
+#define NeverCanonicalClassName "NeverCanonical"
+#define NeverCanonicalUnlessDependentClassName "NeverCanonicalUnlessDependent"
+#define LeafTypeClassName "LeafType"
+#define AbstractFieldName "Abstract"
+
+#endif
diff --git a/clang/utils/TableGen/ClangASTNodesEmitter.cpp b/clang/utils/TableGen/ClangASTNodesEmitter.cpp
index 3ece9be6..704ccda 100644
--- a/clang/utils/TableGen/ClangASTNodesEmitter.cpp
+++ b/clang/utils/TableGen/ClangASTNodesEmitter.cpp
@@ -10,8 +10,10 @@
//
//===----------------------------------------------------------------------===//
+#include "ClangASTEmitters.h"
#include "TableGenBackends.h"
+#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <cctype>
@@ -30,8 +32,11 @@
typedef ChildMap::const_iterator ChildIterator;
RecordKeeper &Records;
- Record Root;
+ Record *Root = nullptr;
+ const std::string &NodeClassName;
const std::string &BaseSuffix;
+ std::string MacroHierarchyName;
+ ChildMap Tree;
// Create a macro-ized version of a name
static std::string macroName(std::string S) {
@@ -41,23 +46,30 @@
return S;
}
+ const std::string ¯oHierarchyName() {
+ assert(Root && "root node not yet derived!");
+ if (MacroHierarchyName.empty())
+ MacroHierarchyName = macroName(Root->getName());
+ return MacroHierarchyName;
+ }
+
// Return the name to be printed in the base field. Normally this is
// the record's name plus the base suffix, but if it is the root node and
// the suffix is non-empty, it's just the suffix.
std::string baseName(Record &R) {
- if (&R == &Root && !BaseSuffix.empty())
+ if (&R == Root && !BaseSuffix.empty())
return BaseSuffix;
return R.getName().str() + BaseSuffix;
}
- std::pair<Record *, Record *> EmitNode (const ChildMap &Tree, raw_ostream& OS,
- Record *Base);
+ void deriveChildTree();
+
+ std::pair<Record *, Record *> EmitNode(raw_ostream& OS, Record *Base);
public:
explicit ClangASTNodesEmitter(RecordKeeper &R, const std::string &N,
const std::string &S)
- : Records(R), Root(N, SMLoc(), R), BaseSuffix(S)
- {}
+ : Records(R), NodeClassName(N), BaseSuffix(S) {}
// run - Output the .inc file contents
void run(raw_ostream &OS);
@@ -70,23 +82,19 @@
// Returns the first and last non-abstract subrecords
// Called recursively to ensure that nodes remain contiguous
-std::pair<Record *, Record *> ClangASTNodesEmitter::EmitNode(
- const ChildMap &Tree,
- raw_ostream &OS,
- Record *Base) {
+std::pair<Record *, Record *> ClangASTNodesEmitter::EmitNode(raw_ostream &OS,
+ Record *Base) {
std::string BaseName = macroName(Base->getName());
ChildIterator i = Tree.lower_bound(Base), e = Tree.upper_bound(Base);
Record *First = nullptr, *Last = nullptr;
- // This might be the pseudo-node for Stmt; don't assume it has an Abstract
- // bit
- if (Base->getValue("Abstract") && !Base->getValueAsBit("Abstract"))
+ if (!Base->getValueAsBit(AbstractFieldName))
First = Last = Base;
for (; i != e; ++i) {
Record *R = i->second;
- bool Abstract = R->getValueAsBit("Abstract");
+ bool Abstract = R->getValueAsBit(AbstractFieldName);
std::string NodeName = macroName(R->getName());
OS << "#ifndef " << NodeName << "\n";
@@ -95,7 +103,7 @@
OS << "#endif\n";
if (Abstract)
- OS << "ABSTRACT_" << macroName(Root.getName()) << "(" << NodeName << "("
+ OS << "ABSTRACT_" << macroHierarchyName() << "(" << NodeName << "("
<< R->getName() << ", " << baseName(*Base) << "))\n";
else
OS << NodeName << "(" << R->getName() << ", "
@@ -103,7 +111,7 @@
if (Tree.find(R) != Tree.end()) {
const std::pair<Record *, Record *> &Result
- = EmitNode(Tree, OS, R);
+ = EmitNode(OS, R);
if (!First && Result.first)
First = Result.first;
if (Result.second)
@@ -122,10 +130,10 @@
if (First) {
assert (Last && "Got a first node but not a last node for a range!");
- if (Base == &Root)
- OS << "LAST_" << macroName(Root.getName()) << "_RANGE(";
+ if (Base == Root)
+ OS << "LAST_" << macroHierarchyName() << "_RANGE(";
else
- OS << macroName(Root.getName()) << "_RANGE(";
+ OS << macroHierarchyName() << "_RANGE(";
OS << Base->getName() << ", " << First->getName() << ", "
<< Last->getName() << ")\n\n";
}
@@ -133,46 +141,58 @@
return std::make_pair(First, Last);
}
-void ClangASTNodesEmitter::run(raw_ostream &OS) {
- emitSourceFileHeader("List of AST nodes of a particular kind", OS);
+void ClangASTNodesEmitter::deriveChildTree() {
+ assert(Root == nullptr && "already computed tree");
- // Write the preamble
- OS << "#ifndef ABSTRACT_" << macroName(Root.getName()) << "\n";
- OS << "# define ABSTRACT_" << macroName(Root.getName()) << "(Type) Type\n";
- OS << "#endif\n";
-
- OS << "#ifndef " << macroName(Root.getName()) << "_RANGE\n";
- OS << "# define "
- << macroName(Root.getName()) << "_RANGE(Base, First, Last)\n";
- OS << "#endif\n\n";
-
- OS << "#ifndef LAST_" << macroName(Root.getName()) << "_RANGE\n";
- OS << "# define LAST_"
- << macroName(Root.getName()) << "_RANGE(Base, First, Last) "
- << macroName(Root.getName()) << "_RANGE(Base, First, Last)\n";
- OS << "#endif\n\n";
-
// Emit statements
const std::vector<Record*> Stmts
- = Records.getAllDerivedDefinitions(Root.getName());
-
- ChildMap Tree;
+ = Records.getAllDerivedDefinitions(NodeClassName);
for (unsigned i = 0, e = Stmts.size(); i != e; ++i) {
Record *R = Stmts[i];
- if (R->getValue("Base"))
- Tree.insert(std::make_pair(R->getValueAsDef("Base"), R));
+ if (auto B = R->getValueAsOptionalDef(BaseFieldName))
+ Tree.insert(std::make_pair(B, R));
+ else if (Root)
+ PrintFatalError(R->getLoc(),
+ Twine("multiple root nodes in \"") + NodeClassName
+ + "\" hierarchy");
else
- Tree.insert(std::make_pair(&Root, R));
+ Root = R;
}
- EmitNode(Tree, OS, &Root);
+ if (!Root)
+ PrintFatalError(Twine("didn't find root node in \"") + NodeClassName
+ + "\" hierarchy");
+}
- OS << "#undef " << macroName(Root.getName()) << "\n";
- OS << "#undef " << macroName(Root.getName()) << "_RANGE\n";
- OS << "#undef LAST_" << macroName(Root.getName()) << "_RANGE\n";
- OS << "#undef ABSTRACT_" << macroName(Root.getName()) << "\n";
+void ClangASTNodesEmitter::run(raw_ostream &OS) {
+ deriveChildTree();
+
+ emitSourceFileHeader("List of AST nodes of a particular kind", OS);
+
+ // Write the preamble
+ OS << "#ifndef ABSTRACT_" << macroHierarchyName() << "\n";
+ OS << "# define ABSTRACT_" << macroHierarchyName() << "(Type) Type\n";
+ OS << "#endif\n";
+
+ OS << "#ifndef " << macroHierarchyName() << "_RANGE\n";
+ OS << "# define "
+ << macroHierarchyName() << "_RANGE(Base, First, Last)\n";
+ OS << "#endif\n\n";
+
+ OS << "#ifndef LAST_" << macroHierarchyName() << "_RANGE\n";
+ OS << "# define LAST_"
+ << macroHierarchyName() << "_RANGE(Base, First, Last) "
+ << macroHierarchyName() << "_RANGE(Base, First, Last)\n";
+ OS << "#endif\n\n";
+
+ EmitNode(OS, Root);
+
+ OS << "#undef " << macroHierarchyName() << "\n";
+ OS << "#undef " << macroHierarchyName() << "_RANGE\n";
+ OS << "#undef LAST_" << macroHierarchyName() << "_RANGE\n";
+ OS << "#undef ABSTRACT_" << macroHierarchyName() << "\n";
}
void clang::EmitClangASTNodes(RecordKeeper &RK, raw_ostream &OS,
@@ -199,15 +219,14 @@
typedef std::vector<Record*> RecordVector;
RecordVector DeclContextsVector
- = Records.getAllDerivedDefinitions("DeclContext");
- RecordVector Decls = Records.getAllDerivedDefinitions("Decl");
+ = Records.getAllDerivedDefinitions(DeclContextNodeClassName);
+ RecordVector Decls = Records.getAllDerivedDefinitions(DeclNodeClassName);
RecordSet DeclContexts (DeclContextsVector.begin(), DeclContextsVector.end());
for (RecordVector::iterator i = Decls.begin(), e = Decls.end(); i != e; ++i) {
Record *R = *i;
- if (R->getValue("Base")) {
- Record *B = R->getValueAsDef("Base");
+ if (Record *B = R->getValueAsOptionalDef(BaseFieldName)) {
if (DeclContexts.find(B) != DeclContexts.end()) {
OS << "DECL_CONTEXT_BASE(" << B->getName() << ")\n";
DeclContexts.erase(B);
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp
index 0d92a32..f9f285c 100644
--- a/clang/utils/TableGen/ClangAttrEmitter.cpp
+++ b/clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "TableGenBackends.h"
+#include "ClangASTEmitters.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
@@ -1808,7 +1809,7 @@
} // end anonymous namespace
static bool doesDeclDeriveFrom(const Record *D, const Record *Base) {
- const Record *CurrentBase = D->getValueAsDef("Base");
+ const Record *CurrentBase = D->getValueAsOptionalDef(BaseFieldName);
if (!CurrentBase)
return false;
if (CurrentBase == Base)
@@ -1849,7 +1850,8 @@
std::vector<Record *> Aggregates =
Records.getAllDerivedDefinitions("AttrSubjectMatcherAggregateRule");
- std::vector<Record *> DeclNodes = Records.getAllDerivedDefinitions("DDecl");
+ std::vector<Record *> DeclNodes =
+ Records.getAllDerivedDefinitions(DeclNodeClassName);
for (const auto *Aggregate : Aggregates) {
Record *SubjectDecl = Aggregate->getValueAsDef("Subject");
@@ -3303,9 +3305,8 @@
// If we couldn't find the DiagSpelling in this object, we can check to see
// if the object is one that has a base, and if it is, loop up to the Base
// member recursively.
- std::string Super = R.getSuperClasses().back().first->getName();
- if (Super == "DDecl" || Super == "DStmt")
- return GetDiagnosticSpelling(*R.getValueAsDef("Base"));
+ if (auto Base = R.getValueAsOptionalDef(BaseFieldName))
+ return GetDiagnosticSpelling(*Base);
return "";
}
@@ -3385,7 +3386,8 @@
if (I != CustomSubjectSet.end())
return *I;
- Record *Base = Subject.getValueAsDef("Base");
+ // This only works with non-root Decls.
+ Record *Base = Subject.getValueAsDef(BaseFieldName);
// Not currently support custom subjects within custom subjects.
if (Base->isSubClassOf("SubsetSubject")) {
diff --git a/clang/utils/TableGen/ClangTypeNodesEmitter.cpp b/clang/utils/TableGen/ClangTypeNodesEmitter.cpp
index c9986c8..7640953 100644
--- a/clang/utils/TableGen/ClangTypeNodesEmitter.cpp
+++ b/clang/utils/TableGen/ClangTypeNodesEmitter.cpp
@@ -45,6 +45,9 @@
//
//===----------------------------------------------------------------------===//
+#include "ClangASTEmitters.h"
+#include "TableGenBackends.h"
+
#include "llvm/ADT/StringRef.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
@@ -52,7 +55,6 @@
#include <set>
#include <string>
#include <vector>
-#include "TableGenBackends.h"
using namespace llvm;
@@ -66,16 +68,7 @@
#define LastTypeMacroName "LAST_TYPE"
#define LeafTypeMacroName "LEAF_TYPE"
-// These are spellings in the tblgen file.
-// (Type is also used for the spelling of the AST class.)
#define TypeClassName "Type"
-#define DerivedTypeClassName "DerivedType"
-#define AlwaysDependentClassName "AlwaysDependent"
-#define NeverCanonicalClassName "NeverCanonical"
-#define NeverCanonicalUnlessDependentClassName "NeverCanonicalUnlessDependent"
-#define LeafTypeClassName "LeafType"
-#define AbstractFieldName "Abstract"
-#define BaseFieldName "Base"
static StringRef getIdForType(Record *type) {
// The record name is expected to be the full C++ class name,
@@ -96,7 +89,7 @@
public:
TypeNodeEmitter(RecordKeeper &records, raw_ostream &out)
: Records(records), Out(out),
- Types(Records.getAllDerivedDefinitions("Type")) {
+ Types(Records.getAllDerivedDefinitions(TypeNodeClassName)) {
}
void emit();
@@ -151,9 +144,12 @@
void TypeNodeEmitter::emitNodeInvocations() {
for (auto type : Types) {
- // The name with the Type suffix.
+ // The name without the Type suffix.
StringRef id = getIdForType(type);
+ // If this is the Type node itself, skip it.
+ if (id.empty()) continue;
+
// Figure out which macro to use.
StringRef macroName;
auto setMacroName = [&](StringRef newName) {
@@ -177,8 +173,8 @@
// Compute the base class.
StringRef baseName = TypeClassName;
- if (type->isSubClassOf(DerivedTypeClassName))
- baseName = type->getValueAsDef(BaseFieldName)->getName();
+ if (auto base = type->getValueAsOptionalDef(BaseFieldName))
+ baseName = base->getName();
// Generate the invocation line.
Out << macroName << "(" << id << ", " << baseName << ")\n";
diff --git a/clang/utils/TableGen/TableGen.cpp b/clang/utils/TableGen/TableGen.cpp
index 29c6d76..c988a58 100644
--- a/clang/utils/TableGen/TableGen.cpp
+++ b/clang/utils/TableGen/TableGen.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "TableGenBackends.h" // Declares all backends.
+#include "ClangASTEmitters.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
@@ -263,14 +264,14 @@
EmitClangDiagsIndexName(Records, OS);
break;
case GenClangCommentNodes:
- EmitClangASTNodes(Records, OS, "Comment", "");
+ EmitClangASTNodes(Records, OS, CommentNodeClassName, "");
break;
case GenClangDeclNodes:
- EmitClangASTNodes(Records, OS, "Decl", "Decl");
+ EmitClangASTNodes(Records, OS, DeclNodeClassName, "Decl");
EmitClangDeclContext(Records, OS);
break;
case GenClangStmtNodes:
- EmitClangASTNodes(Records, OS, "Stmt", "");
+ EmitClangASTNodes(Records, OS, StmtNodeClassName, "");
break;
case GenClangTypeNodes:
EmitClangTypeNodes(Records, OS);