Index: include/clang/AST/RecursiveASTVisitor.h =================================================================== --- include/clang/AST/RecursiveASTVisitor.h +++ include/clang/AST/RecursiveASTVisitor.h @@ -255,6 +255,13 @@ /// \returns false if the visitation was terminated early, true otherwise. bool TraverseLambdaBody(LambdaExpr *LE); + /// \brief Recursively visit the syntactic and semantic forms of a + /// initialization list. + /// + /// \returns false if the visitation was terminated early, true otherwise. + bool TraverseSyntacticInitListExpr(InitListExpr *S); + bool TraverseSemanticInitListExpr(InitListExpr *S); + // ---- Methods on Attrs ---- // \brief Visit an attribute. @@ -2056,13 +2063,8 @@ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); }) -// InitListExpr is a tricky one, because we want to do all our work on -// the syntactic form of the listexpr, but this method takes the -// semantic form by default. We can't use the macro helper because it -// calls WalkUp*() on the semantic form, before our code can convert -// to the syntactic form. template -bool RecursiveASTVisitor::TraverseInitListExpr(InitListExpr *S) { +bool RecursiveASTVisitor::TraverseSyntacticInitListExpr(InitListExpr *S) { InitListExpr *Syn = S->isSemanticForm() ? S->getSyntacticForm() : S; if (Syn) { TRY_TO(WalkUpFromInitListExpr(Syn)); @@ -2071,6 +2073,11 @@ TRY_TO(TraverseStmt(SubStmt)); } } + return true; +} + +template +bool RecursiveASTVisitor::TraverseSemanticInitListExpr(InitListExpr *S) { InitListExpr *Sem = S->isSemanticForm() ? S : S->getSemanticForm(); if (Sem) { TRY_TO(WalkUpFromInitListExpr(Sem)); @@ -2081,6 +2088,25 @@ return true; } +// InitListExpr is a tricky one, because we want to do all our work on +// the syntactic form of the listexpr, but this method takes the +// semantic form by default. We can't use the macro helper because it +// calls WalkUp*() on the semantic form, before our code can convert +// to the syntactic form. +// +// This method is called once for each pair of syntactic and semantic +// InitListExpr, and it traverses the subtrees defined by the two forms. This +// may cause some of the children to be visited twice, if they appear both in +// the syntactic and the semantic form. +// +// There is no guarantee about which form \p S takes when this method is called. +template +bool RecursiveASTVisitor::TraverseInitListExpr(InitListExpr *S) { + TRY_TO(TraverseSyntacticInitListExpr(S)); + TRY_TO(TraverseSemanticInitListExpr(S)); + return true; +} + // GenericSelectionExpr is a special case because the types and expressions // are interleaved. We also need to watch out for null types (default // generic associations).