2,725 changes: 3 additions & 2,722 deletions clang/include/clang/AST/DataRecursiveASTVisitor.h

Large diffs are not rendered by default.

287 changes: 118 additions & 169 deletions clang/include/clang/AST/RecursiveASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ namespace clang {
/// instantiations will be visited at the same time as the pattern
/// from which they were produced.
template <typename Derived> class RecursiveASTVisitor {
/// A queue used for performing data recursion over statements.
/// Parameters involving this type are used to implement data
/// recursion over Stmts and Exprs within this class, and should
/// not be explicitly specified by derived classes.
typedef SmallVectorImpl<Stmt *> DataRecursionQueue;

public:
/// \brief Return a reference to the derived class.
Derived &getDerived() { return *static_cast<Derived *>(this); }
Expand All @@ -148,19 +154,12 @@ template <typename Derived> class RecursiveASTVisitor {
/// code, e.g., implicit constructors and destructors.
bool shouldVisitImplicitCode() const { return false; }

/// \brief Return whether \param S should be traversed using data recursion
/// to avoid a stack overflow with extreme cases.
bool shouldUseDataRecursionFor(Stmt *S) const {
return isa<BinaryOperator>(S) || isa<UnaryOperator>(S) ||
isa<CaseStmt>(S) || isa<CXXOperatorCallExpr>(S);
}

/// \brief Recursively visit a statement or expression, by
/// dispatching to Traverse*() based on the argument's dynamic type.
///
/// \returns false if the visitation was terminated early, true
/// otherwise (including when the argument is NULL).
bool TraverseStmt(Stmt *S);
/// otherwise (including when the argument is nullptr).
bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue = nullptr);

/// \brief Recursively visit a type, by dispatching to
/// Traverse*Type() based on the argument's getTypeClass() property.
Expand Down Expand Up @@ -253,13 +252,14 @@ template <typename Derived> class RecursiveASTVisitor {
/// \c LE->getBody().
///
/// \returns false if the visitation was terminated early, true otherwise.
bool TraverseLambdaBody(LambdaExpr *LE);
bool TraverseLambdaBody(LambdaExpr *LE, DataRecursionQueue *Queue = nullptr);

/// \brief Recursively visit the syntactic or semantic form of an
/// initialization list.
///
/// \returns false if the visitation was terminated early, true otherwise.
bool TraverseSynOrSemInitListExpr(InitListExpr *S);
bool TraverseSynOrSemInitListExpr(InitListExpr *S,
DataRecursionQueue *Queue = nullptr);

// ---- Methods on Attrs ----

Expand All @@ -273,9 +273,36 @@ template <typename Derived> class RecursiveASTVisitor {

// ---- Methods on Stmts ----

private:
template<typename T, T X, typename U, U Y>
struct is_same_member_pointer : std::false_type {};
template<typename T, T X>
struct is_same_member_pointer<T, X, T, X> : std::true_type {};

// Traverse the given statement. If the traverse function was not overridden,
// pass on the data recursion queue information.
#define TRAVERSE_STMT_BASE(NAME, CLASS, VAR, QUEUE) \
(is_same_member_pointer<decltype(&Derived::Traverse##NAME), \
&Derived::Traverse##NAME, \
decltype(&RecursiveASTVisitor::Traverse##NAME), \
&RecursiveASTVisitor::Traverse##NAME>::value \
? this->Traverse##NAME(static_cast<CLASS *>(VAR), QUEUE) \
: getDerived().Traverse##NAME(static_cast<CLASS *>(VAR)))

// Try to traverse the given statement, or enqueue it if we're performing data
// recursion in the middle of traversing another statement. Can only be called
// from within a DEF_TRAVERSE_STMT body or similar context.
#define TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S) \
do { \
if (!TRAVERSE_STMT_BASE(Stmt, Stmt, S, Queue)) \
return false; \
} while (0)

public:
// Declare Traverse*() for all concrete Stmt classes.
#define ABSTRACT_STMT(STMT)
#define STMT(CLASS, PARENT) bool Traverse##CLASS(CLASS *S);
#define STMT(CLASS, PARENT) \
bool Traverse##CLASS(CLASS *S, DataRecursionQueue *Queue = nullptr);
#include "clang/AST/StmtNodes.inc"
// The above header #undefs ABSTRACT_STMT and STMT upon exit.

Expand All @@ -295,9 +322,10 @@ template <typename Derived> class RecursiveASTVisitor {
// operator methods. Unary operators are not classes in themselves
// (they're all opcodes in UnaryOperator) but do have visitors.
#define OPERATOR(NAME) \
bool TraverseUnary##NAME(UnaryOperator *S) { \
bool TraverseUnary##NAME(UnaryOperator *S, \
DataRecursionQueue *Queue = nullptr) { \
TRY_TO(WalkUpFromUnary##NAME(S)); \
TRY_TO(TraverseStmt(S->getSubExpr())); \
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getSubExpr()); \
return true; \
} \
bool WalkUpFromUnary##NAME(UnaryOperator *S) { \
Expand All @@ -314,10 +342,10 @@ template <typename Derived> class RecursiveASTVisitor {
// operator methods. Binary operators are not classes in themselves
// (they're all opcodes in BinaryOperator) but do have visitors.
#define GENERAL_BINOP_FALLBACK(NAME, BINOP_TYPE) \
bool TraverseBin##NAME(BINOP_TYPE *S) { \
bool TraverseBin##NAME(BINOP_TYPE *S, DataRecursionQueue *Queue = nullptr) { \
TRY_TO(WalkUpFromBin##NAME(S)); \
TRY_TO(TraverseStmt(S->getLHS())); \
TRY_TO(TraverseStmt(S->getRHS())); \
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getLHS()); \
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getRHS()); \
return true; \
} \
bool WalkUpFromBin##NAME(BINOP_TYPE *S) { \
Expand Down Expand Up @@ -443,129 +471,32 @@ template <typename Derived> class RecursiveASTVisitor {
/// \brief Process clauses with list of variables.
template <typename T> bool VisitOMPClauseList(T *Node);

struct EnqueueJob {
Stmt *S;
Stmt::child_iterator StmtIt;

EnqueueJob(Stmt *S) : S(S), StmtIt() {}
};
bool dataTraverse(Stmt *S);
bool dataTraverseNode(Stmt *S, bool &EnqueueChildren);
bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue);
};

template <typename Derived>
bool RecursiveASTVisitor<Derived>::dataTraverse(Stmt *S) {

SmallVector<EnqueueJob, 16> Queue;
SmallVector<Stmt*, 16> Queue;
Queue.push_back(S);

while (!Queue.empty()) {
EnqueueJob &job = Queue.back();
Stmt *CurrS = job.S;
if (!CurrS) {
Queue.pop_back();
continue;
}

if (getDerived().shouldUseDataRecursionFor(CurrS)) {
if (job.StmtIt == Stmt::child_iterator()) {
bool EnqueueChildren = true;
if (!dataTraverseNode(CurrS, EnqueueChildren))
return false;
if (!EnqueueChildren) {
Queue.pop_back();
continue;
}
job.StmtIt = CurrS->child_begin();
} else {
++job.StmtIt;
}
Stmt *CurrS = Queue.pop_back_val();

if (job.StmtIt != CurrS->child_end())
Queue.push_back(*job.StmtIt);
else
Queue.pop_back();
continue;
}

Queue.pop_back();
TRY_TO(TraverseStmt(CurrS));
size_t N = Queue.size();
TRY_TO(dataTraverseNode(CurrS, &Queue));
// Process new children in the order they were added.
std::reverse(Queue.begin() + N, Queue.end());
}

return true;
}

template <typename Derived>
bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S,
bool &EnqueueChildren) {

// Dispatch to the corresponding WalkUpFrom* function only if the derived
// class didn't override Traverse* (and thus the traversal is trivial).
#define DISPATCH_WALK(NAME, CLASS, VAR) \
{ \
bool (Derived::*DerivedFn)(CLASS *) = &Derived::Traverse##NAME; \
bool (Derived::*BaseFn)(CLASS *) = &RecursiveASTVisitor::Traverse##NAME; \
if (DerivedFn == BaseFn) \
return getDerived().WalkUpFrom##NAME(static_cast<CLASS *>(VAR)); \
} \
EnqueueChildren = false; \
return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR));

if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
switch (BinOp->getOpcode()) {
#define OPERATOR(NAME) \
case BO_##NAME: \
DISPATCH_WALK(Bin##NAME, BinaryOperator, S);

BINOP_LIST()
#undef OPERATOR

#define OPERATOR(NAME) \
case BO_##NAME##Assign: \
DISPATCH_WALK(Bin##NAME##Assign, CompoundAssignOperator, S);

CAO_LIST()
#undef OPERATOR
}
} else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) {
switch (UnOp->getOpcode()) {
#define OPERATOR(NAME) \
case UO_##NAME: \
DISPATCH_WALK(Unary##NAME, UnaryOperator, S);

UNARYOP_LIST()
#undef OPERATOR
}
}

// Top switch stmt: dispatch to TraverseFooStmt for each concrete FooStmt.
switch (S->getStmtClass()) {
case Stmt::NoStmtClass:
break;
#define ABSTRACT_STMT(STMT)
#define STMT(CLASS, PARENT) \
case Stmt::CLASS##Class: \
DISPATCH_WALK(CLASS, CLASS, S);
#include "clang/AST/StmtNodes.inc"
}

#undef DISPATCH_WALK

return true;
}

#define DISPATCH(NAME, CLASS, VAR) \
return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR))

template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {
if (!S)
return true;

#define DISPATCH_STMT(NAME, CLASS, VAR) DISPATCH(NAME, CLASS, VAR)

if (getDerived().shouldUseDataRecursionFor(S))
return dataTraverse(S);
DataRecursionQueue *Queue) {
#define DISPATCH_STMT(NAME, CLASS, VAR) \
return TRAVERSE_STMT_BASE(NAME, CLASS, VAR, Queue);

// If we have a binary expr, dispatch to the subcode of the binop. A smart
// optimizer (e.g. LLVM) will fold this comparison into the switch stmt
Expand Down Expand Up @@ -616,6 +547,30 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {

#undef DISPATCH_STMT

template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S,
DataRecursionQueue *Queue) {
if (!S)
return true;

// If TraverseStmt was overridden (and called the base class version), don't
// do any data recursion; it would be observable.
if (!is_same_member_pointer<decltype(&Derived::TraverseStmt),
&Derived::TraverseStmt,
decltype(&RecursiveASTVisitor::TraverseStmt),
&RecursiveASTVisitor::TraverseStmt>::value)
return dataTraverseNode(S, nullptr);

if (!Queue)
return dataTraverse(S);

Queue->push_back(S);
return true;
}

#define DISPATCH(NAME, CLASS, VAR) \
return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR))

template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) {
if (T.isNull())
Expand Down Expand Up @@ -870,8 +825,9 @@ RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE,
}

template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseLambdaBody(LambdaExpr *LE) {
TRY_TO(TraverseStmt(LE->getBody()));
bool RecursiveASTVisitor<Derived>::TraverseLambdaBody(
LambdaExpr *LE, DataRecursionQueue *Queue) {
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(LE->getBody());
return true;
}

Expand Down Expand Up @@ -1917,25 +1873,26 @@ DEF_TRAVERSE_DECL(ParmVarDecl, {
// This macro makes available a variable S, the passed-in stmt.
#define DEF_TRAVERSE_STMT(STMT, CODE) \
template <typename Derived> \
bool RecursiveASTVisitor<Derived>::Traverse##STMT(STMT *S) { \
bool RecursiveASTVisitor<Derived>::Traverse##STMT( \
STMT *S, DataRecursionQueue *Queue) { \
TRY_TO(WalkUpFrom##STMT(S)); \
{ CODE; } \
for (Stmt *SubStmt : S->children()) { \
TRY_TO(TraverseStmt(SubStmt)); \
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(SubStmt); \
} \
return true; \
}

DEF_TRAVERSE_STMT(GCCAsmStmt, {
TRY_TO(TraverseStmt(S->getAsmString()));
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAsmString());
for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) {
TRY_TO(TraverseStmt(S->getInputConstraintLiteral(I)));
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getInputConstraintLiteral(I));
}
for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) {
TRY_TO(TraverseStmt(S->getOutputConstraintLiteral(I)));
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOutputConstraintLiteral(I));
}
for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) {
TRY_TO(TraverseStmt(S->getClobberStringLiteral(I)));
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getClobberStringLiteral(I));
}
// children() iterates over inputExpr and outputExpr.
})
Expand Down Expand Up @@ -1988,9 +1945,9 @@ DEF_TRAVERSE_STMT(ObjCForCollectionStmt, {})
DEF_TRAVERSE_STMT(ObjCAutoreleasePoolStmt, {})
DEF_TRAVERSE_STMT(CXXForRangeStmt, {
if (!getDerived().shouldVisitImplicitCode()) {
TRY_TO(TraverseStmt(S->getLoopVarStmt()));
TRY_TO(TraverseStmt(S->getRangeInit()));
TRY_TO(TraverseStmt(S->getBody()));
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getLoopVarStmt());
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getRangeInit());
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getBody());
// Visit everything else only if shouldVisitImplicitCode().
return true;
}
Expand Down Expand Up @@ -2067,12 +2024,13 @@ DEF_TRAVERSE_STMT(CXXStaticCastExpr, {
})

template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseSynOrSemInitListExpr(InitListExpr *S) {
bool RecursiveASTVisitor<Derived>::TraverseSynOrSemInitListExpr(
InitListExpr *S, DataRecursionQueue *Queue) {
if (S) {
TRY_TO(WalkUpFromInitListExpr(S));
// All we need are the default actions. FIXME: use a helper function.
for (Stmt *SubStmt : S->children()) {
TRY_TO(TraverseStmt(SubStmt));
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(SubStmt);
}
}
return true;
Expand All @@ -2084,48 +2042,41 @@ bool RecursiveASTVisitor<Derived>::TraverseSynOrSemInitListExpr(InitListExpr *S)
// the syntactic and the semantic form.
//
// There is no guarantee about which form \p S takes when this method is called.
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) {
DEF_TRAVERSE_STMT(InitListExpr, {
TRY_TO(TraverseSynOrSemInitListExpr(
S->isSemanticForm() ? S->getSyntacticForm() : S));
S->isSemanticForm() ? S->getSyntacticForm() : S, Queue));
TRY_TO(TraverseSynOrSemInitListExpr(
S->isSemanticForm() ? S : S->getSemanticForm()));
S->isSemanticForm() ? S : S->getSemanticForm(), Queue));
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).
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseGenericSelectionExpr(
GenericSelectionExpr *S) {
TRY_TO(WalkUpFromGenericSelectionExpr(S));
DEF_TRAVERSE_STMT(GenericSelectionExpr, {
TRY_TO(TraverseStmt(S->getControllingExpr()));
for (unsigned i = 0; i != S->getNumAssocs(); ++i) {
if (TypeSourceInfo *TS = S->getAssocTypeSourceInfo(i))
TRY_TO(TraverseTypeLoc(TS->getTypeLoc()));
TRY_TO(TraverseStmt(S->getAssocExpr(i)));
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAssocExpr(i));
}
return true;
}
})

// PseudoObjectExpr is a special case because of the wierdness with
// PseudoObjectExpr is a special case because of the weirdness with
// syntactic expressions and opaque values.
template <typename Derived>
bool
RecursiveASTVisitor<Derived>::TraversePseudoObjectExpr(PseudoObjectExpr *S) {
TRY_TO(WalkUpFromPseudoObjectExpr(S));
TRY_TO(TraverseStmt(S->getSyntacticForm()));
DEF_TRAVERSE_STMT(PseudoObjectExpr, {
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getSyntacticForm());
for (PseudoObjectExpr::semantics_iterator i = S->semantics_begin(),
e = S->semantics_end();
i != e; ++i) {
Expr *sub = *i;
if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(sub))
sub = OVE->getSourceExpr();
TRY_TO(TraverseStmt(sub));
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(sub);
}
return true;
}
})

DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, {
// This is called for code like 'return T()' where T is a built-in
Expand Down Expand Up @@ -2181,7 +2132,7 @@ DEF_TRAVERSE_STMT(ArrayTypeTraitExpr, {
})

DEF_TRAVERSE_STMT(ExpressionTraitExpr,
{ TRY_TO(TraverseStmt(S->getQueriedExpression())); })
{ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getQueriedExpression()); })

DEF_TRAVERSE_STMT(VAArgExpr, {
// The child-iterator will pick up the expression argument.
Expand All @@ -2194,10 +2145,7 @@ DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, {
})

// Walk only the visible parts of lambda expressions.
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) {
TRY_TO(WalkUpFromLambdaExpr(S));

DEF_TRAVERSE_STMT(LambdaExpr, {
for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(),
CEnd = S->explicit_capture_end();
C != CEnd; ++C) {
Expand Down Expand Up @@ -2226,12 +2174,11 @@ bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) {
}

if (Expr *NE = T->getNoexceptExpr())
TRY_TO(TraverseStmt(NE));
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(NE);
}

TRY_TO(TraverseLambdaBody(S));
return true;
}
return TRAVERSE_STMT_BASE(LambdaBody, LambdaExpr, S, Queue);
})

DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, {
// This is called for code like 'T()', where T is a template argument.
Expand Down Expand Up @@ -2355,25 +2302,25 @@ DEF_TRAVERSE_STMT(AtomicExpr, {})
// derived class requests.
DEF_TRAVERSE_STMT(CoroutineBodyStmt, {
if (!getDerived().shouldVisitImplicitCode()) {
TRY_TO(TraverseStmt(S->getBody()));
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getBody());
return true;
}
})
DEF_TRAVERSE_STMT(CoreturnStmt, {
if (!getDerived().shouldVisitImplicitCode()) {
TRY_TO(TraverseStmt(S->getOperand()));
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand());
return true;
}
})
DEF_TRAVERSE_STMT(CoawaitExpr, {
if (!getDerived().shouldVisitImplicitCode()) {
TRY_TO(TraverseStmt(S->getOperand()));
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand());
return true;
}
})
DEF_TRAVERSE_STMT(CoyieldExpr, {
if (!getDerived().shouldVisitImplicitCode()) {
TRY_TO(TraverseStmt(S->getOperand()));
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand());
return true;
}
})
Expand Down Expand Up @@ -2793,6 +2740,8 @@ bool RecursiveASTVisitor<Derived>::VisitOMPMapClause(OMPMapClause *C) {
// Every class that has getQualifier.

#undef DEF_TRAVERSE_STMT
#undef TRAVERSE_STMT
#undef TRAVERSE_STMT_BASE

#undef TRY_TO

Expand Down
31 changes: 16 additions & 15 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8729,7 +8729,6 @@ createDynTypedNode(const NestedNameSpecifierLoc &Node) {
///
/// FIXME: Currently only builds up the map using \c Stmt and \c Decl nodes.
class ParentMapASTVisitor : public RecursiveASTVisitor<ParentMapASTVisitor> {

public:
/// \brief Builds and returns the translation unit's parent map.
///
Expand All @@ -8756,15 +8755,11 @@ createDynTypedNode(const NestedNameSpecifierLoc &Node) {
bool shouldVisitImplicitCode() const {
return true;
}
// Disables data recursion. We intercept Traverse* methods in the RAV, which
// are not triggered during data recursion.
bool shouldUseDataRecursionFor(clang::Stmt *S) const {
return false;
}

template <typename T, typename MapNodeTy, typename MapTy>
template <typename T, typename MapNodeTy, typename BaseTraverseFn,
typename MapTy>
bool TraverseNode(T Node, MapNodeTy MapNode,
bool (VisitorBase::*traverse)(T), MapTy *Parents) {
BaseTraverseFn BaseTraverse, MapTy *Parents) {
if (!Node)
return true;
if (ParentStack.size() > 0) {
Expand Down Expand Up @@ -8812,31 +8807,37 @@ createDynTypedNode(const NestedNameSpecifierLoc &Node) {
}
}
ParentStack.push_back(createDynTypedNode(Node));
bool Result = (this ->* traverse) (Node);
bool Result = BaseTraverse();
ParentStack.pop_back();
return Result;
}

bool TraverseDecl(Decl *DeclNode) {
return TraverseNode(DeclNode, DeclNode, &VisitorBase::TraverseDecl,
return TraverseNode(DeclNode, DeclNode,
[&] { return VisitorBase::TraverseDecl(DeclNode); },
Parents);
}

bool TraverseStmt(Stmt *StmtNode) {
return TraverseNode(StmtNode, StmtNode, &VisitorBase::TraverseStmt,
return TraverseNode(StmtNode, StmtNode,
[&] { return VisitorBase::TraverseStmt(StmtNode); },
Parents);
}

bool TraverseTypeLoc(TypeLoc TypeLocNode) {
return TraverseNode(TypeLocNode,
ast_type_traits::DynTypedNode::create(TypeLocNode),
&VisitorBase::TraverseTypeLoc, OtherParents);
return TraverseNode(
TypeLocNode, ast_type_traits::DynTypedNode::create(TypeLocNode),
[&] { return VisitorBase::TraverseTypeLoc(TypeLocNode); },
OtherParents);
}

bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLocNode) {
return TraverseNode(
NNSLocNode, ast_type_traits::DynTypedNode::create(NNSLocNode),
&VisitorBase::TraverseNestedNameSpecifierLoc, OtherParents);
[&] {
return VisitorBase::TraverseNestedNameSpecifierLoc(NNSLocNode);
},
OtherParents);
}

ASTContext::ParentMapPointers *Parents;
Expand Down
6 changes: 0 additions & 6 deletions clang/lib/ASTMatchers/ASTMatchFinder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,6 @@ class MatchChildASTVisitor

bool shouldVisitTemplateInstantiations() const { return true; }
bool shouldVisitImplicitCode() const { return true; }
// Disables data recursion. We intercept Traverse* methods in the RAV, which
// are not triggered during data recursion.
bool shouldUseDataRecursionFor(clang::Stmt *S) const { return false; }

private:
// Used for updating the depth during traversal.
Expand Down Expand Up @@ -487,9 +484,6 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,

bool shouldVisitTemplateInstantiations() const { return true; }
bool shouldVisitImplicitCode() const { return true; }
// Disables data recursion. We intercept Traverse* methods in the RAV, which
// are not triggered during data recursion.
bool shouldUseDataRecursionFor(clang::Stmt *S) const { return false; }

private:
class TimeBucketRegion {
Expand Down