ilya-biryukov created this revision.
ilya-biryukov added a reviewer: gribozavr2.
Herald added a project: clang.
ilya-biryukov updated this revision to Diff 237039.
ilya-biryukov added a comment.
ilya-biryukov added a parent revision: D72334: [Syntax] Build nodes for
template declarations..
Remove the (now redundant) NodeAndRole class
Only used to assign roles to child nodes for now. This is more efficient
than doing range-based queries.
In the future, will be exposed in the public API of syntax trees.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D72446
Files:
clang/include/clang/Tooling/Syntax/Tree.h
clang/lib/Tooling/Syntax/BuildTree.cpp
clang/lib/Tooling/Syntax/Tree.cpp
Index: clang/lib/Tooling/Syntax/Tree.cpp
===================================================================
--- clang/lib/Tooling/Syntax/Tree.cpp
+++ clang/lib/Tooling/Syntax/Tree.cpp
@@ -48,14 +48,20 @@
bool syntax::Tree::classof(const Node *N) { return N->kind() > NodeKind::Leaf; }
void syntax::Tree::prependChildLowLevel(Node *Child, NodeRole Role) {
- assert(Child->Parent == nullptr);
- assert(Child->NextSibling == nullptr);
assert(Child->role() == NodeRole::Detached);
assert(Role != NodeRole::Detached);
+ Child->Role = static_cast<unsigned>(Role);
+ prependChildLowLevel(Child);
+}
+
+void syntax::Tree::prependChildLowLevel(Node *Child) {
+ assert(Child->Parent == nullptr);
+ assert(Child->NextSibling == nullptr);
+ assert(Child->role() != NodeRole::Detached);
+
Child->Parent = this;
Child->NextSibling = this->FirstChild;
- Child->Role = static_cast<unsigned>(Role);
this->FirstChild = Child;
}
Index: clang/lib/Tooling/Syntax/BuildTree.cpp
===================================================================
--- clang/lib/Tooling/Syntax/BuildTree.cpp
+++ clang/lib/Tooling/Syntax/BuildTree.cpp
@@ -25,6 +25,8 @@
#include "clang/Tooling/Syntax/Tokens.h"
#include "clang/Tooling/Syntax/Tree.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallVector.h"
@@ -34,6 +36,7 @@
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
+#include <cstddef>
#include <map>
using namespace clang;
@@ -132,6 +135,32 @@
return SourceRange(Start, End);
}
+namespace {
+/// All AST hierarchy roots that can be represented as pointers.
+using ASTPtr = llvm::PointerUnion<Stmt *, Decl *>;
+/// Maintains a mapping from AST to syntax tree nodes. This class will get more
+/// complicated as we support more kinds of AST nodes, e.g. TypeLocs.
+/// FIXME: expose this as public API.
+class ASTToSyntaxMapping {
+public:
+ void add(ASTPtr From, syntax::Tree *To) {
+ assert(To != nullptr);
+
+ bool Added = Nodes.insert({From.getOpaqueValue(), To}).second;
+ (void)Added;
+ assert(Added && "mapping added twice");
+ }
+
+ syntax::Tree *find(ASTPtr P) const {
+ return Nodes.lookup(P.getOpaqueValue());
+ }
+
+private:
+ // Keys are either Stmt* or Decl*.
+ llvm::DenseMap<void *, syntax::Tree *> Nodes;
+};
+} // namespace
+
/// A helper class for constructing the syntax tree while traversing a clang
/// AST.
///
@@ -159,7 +188,18 @@
/// Populate children for \p New node, assuming it covers tokens from \p
/// Range.
- void foldNode(llvm::ArrayRef<syntax::Token> Range, syntax::Tree *New);
+ void foldNode(llvm::ArrayRef<syntax::Token> Range, syntax::Tree *New,
+ ASTPtr From) {
+ assert(New);
+ Pending.foldChildren(Arena, Range, New);
+ if (From)
+ Mapping.add(From, New);
+ }
+ void foldNode(llvm::ArrayRef<syntax::Token> Range, syntax::Tree *New,
+ TypeLoc L) {
+ // FIXME: add mapping for TypeLocs
+ foldNode(Range, New, nullptr);
+ }
/// Must be called with the range of each `DeclaratorDecl`. Ensures the
/// corresponding declarator nodes are covered by `SimpleDeclaration`.
@@ -182,8 +222,11 @@
/// Set role for \p T.
void markChildToken(const syntax::Token *T, NodeRole R);
- /// Set role for the node that spans exactly \p Range.
- void markChild(llvm::ArrayRef<syntax::Token> Range, NodeRole R);
+ /// Set role for \p N.
+ void markChild(syntax::Node *N, NodeRole R);
+ /// Set role for the syntax node matching \p N.
+ void markChild(ASTPtr N, NodeRole R);
+
/// Set role for the delayed node that spans exactly \p Range.
void markDelayedChild(llvm::ArrayRef<syntax::Token> Range, NodeRole R);
// Set role for the node that may or may not be delayed. Node must span
@@ -275,6 +318,11 @@
return Tokens;
}
+ void setRole(syntax::Node *N, NodeRole R) {
+ assert(N->role() == NodeRole::Detached);
+ N->Role = static_cast<unsigned>(R);
+ }
+
/// A collection of trees covering the input tokens.
/// When created, each tree corresponds to a single token in the file.
/// Clients call 'foldChildren' to attach one or more subtrees to a parent
@@ -291,7 +339,7 @@
auto *L = new (A.allocator()) syntax::Leaf(&T);
L->Original = true;
L->CanModify = A.tokenBuffer().spelledForExpanded(T).hasValue();
- Trees.insert(Trees.end(), {&T, NodeAndRole{L}});
+ Trees.insert(Trees.end(), {&T, L});
}
}
@@ -323,7 +371,9 @@
assert((std::next(It) == Trees.end() ||
std::next(It)->first == Range.end()) &&
"no child with the specified range");
- It->second.Role = Role;
+ assert(It->second->role() == NodeRole::Detached &&
+ "re-assigning role for a child");
+ It->second->Role = static_cast<unsigned>(Role);
}
/// Add \p Node to the forest and attach child nodes based on \p Tokens.
@@ -379,7 +429,7 @@
// EXPECTS: all tokens were consumed and are owned by a single root node.
syntax::Node *finalize() && {
assert(Trees.size() == 1);
- auto *Root = Trees.begin()->second.Node;
+ auto *Root = Trees.begin()->second;
Trees = {};
return Root;
}
@@ -393,9 +443,9 @@
: A.tokenBuffer().expandedTokens().end() - It->first;
R += llvm::formatv("- '{0}' covers '{1}'+{2} tokens\n",
- It->second.Node->kind(),
+ It->second->kind(),
It->first->text(A.sourceManager()), CoveredTokens);
- R += It->second.Node->dump(A);
+ R += It->second->dump(A);
}
return R;
}
@@ -419,32 +469,27 @@
"fold crosses boundaries of existing subtrees");
// (!) we need to go in reverse order, because we can only prepend.
- for (auto It = EndChildren; It != BeginChildren; --It)
- Node->prependChildLowLevel(std::prev(It)->second.Node,
- std::prev(It)->second.Role);
+ for (auto It = EndChildren; It != BeginChildren; --It) {
+ auto *N = std::prev(It)->second;
+ if (N->role() == NodeRole::Detached)
+ N->Role = static_cast<unsigned>(NodeRole::Unknown);
+ Node->prependChildLowLevel(N);
+ }
// Mark that this node came from the AST and is backed by the source code.
Node->Original = true;
Node->CanModify = A.tokenBuffer().spelledForExpanded(Tokens).hasValue();
Trees.erase(BeginChildren, EndChildren);
- Trees.insert({FirstToken, NodeAndRole(Node)});
+ Trees.insert({FirstToken, Node});
}
- /// A with a role that should be assigned to it when adding to a parent.
- struct NodeAndRole {
- explicit NodeAndRole(syntax::Node *Node)
- : Node(Node), Role(NodeRole::Unknown) {}
-
- syntax::Node *Node;
- NodeRole Role;
- };
/// Maps from the start token to a subtree starting at that token.
/// Keys in the map are pointers into the array of expanded tokens, so
/// pointer order corresponds to the order of preprocessor tokens.
/// FIXME: storing the end tokens is redundant.
/// FIXME: the key of a map is redundant, it is also stored in NodeForRange.
- std::map<const syntax::Token *, NodeAndRole> Trees;
+ std::map<const syntax::Token *, syntax::Node *> Trees;
/// See documentation of `foldChildrenDelayed` for details.
struct DelayedFold {
@@ -464,6 +509,7 @@
LocationToToken;
Forest Pending;
llvm::DenseSet<Decl *> DeclsWithoutSemicolons;
+ ASTToSyntaxMapping Mapping;
};
namespace {
@@ -490,10 +536,10 @@
Builder.sourceManager(), DD->getTypeSourceInfo()->getTypeLoc(),
getQualifiedNameStart(DD), Initializer);
if (Declarator.isValid()) {
- auto Tokens =
- Builder.getRange(Declarator.getBegin(), Declarator.getEnd());
- Builder.foldNode(Tokens, new (allocator()) syntax::SimpleDeclarator);
- Builder.markChild(Tokens, syntax::NodeRole::SimpleDeclaration_declarator);
+ auto *N = new (allocator()) syntax::SimpleDeclarator;
+ Builder.foldNode(
+ Builder.getRange(Declarator.getBegin(), Declarator.getEnd()), N, DD);
+ Builder.markChild(N, syntax::NodeRole::SimpleDeclaration_declarator);
}
return true;
@@ -507,9 +553,9 @@
Builder.sourceManager(), D->getTypeSourceInfo()->getTypeLoc(),
/*Name=*/D->getLocation(), /*Initializer=*/SourceRange());
if (R.isValid()) {
- auto Tokens = Builder.getRange(R.getBegin(), R.getEnd());
- Builder.foldNode(Tokens, new (allocator()) syntax::SimpleDeclarator);
- Builder.markChild(Tokens, syntax::NodeRole::SimpleDeclaration_declarator);
+ auto *N = new (allocator()) syntax::SimpleDeclarator;
+ Builder.foldNode(Builder.getRange(R.getBegin(), R.getEnd()), N, D);
+ Builder.markChild(N, syntax::NodeRole::SimpleDeclaration_declarator);
}
return true;
}
@@ -517,7 +563,7 @@
bool VisitDecl(Decl *D) {
assert(!D->isImplicit());
Builder.foldNode(Builder.getDeclRange(D),
- new (allocator()) syntax::UnknownDeclaration());
+ new (allocator()) syntax::UnknownDeclaration(), D);
return true;
}
@@ -530,11 +576,11 @@
return false;
if (C->isExplicitSpecialization())
return true; // we are only interested in explicit instantiations.
- if (!WalkUpFromClassTemplateSpecializationDecl(C))
- return false;
+ auto *Declaration =
+ cast<syntax::SimpleDeclaration>(handleFreeStandingTagDecl(C));
foldExplicitTemplateInstantiation(
Builder.getTemplateRange(C), Builder.findToken(C->getExternLoc()),
- Builder.findToken(C->getTemplateKeywordLoc()), Builder.getDeclRange(C));
+ Builder.findToken(C->getTemplateKeywordLoc()), Declaration);
return true;
}
@@ -542,7 +588,7 @@
foldTemplateDeclaration(
Builder.getDeclRange(S),
Builder.findToken(S->getTemplateParameters()->getTemplateLoc()),
- Builder.getDeclRange(S->getTemplatedDecl()));
+ Builder.getDeclRange(S->getTemplatedDecl()), S);
return true;
}
@@ -552,24 +598,30 @@
assert(C->getNumTemplateParameterLists() == 0);
return true;
}
+ handleFreeStandingTagDecl(C);
+ return true;
+ }
+
+ syntax::Declaration *handleFreeStandingTagDecl(TagDecl *C) {
+ assert(C->isFreeStanding());
// Class is a declaration specifier and needs a spanning declaration node.
auto DeclarationRange = Builder.getDeclRange(C);
- Builder.foldNode(DeclarationRange,
- new (allocator()) syntax::SimpleDeclaration);
+ syntax::Declaration *Result = new (allocator()) syntax::SimpleDeclaration;
+ Builder.foldNode(DeclarationRange, Result, nullptr);
// Build TemplateDeclaration nodes if we had template parameters.
auto ConsumeTemplateParameters = [&](const TemplateParameterList &L) {
auto *TemplateKW = Builder.findToken(L.getTemplateLoc());
auto R = llvm::makeArrayRef(TemplateKW, DeclarationRange.end());
- foldTemplateDeclaration(R, TemplateKW, DeclarationRange);
-
+ Result =
+ foldTemplateDeclaration(R, TemplateKW, DeclarationRange, nullptr);
DeclarationRange = R;
};
if (auto *S = llvm::dyn_cast<ClassTemplatePartialSpecializationDecl>(C))
ConsumeTemplateParameters(*S->getTemplateParameters());
for (unsigned I = C->getNumTemplateParameterLists(); 0 < I; --I)
ConsumeTemplateParameters(*C->getTemplateParameterList(I - 1));
- return true;
+ return Result;
}
bool WalkUpFromTranslationUnitDecl(TranslationUnitDecl *TU) {
@@ -587,14 +639,14 @@
Builder.markChildToken(S->getRBracLoc(), NodeRole::CloseParen);
Builder.foldNode(Builder.getStmtRange(S),
- new (allocator()) syntax::CompoundStatement);
+ new (allocator()) syntax::CompoundStatement, S);
return true;
}
// Some statements are not yet handled by syntax trees.
bool WalkUpFromStmt(Stmt *S) {
Builder.foldNode(Builder.getStmtRange(S),
- new (allocator()) syntax::UnknownStatement);
+ new (allocator()) syntax::UnknownStatement, S);
return true;
}
@@ -632,7 +684,7 @@
bool WalkUpFromExpr(Expr *E) {
assert(!isImplicitExpr(E) && "should be handled by TraverseStmt");
Builder.foldNode(Builder.getExprRange(E),
- new (allocator()) syntax::UnknownExpression);
+ new (allocator()) syntax::UnknownExpression, E);
return true;
}
@@ -644,7 +696,7 @@
// FIXME: build corresponding nodes for the name of this namespace.
return true;
}
- Builder.foldNode(Tokens, new (allocator()) syntax::NamespaceDefinition);
+ Builder.foldNode(Tokens, new (allocator()) syntax::NamespaceDefinition, S);
return true;
}
@@ -659,7 +711,7 @@
Builder.markChildToken(L.getLParenLoc(), syntax::NodeRole::OpenParen);
Builder.markChildToken(L.getRParenLoc(), syntax::NodeRole::CloseParen);
Builder.foldNode(Builder.getRange(L.getLParenLoc(), L.getRParenLoc()),
- new (allocator()) syntax::ParenDeclarator);
+ new (allocator()) syntax::ParenDeclarator, L);
return true;
}
@@ -670,7 +722,7 @@
syntax::NodeRole::ArraySubscript_sizeExpression);
Builder.markChildToken(L.getRBracketLoc(), syntax::NodeRole::CloseParen);
Builder.foldNode(Builder.getRange(L.getLBracketLoc(), L.getRBracketLoc()),
- new (allocator()) syntax::ArraySubscript);
+ new (allocator()) syntax::ArraySubscript, L);
return true;
}
@@ -682,7 +734,7 @@
syntax::NodeRole::ParametersAndQualifiers_parameter);
Builder.markChildToken(L.getRParenLoc(), syntax::NodeRole::CloseParen);
Builder.foldNode(Builder.getRange(L.getLParenLoc(), L.getEndLoc()),
- new (allocator()) syntax::ParametersAndQualifiers);
+ new (allocator()) syntax::ParametersAndQualifiers, L);
return true;
}
@@ -700,7 +752,7 @@
bool WalkUpFromMemberPointerTypeLoc(MemberPointerTypeLoc L) {
auto SR = L.getLocalSourceRange();
Builder.foldNode(Builder.getRange(SR.getBegin(), SR.getEnd()),
- new (allocator()) syntax::MemberPointer);
+ new (allocator()) syntax::MemberPointer, L);
return true;
}
@@ -709,13 +761,13 @@
// and fold resulting nodes.
bool WalkUpFromDeclStmt(DeclStmt *S) {
Builder.foldNode(Builder.getStmtRange(S),
- new (allocator()) syntax::DeclarationStatement);
+ new (allocator()) syntax::DeclarationStatement, S);
return true;
}
bool WalkUpFromNullStmt(NullStmt *S) {
Builder.foldNode(Builder.getStmtRange(S),
- new (allocator()) syntax::EmptyStatement);
+ new (allocator()) syntax::EmptyStatement, S);
return true;
}
@@ -724,7 +776,7 @@
syntax::NodeRole::IntroducerKeyword);
Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement);
Builder.foldNode(Builder.getStmtRange(S),
- new (allocator()) syntax::SwitchStatement);
+ new (allocator()) syntax::SwitchStatement, S);
return true;
}
@@ -734,7 +786,7 @@
Builder.markExprChild(S->getLHS(), syntax::NodeRole::CaseStatement_value);
Builder.markStmtChild(S->getSubStmt(), syntax::NodeRole::BodyStatement);
Builder.foldNode(Builder.getStmtRange(S),
- new (allocator()) syntax::CaseStatement);
+ new (allocator()) syntax::CaseStatement, S);
return true;
}
@@ -743,7 +795,7 @@
syntax::NodeRole::IntroducerKeyword);
Builder.markStmtChild(S->getSubStmt(), syntax::NodeRole::BodyStatement);
Builder.foldNode(Builder.getStmtRange(S),
- new (allocator()) syntax::DefaultStatement);
+ new (allocator()) syntax::DefaultStatement, S);
return true;
}
@@ -756,7 +808,7 @@
Builder.markStmtChild(S->getElse(),
syntax::NodeRole::IfStatement_elseStatement);
Builder.foldNode(Builder.getStmtRange(S),
- new (allocator()) syntax::IfStatement);
+ new (allocator()) syntax::IfStatement, S);
return true;
}
@@ -764,7 +816,7 @@
Builder.markChildToken(S->getForLoc(), syntax::NodeRole::IntroducerKeyword);
Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement);
Builder.foldNode(Builder.getStmtRange(S),
- new (allocator()) syntax::ForStatement);
+ new (allocator()) syntax::ForStatement, S);
return true;
}
@@ -773,7 +825,7 @@
syntax::NodeRole::IntroducerKeyword);
Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement);
Builder.foldNode(Builder.getStmtRange(S),
- new (allocator()) syntax::WhileStatement);
+ new (allocator()) syntax::WhileStatement, S);
return true;
}
@@ -781,7 +833,7 @@
Builder.markChildToken(S->getContinueLoc(),
syntax::NodeRole::IntroducerKeyword);
Builder.foldNode(Builder.getStmtRange(S),
- new (allocator()) syntax::ContinueStatement);
+ new (allocator()) syntax::ContinueStatement, S);
return true;
}
@@ -789,7 +841,7 @@
Builder.markChildToken(S->getBreakLoc(),
syntax::NodeRole::IntroducerKeyword);
Builder.foldNode(Builder.getStmtRange(S),
- new (allocator()) syntax::BreakStatement);
+ new (allocator()) syntax::BreakStatement, S);
return true;
}
@@ -799,7 +851,7 @@
Builder.markExprChild(S->getRetValue(),
syntax::NodeRole::ReturnStatement_value);
Builder.foldNode(Builder.getStmtRange(S),
- new (allocator()) syntax::ReturnStatement);
+ new (allocator()) syntax::ReturnStatement, S);
return true;
}
@@ -807,13 +859,13 @@
Builder.markChildToken(S->getForLoc(), syntax::NodeRole::IntroducerKeyword);
Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement);
Builder.foldNode(Builder.getStmtRange(S),
- new (allocator()) syntax::RangeBasedForStatement);
+ new (allocator()) syntax::RangeBasedForStatement, S);
return true;
}
bool WalkUpFromEmptyDecl(EmptyDecl *S) {
Builder.foldNode(Builder.getDeclRange(S),
- new (allocator()) syntax::EmptyDeclaration);
+ new (allocator()) syntax::EmptyDeclaration, S);
return true;
}
@@ -823,55 +875,56 @@
Builder.markExprChild(S->getMessage(),
syntax::NodeRole::StaticAssertDeclaration_message);
Builder.foldNode(Builder.getDeclRange(S),
- new (allocator()) syntax::StaticAssertDeclaration);
+ new (allocator()) syntax::StaticAssertDeclaration, S);
return true;
}
bool WalkUpFromLinkageSpecDecl(LinkageSpecDecl *S) {
Builder.foldNode(Builder.getDeclRange(S),
- new (allocator()) syntax::LinkageSpecificationDeclaration);
+ new (allocator()) syntax::LinkageSpecificationDeclaration,
+ S);
return true;
}
bool WalkUpFromNamespaceAliasDecl(NamespaceAliasDecl *S) {
Builder.foldNode(Builder.getDeclRange(S),
- new (allocator()) syntax::NamespaceAliasDefinition);
+ new (allocator()) syntax::NamespaceAliasDefinition, S);
return true;
}
bool WalkUpFromUsingDirectiveDecl(UsingDirectiveDecl *S) {
Builder.foldNode(Builder.getDeclRange(S),
- new (allocator()) syntax::UsingNamespaceDirective);
+ new (allocator()) syntax::UsingNamespaceDirective, S);
return true;
}
bool WalkUpFromUsingDecl(UsingDecl *S) {
Builder.foldNode(Builder.getDeclRange(S),
- new (allocator()) syntax::UsingDeclaration);
+ new (allocator()) syntax::UsingDeclaration, S);
return true;
}
bool WalkUpFromUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *S) {
Builder.foldNode(Builder.getDeclRange(S),
- new (allocator()) syntax::UsingDeclaration);
+ new (allocator()) syntax::UsingDeclaration, S);
return true;
}
bool WalkUpFromUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *S) {
Builder.foldNode(Builder.getDeclRange(S),
- new (allocator()) syntax::UsingDeclaration);
+ new (allocator()) syntax::UsingDeclaration, S);
return true;
}
bool WalkUpFromTypeAliasDecl(TypeAliasDecl *S) {
Builder.foldNode(Builder.getDeclRange(S),
- new (allocator()) syntax::TypeAliasDeclaration);
+ new (allocator()) syntax::TypeAliasDeclaration, S);
return true;
}
private:
/// Returns the range of the built node.
- llvm::ArrayRef<syntax::Token> BuildTrailingReturn(FunctionProtoTypeLoc L) {
+ syntax::TrailingReturnType *BuildTrailingReturn(FunctionProtoTypeLoc L) {
assert(L.getTypePtr()->hasTrailingReturn());
auto ReturnedType = L.getReturnLoc();
@@ -880,12 +933,12 @@
getDeclaratorRange(this->Builder.sourceManager(), ReturnedType,
/*Name=*/SourceLocation(),
/*Initializer=*/SourceLocation());
- llvm::ArrayRef<syntax::Token> ReturnDeclaratorTokens;
+ syntax::SimpleDeclarator *ReturnDeclarator = nullptr;
if (ReturnDeclaratorRange.isValid()) {
- ReturnDeclaratorTokens = Builder.getRange(
- ReturnDeclaratorRange.getBegin(), ReturnDeclaratorRange.getEnd());
- Builder.foldNode(ReturnDeclaratorTokens,
- new (allocator()) syntax::SimpleDeclarator);
+ ReturnDeclarator = new (allocator()) syntax::SimpleDeclarator;
+ Builder.foldNode(Builder.getRange(ReturnDeclaratorRange.getBegin(),
+ ReturnDeclaratorRange.getEnd()),
+ ReturnDeclarator, nullptr);
}
// Build node for trailing return type.
@@ -895,18 +948,18 @@
assert(Arrow->kind() == tok::arrow);
auto Tokens = llvm::makeArrayRef(Arrow, Return.end());
Builder.markChildToken(Arrow, syntax::NodeRole::TrailingReturnType_arrow);
- if (!ReturnDeclaratorTokens.empty())
- Builder.markChild(ReturnDeclaratorTokens,
+ if (ReturnDeclarator)
+ Builder.markChild(ReturnDeclarator,
syntax::NodeRole::TrailingReturnType_declarator);
- Builder.foldNode(Tokens, new (allocator()) syntax::TrailingReturnType);
- return Tokens;
+ auto *R = new (allocator()) syntax::TrailingReturnType;
+ Builder.foldNode(Tokens, R, nullptr);
+ return R;
}
- void
- foldExplicitTemplateInstantiation(ArrayRef<syntax::Token> Range,
- const syntax::Token *ExternKW,
- const syntax::Token *TemplateKW,
- ArrayRef<syntax::Token> InnerDeclaration) {
+ void foldExplicitTemplateInstantiation(
+ ArrayRef<syntax::Token> Range, const syntax::Token *ExternKW,
+ const syntax::Token *TemplateKW,
+ syntax::SimpleDeclaration *InnerDeclaration) {
assert(!ExternKW || ExternKW->kind() == tok::kw_extern);
assert(TemplateKW && TemplateKW->kind() == tok::kw_template);
Builder.markChildToken(
@@ -917,18 +970,22 @@
InnerDeclaration,
syntax::NodeRole::ExplicitTemplateInstantiation_declaration);
Builder.foldNode(Range,
- new (allocator()) syntax::ExplicitTemplateInstantiation);
+ new (allocator()) syntax::ExplicitTemplateInstantiation,
+ nullptr);
}
- void foldTemplateDeclaration(ArrayRef<syntax::Token> Range,
- const syntax::Token *TemplateKW,
- ArrayRef<syntax::Token> TemplatedDeclaration) {
+ syntax::TemplateDeclaration *foldTemplateDeclaration(
+ ArrayRef<syntax::Token> Range, const syntax::Token *TemplateKW,
+ ArrayRef<syntax::Token> TemplatedDeclaration, Decl *From) {
assert(TemplateKW && TemplateKW->kind() == tok::kw_template);
Builder.markChildToken(TemplateKW, syntax::NodeRole::IntroducerKeyword);
Builder.markMaybeDelayedChild(
TemplatedDeclaration,
syntax::NodeRole::TemplateDeclaration_declaration);
- Builder.foldNode(Range, new (allocator()) syntax::TemplateDeclaration);
+
+ auto *N = new (allocator()) syntax::TemplateDeclaration;
+ Builder.foldNode(Range, N, From);
+ return N;
}
/// A small helper to save some typing.
@@ -939,11 +996,6 @@
};
} // namespace
-void syntax::TreeBuilder::foldNode(llvm::ArrayRef<syntax::Token> Range,
- syntax::Tree *New) {
- Pending.foldChildren(Arena, Range, New);
-}
-
void syntax::TreeBuilder::noticeDeclRange(llvm::ArrayRef<syntax::Token> Range) {
if (Pending.extendDelayedFold(Range))
return;
@@ -967,9 +1019,15 @@
Pending.assignRole(*T, R);
}
-void syntax::TreeBuilder::markChild(llvm::ArrayRef<syntax::Token> Range,
- NodeRole R) {
- Pending.assignRole(Range, R);
+void syntax::TreeBuilder::markChild(syntax::Node *N, NodeRole R) {
+ assert(N);
+ setRole(N, R);
+}
+
+void syntax::TreeBuilder::markChild(ASTPtr N, NodeRole R) {
+ auto *SN = Mapping.find(N);
+ assert(SN != nullptr);
+ setRole(SN, R);
}
void syntax::TreeBuilder::markDelayedChild(llvm::ArrayRef<syntax::Token> Range,
@@ -986,24 +1044,29 @@
if (!Child)
return;
- auto Range = getStmtRange(Child);
+ syntax::Tree *ChildNode = Mapping.find(Child);
+ assert(ChildNode != nullptr);
+
// This is an expression in a statement position, consume the trailing
// semicolon and form an 'ExpressionStatement' node.
if (auto *E = dyn_cast<Expr>(Child)) {
- Pending.assignRole(getExprRange(E),
- NodeRole::ExpressionStatement_expression);
- // (!) 'getRange(Stmt)' ensures this already covers a trailing semicolon.
- Pending.foldChildren(Arena, Range,
- new (allocator()) syntax::ExpressionStatement);
+ setRole(ChildNode, NodeRole::ExpressionStatement_expression);
+ ChildNode = new (allocator()) syntax::ExpressionStatement;
+ // (!) 'getStmtRange()' ensures this covers a trailing semicolon.
+ Pending.foldChildren(Arena, getStmtRange(Child), ChildNode);
}
- Pending.assignRole(Range, Role);
+ setRole(ChildNode, Role);
}
void syntax::TreeBuilder::markExprChild(Expr *Child, NodeRole Role) {
if (!Child)
return;
+ Child = Child->IgnoreImplicit();
- Pending.assignRole(getExprRange(Child), Role);
+ syntax::Tree *ChildNode = Mapping.find(Child);
+ Child->dumpColor();
+ assert(ChildNode != nullptr);
+ setRole(ChildNode, Role);
}
const syntax::Token *syntax::TreeBuilder::findToken(SourceLocation L) const {
Index: clang/include/clang/Tooling/Syntax/Tree.h
===================================================================
--- clang/include/clang/Tooling/Syntax/Tree.h
+++ clang/include/clang/Tooling/Syntax/Tree.h
@@ -163,8 +163,11 @@
/// Prepend \p Child to the list of children and and sets the parent pointer.
/// A very low-level operation that does not check any invariants, only used
/// by TreeBuilder and FactoryImpl.
- /// EXPECTS: Role != NodeRoleDetached.
+ /// EXPECTS: Role != Detached.
void prependChildLowLevel(Node *Child, NodeRole Role);
+ /// Like the previous overload, but does not set role for \p Child.
+ /// EXPECTS: Child->Role != Detached
+ void prependChildLowLevel(Node *Child);
friend class TreeBuilder;
friend class FactoryImpl;
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits