summaryrefslogtreecommitdiffstats
path: root/include/clang
diff options
context:
space:
mode:
authorSam McCall <sam.mccall@gmail.com>2019-01-14 10:31:42 +0000
committerSam McCall <sam.mccall@gmail.com>2019-01-14 10:31:42 +0000
commit765aed95548bbd215d97f8418f43815823e79905 (patch)
tree74df789599c43aa40aea18afd5650f5ae4ecc53d /include/clang
parente593a791f2cf19db84237b0b9d632e9966a00a39 (diff)
[AST] RecursiveASTVisitor visits lambda classes when implicit visitation is on.
Summary: This fixes ASTContext's parent map for nodes in such classes (e.g. operator()). https://bugs.llvm.org/show_bug.cgi?id=39949 This also changes the observed shape of the AST for implicit RAVs. - this includes AST MatchFinder: cxxRecordDecl() now matches lambda classes, functionDecl() matches the call operator, and the parent chain is body -> call operator -> lambda class -> lambdaexpr rather than body -> lambdaexpr. - this appears not to matter for the ASTImporterLookupTable builder - this doesn't matter for the other RAVs in-tree. In order to do this, we remove the TraverseLambdaBody hook. The problem is it's hard/weird to ensure this hook is called when traversing via the implicit class. There were just two users of this hook in-tree, who use it to skip bodies. I replaced these with explicitly traversing the captures only. Another approach would be recording the bodies when the lambda is visited, and then recognizing them later. I'd be open to suggestion on how to preserve this hook, instead. Reviewers: aaron.ballman, JonasToth Subscribers: cfe-commits, rsmith, jdennett Differential Revision: https://reviews.llvm.org/D56444 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@351047 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/clang')
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h52
1 files changed, 22 insertions, 30 deletions
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index 0d88517010..96f3d24c6d 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -298,14 +298,6 @@ public:
bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
Expr *Init);
- /// Recursively visit the body of a lambda expression.
- ///
- /// This provides a hook for visitors that need more context when visiting
- /// \c LE->getBody().
- ///
- /// \returns false if the visitation was terminated early, true otherwise.
- bool TraverseLambdaBody(LambdaExpr *LE, DataRecursionQueue *Queue = nullptr);
-
/// Recursively visit the syntactic or semantic form of an
/// initialization list.
///
@@ -936,13 +928,6 @@ RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE,
return true;
}
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseLambdaBody(
- LambdaExpr *LE, DataRecursionQueue *Queue) {
- TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(LE->getBody());
- return true;
-}
-
// ----------------- Type traversal -----------------
// This macro makes available a variable T, the passed-in type.
@@ -2404,6 +2389,7 @@ DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, {
// Walk only the visible parts of lambda expressions.
DEF_TRAVERSE_STMT(LambdaExpr, {
+ // Visit the capture list.
for (unsigned I = 0, N = S->capture_size(); I != N; ++I) {
const LambdaCapture *C = S->capture_begin() + I;
if (C->isExplicit() || getDerived().shouldVisitImplicitCode()) {
@@ -2411,25 +2397,31 @@ DEF_TRAVERSE_STMT(LambdaExpr, {
}
}
- TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
- FunctionProtoTypeLoc Proto = TL.getAsAdjusted<FunctionProtoTypeLoc>();
+ if (getDerived().shouldVisitImplicitCode()) {
+ // The implicit model is simple: everything else is in the lambda class.
+ TRY_TO(TraverseDecl(S->getLambdaClass()));
+ } else {
+ // We need to poke around to find the bits that might be explicitly written.
+ TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
+ FunctionProtoTypeLoc Proto = TL.getAsAdjusted<FunctionProtoTypeLoc>();
- if (S->hasExplicitParameters()) {
- // Visit parameters.
- for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I)
- TRY_TO(TraverseDecl(Proto.getParam(I)));
- }
- if (S->hasExplicitResultType())
- TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));
+ if (S->hasExplicitParameters()) {
+ // Visit parameters.
+ for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I)
+ TRY_TO(TraverseDecl(Proto.getParam(I)));
+ }
+ if (S->hasExplicitResultType())
+ TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));
- auto *T = Proto.getTypePtr();
- for (const auto &E : T->exceptions())
- TRY_TO(TraverseType(E));
+ auto *T = Proto.getTypePtr();
+ for (const auto &E : T->exceptions())
+ TRY_TO(TraverseType(E));
- if (Expr *NE = T->getNoexceptExpr())
- TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(NE);
+ if (Expr *NE = T->getNoexceptExpr())
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(NE);
- ReturnValue = TRAVERSE_STMT_BASE(LambdaBody, LambdaExpr, S, Queue);
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getBody());
+ }
ShouldVisitChildren = false;
})