diff --git a/clang/include/clang/Tooling/Syntax/Tree.h b/clang/include/clang/Tooling/Syntax/Tree.h --- a/clang/include/clang/Tooling/Syntax/Tree.h +++ b/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; diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/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 #include 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; +/// 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 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 Range, syntax::Tree *New); + void foldNode(llvm::ArrayRef Range, syntax::Tree *New, + ASTPtr From) { + assert(New); + Pending.foldChildren(Arena, Range, New); + if (From) + Mapping.add(From, New); + } + void foldNode(llvm::ArrayRef 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 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 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(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 @@ -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.Node->role() == NodeRole::Detached && + "re-assigning role for a child"); + It->second.Node->Role = static_cast(Role); } /// Add \p Node to the forest and attach child nodes based on \p Tokens. @@ -419,9 +469,12 @@ "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.Node; + if (N->role() == NodeRole::Detached) + N->Role = static_cast(NodeRole::Unknown); + Node->prependChildLowLevel(N); + } // Mark that this node came from the AST and is backed by the source code. Node->Original = true; @@ -432,11 +485,9 @@ } /// 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) {} + explicit NodeAndRole(syntax::Node *Node) : Node(Node) {} syntax::Node *Node; - NodeRole Role; }; /// Maps from the start token to a subtree starting at that token. @@ -464,6 +515,7 @@ LocationToToken; Forest Pending; llvm::DenseSet DeclsWithoutSemicolons; + ASTToSyntaxMapping Mapping; }; namespace { @@ -490,10 +542,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 +559,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 +569,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 +582,11 @@ return false; if (C->isExplicitSpecialization()) return true; // we are only interested in explicit instantiations. - if (!WalkUpFromClassTemplateSpecializationDecl(C)) - return false; + auto *Declaration = + cast(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 +594,7 @@ foldTemplateDeclaration( Builder.getDeclRange(S), Builder.findToken(S->getTemplateParameters()->getTemplateLoc()), - Builder.getDeclRange(S->getTemplatedDecl())); + Builder.getDeclRange(S->getTemplatedDecl()), S); return true; } @@ -552,24 +604,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(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 +645,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 +690,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 +702,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 +717,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 +728,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 +740,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 +758,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 +767,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 +782,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 +792,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 +801,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 +814,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 +822,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 +831,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 +839,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 +847,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 +857,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 +865,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 +881,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 BuildTrailingReturn(FunctionProtoTypeLoc L) { + syntax::TrailingReturnType *BuildTrailingReturn(FunctionProtoTypeLoc L) { assert(L.getTypePtr()->hasTrailingReturn()); auto ReturnedType = L.getReturnLoc(); @@ -880,12 +939,12 @@ getDeclaratorRange(this->Builder.sourceManager(), ReturnedType, /*Name=*/SourceLocation(), /*Initializer=*/SourceLocation()); - llvm::ArrayRef 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 +954,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 Range, - const syntax::Token *ExternKW, - const syntax::Token *TemplateKW, - ArrayRef InnerDeclaration) { + void foldExplicitTemplateInstantiation( + ArrayRef 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 +976,22 @@ InnerDeclaration, syntax::NodeRole::ExplicitTemplateInstantiation_declaration); Builder.foldNode(Range, - new (allocator()) syntax::ExplicitTemplateInstantiation); + new (allocator()) syntax::ExplicitTemplateInstantiation, + nullptr); } - void foldTemplateDeclaration(ArrayRef Range, - const syntax::Token *TemplateKW, - ArrayRef TemplatedDeclaration) { + syntax::TemplateDeclaration *foldTemplateDeclaration( + ArrayRef Range, const syntax::Token *TemplateKW, + ArrayRef 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 +1002,6 @@ }; } // namespace -void syntax::TreeBuilder::foldNode(llvm::ArrayRef Range, - syntax::Tree *New) { - Pending.foldChildren(Arena, Range, New); -} - void syntax::TreeBuilder::noticeDeclRange(llvm::ArrayRef Range) { if (Pending.extendDelayedFold(Range)) return; @@ -967,9 +1025,15 @@ Pending.assignRole(*T, R); } -void syntax::TreeBuilder::markChild(llvm::ArrayRef 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 Range, @@ -986,24 +1050,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(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 { diff --git a/clang/lib/Tooling/Syntax/Tree.cpp b/clang/lib/Tooling/Syntax/Tree.cpp --- a/clang/lib/Tooling/Syntax/Tree.cpp +++ b/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(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(Role); this->FirstChild = Child; }