summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlp Toker <alp@nuanti.com>2014-06-26 01:42:24 +0000
committerAlp Toker <alp@nuanti.com>2014-06-26 01:42:24 +0000
commit2a38ab6aeaab8fbe3c4c74ea3ed389ca5bd04c07 (patch)
tree7014c0da5afbda5a5a94415e42577e14c63f7f5e
parent5937825128564ab750d20467a91d6776afe8cc73 (diff)
downloadclang-2a38ab6aeaab8fbe3c4c74ea3ed389ca5bd04c07.tar.gz
clang-2a38ab6aeaab8fbe3c4c74ea3ed389ca5bd04c07.tar.bz2
clang-2a38ab6aeaab8fbe3c4c74ea3ed389ca5bd04c07.tar.xz
RAV: visit copy expressions of captured variables in blocks (ObjC++11)
Patch by Mathieu Baudet. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@211758 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/DataRecursiveASTVisitor.h5
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h5
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTest.cpp10
-rw-r--r--unittests/Tooling/TestVisitor.h13
4 files changed, 32 insertions, 1 deletions
diff --git a/include/clang/AST/DataRecursiveASTVisitor.h b/include/clang/AST/DataRecursiveASTVisitor.h
index 93a9d1d0d2..23c9ce554f 100644
--- a/include/clang/AST/DataRecursiveASTVisitor.h
+++ b/include/clang/AST/DataRecursiveASTVisitor.h
@@ -1207,6 +1207,11 @@ DEF_TRAVERSE_DECL(BlockDecl, {
if (TypeSourceInfo *TInfo = D->getSignatureAsWritten())
TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
TRY_TO(TraverseStmt(D->getBody()));
+ for (const auto &I : D->captures()) {
+ if (I.hasCopyExpr()) {
+ TRY_TO(TraverseStmt(I.getCopyExpr()));
+ }
+ }
// This return statement makes sure the traversal of nodes in
// decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro)
// is skipped - don't remove it.
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index c9de9e318f..2877642be5 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -1272,6 +1272,11 @@ DEF_TRAVERSE_DECL(BlockDecl, {
if (TypeSourceInfo *TInfo = D->getSignatureAsWritten())
TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
TRY_TO(TraverseStmt(D->getBody()));
+ for (const auto &I : D->captures()) {
+ if (I.hasCopyExpr()) {
+ TRY_TO(TraverseStmt(I.getCopyExpr()));
+ }
+ }
// This return statement makes sure the traversal of nodes in
// decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro)
// is skipped - don't remove it.
diff --git a/unittests/Tooling/RecursiveASTVisitorTest.cpp b/unittests/Tooling/RecursiveASTVisitorTest.cpp
index 6be734e6d4..a1a93a59c7 100644
--- a/unittests/Tooling/RecursiveASTVisitorTest.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTest.cpp
@@ -561,6 +561,16 @@ TEST(RecursiveASTVisitor, HasCaptureDefaultLoc) {
LambdaDefaultCaptureVisitor::Lang_CXX11));
}
+TEST(RecursiveASTVisitor, VisitsCopyExprOfBlockDeclCapture) {
+ DeclRefExprVisitor Visitor;
+ Visitor.ExpectMatch("x", 3, 24);
+ EXPECT_TRUE(Visitor.runOver("void f(int(^)(int)); \n"
+ "void g() { \n"
+ " f([&](int x){ return x; }); \n"
+ "}",
+ DeclRefExprVisitor::Lang_OBJCXX11));
+}
+
// Checks for lambda classes that are not marked as implicitly-generated.
// (There should be none.)
class ClassVisitor : public ExpectedLocationVisitor<ClassVisitor> {
diff --git a/unittests/Tooling/TestVisitor.h b/unittests/Tooling/TestVisitor.h
index 2e64032cf4..ae02fb5ebb 100644
--- a/unittests/Tooling/TestVisitor.h
+++ b/unittests/Tooling/TestVisitor.h
@@ -39,7 +39,14 @@ public:
virtual ~TestVisitor() { }
- enum Language { Lang_C, Lang_CXX98, Lang_CXX11, Lang_OBJC, Lang_CXX=Lang_CXX98 };
+ enum Language {
+ Lang_C,
+ Lang_CXX98,
+ Lang_CXX11,
+ Lang_OBJC,
+ Lang_OBJCXX11,
+ Lang_CXX = Lang_CXX98
+ };
/// \brief Runs the current AST visitor over the given code.
bool runOver(StringRef Code, Language L = Lang_CXX) {
@@ -49,6 +56,10 @@ public:
case Lang_CXX98: Args.push_back("-std=c++98"); break;
case Lang_CXX11: Args.push_back("-std=c++11"); break;
case Lang_OBJC: Args.push_back("-ObjC"); break;
+ case Lang_OBJCXX11:
+ Args.push_back("-ObjC++");
+ Args.push_back("-std=c++11");
+ break;
}
return tooling::runToolOnCodeWithArgs(CreateTestAction(), Code, Args);
}