summaryrefslogtreecommitdiffstats
path: root/clang/utils
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2019-10-25 16:28:03 -0700
committerJohn McCall <rjmccall@apple.com>2019-10-25 16:39:21 -0700
commitbaf91d02da6e68c4ee6723ef68911fcd80ece6a5 (patch)
tree05796f6be2edb73698c2ad7924bed206104590ff /clang/utils
parent27e2c8faec6926fafdbd4d9b5b2f827f002e1c8e (diff)
downloadbcm5719-llvm-baf91d02da6e68c4ee6723ef68911fcd80ece6a5.tar.gz
bcm5719-llvm-baf91d02da6e68c4ee6723ef68911fcd80ece6a5.zip
[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.
Diffstat (limited to 'clang/utils')
-rw-r--r--clang/utils/TableGen/ClangASTEmitters.h39
-rw-r--r--clang/utils/TableGen/ClangASTNodesEmitter.cpp119
-rw-r--r--clang/utils/TableGen/ClangAttrEmitter.cpp14
-rw-r--r--clang/utils/TableGen/ClangTypeNodesEmitter.cpp24
-rw-r--r--clang/utils/TableGen/TableGen.cpp7
5 files changed, 130 insertions, 73 deletions
diff --git a/clang/utils/TableGen/ClangASTEmitters.h b/clang/utils/TableGen/ClangASTEmitters.h
new file mode 100644
index 00000000000..942c85f1613
--- /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 3ece9be6a5c..704ccda9bbd 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 @@ class ClangASTNodesEmitter {
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 @@ class ClangASTNodesEmitter {
return S;
}
+ const std::string &macroHierarchyName() {
+ 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 @@ public:
// 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 @@ std::pair<Record *, Record *> ClangASTNodesEmitter::EmitNode(
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 @@ std::pair<Record *, Record *> ClangASTNodesEmitter::EmitNode(
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 @@ std::pair<Record *, Record *> ClangASTNodesEmitter::EmitNode(
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 @@ std::pair<Record *, Record *> ClangASTNodesEmitter::EmitNode(
return std::make_pair(First, Last);
}
+void ClangASTNodesEmitter::deriveChildTree() {
+ assert(Root == nullptr && "already computed tree");
+
+ // Emit statements
+ const std::vector<Record*> Stmts
+ = Records.getAllDerivedDefinitions(NodeClassName);
+
+ for (unsigned i = 0, e = Stmts.size(); i != e; ++i) {
+ Record *R = Stmts[i];
+
+ 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
+ Root = R;
+ }
+
+ if (!Root)
+ PrintFatalError(Twine("didn't find root node in \"") + NodeClassName
+ + "\" hierarchy");
+}
+
void ClangASTNodesEmitter::run(raw_ostream &OS) {
+ deriveChildTree();
+
emitSourceFileHeader("List of AST nodes of a particular kind", OS);
// Write the preamble
- OS << "#ifndef ABSTRACT_" << macroName(Root.getName()) << "\n";
- OS << "# define ABSTRACT_" << macroName(Root.getName()) << "(Type) Type\n";
+ OS << "#ifndef ABSTRACT_" << macroHierarchyName() << "\n";
+ OS << "# define ABSTRACT_" << macroHierarchyName() << "(Type) Type\n";
OS << "#endif\n";
- OS << "#ifndef " << macroName(Root.getName()) << "_RANGE\n";
+ OS << "#ifndef " << macroHierarchyName() << "_RANGE\n";
OS << "# define "
- << macroName(Root.getName()) << "_RANGE(Base, First, Last)\n";
+ << macroHierarchyName() << "_RANGE(Base, First, Last)\n";
OS << "#endif\n\n";
- OS << "#ifndef LAST_" << macroName(Root.getName()) << "_RANGE\n";
+ OS << "#ifndef LAST_" << macroHierarchyName() << "_RANGE\n";
OS << "# define LAST_"
- << macroName(Root.getName()) << "_RANGE(Base, First, Last) "
- << macroName(Root.getName()) << "_RANGE(Base, First, Last)\n";
+ << macroHierarchyName() << "_RANGE(Base, First, Last) "
+ << macroHierarchyName() << "_RANGE(Base, First, Last)\n";
OS << "#endif\n\n";
-
- // Emit statements
- const std::vector<Record*> Stmts
- = Records.getAllDerivedDefinitions(Root.getName());
-
- ChildMap Tree;
-
- 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));
- else
- Tree.insert(std::make_pair(&Root, R));
- }
- EmitNode(Tree, OS, &Root);
+ EmitNode(OS, Root);
- 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";
+ 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 @@ void clang::EmitClangDeclContext(RecordKeeper &Records, raw_ostream &OS) {
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 0d92a321c74..f9f285c0d4f 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 @@ struct PragmaClangAttributeSupport {
} // 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 @@ PragmaClangAttributeSupport::PragmaClangAttributeSupport(
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 @@ static std::string GetDiagnosticSpelling(const Record &R) {
// 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 @@ static std::string GenerateCustomAppertainsTo(const Record &Subject,
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 c9986c8fa49..76409539351 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 @@ using namespace llvm;
#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 @@ class TypeNodeEmitter {
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::emitFallbackDefine(StringRef macroName,
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 @@ void TypeNodeEmitter::emitNodeInvocations() {
// 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 29c6d76f73e..c988a580f29 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 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
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);
OpenPOWER on IntegriCloud