summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h8
-rw-r--r--unittests/ASTMatchers/ASTMatchersTest.cpp6
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTest.cpp25
-rw-r--r--unittests/Tooling/TestVisitor.h6
4 files changed, 43 insertions, 2 deletions
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index ac7795f933..acba46dcd7 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -1776,6 +1776,14 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
// including exception specifications.
if (TypeSourceInfo *TSI = D->getTypeSourceInfo()) {
TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
+ } else if (getDerived().shouldVisitImplicitCode()) {
+ // Visit parameter variable declarations of the implicit function
+ // if the traverser is visiting implicit code. Parameter variable
+ // declarations do not have valid TypeSourceInfo, so to visit them
+ // we need to traverse the declarations explicitly.
+ for (FunctionDecl::param_const_iterator I = D->param_begin(),
+ E = D->param_end(); I != E; ++I)
+ TRY_TO(TraverseDecl(*I));
}
if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
diff --git a/unittests/ASTMatchers/ASTMatchersTest.cpp b/unittests/ASTMatchers/ASTMatchersTest.cpp
index 4994192bda..556b0b896e 100644
--- a/unittests/ASTMatchers/ASTMatchersTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersTest.cpp
@@ -1361,8 +1361,12 @@ TEST(Matcher, References) {
ReferenceClassX));
EXPECT_TRUE(
matches("class X {}; void y(X y) { const X &x = y; }", ReferenceClassX));
+ // The match here is on the implicit copy constructor code for
+ // class X, not on code 'X x = y'.
EXPECT_TRUE(
- notMatches("class X {}; void y(X y) { X x = y; }", ReferenceClassX));
+ matches("class X {}; void y(X y) { X x = y; }", ReferenceClassX));
+ EXPECT_TRUE(
+ notMatches("class X {}; extern X x;", ReferenceClassX));
EXPECT_TRUE(
notMatches("class X {}; void y(X *y) { X *&x = y; }", ReferenceClassX));
}
diff --git a/unittests/Tooling/RecursiveASTVisitorTest.cpp b/unittests/Tooling/RecursiveASTVisitorTest.cpp
index b1d6f4a37c..b3a8915a59 100644
--- a/unittests/Tooling/RecursiveASTVisitorTest.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTest.cpp
@@ -37,6 +37,17 @@ public:
}
};
+class ParmVarDeclVisitorForImplicitCode :
+ public ExpectedLocationVisitor<ParmVarDeclVisitorForImplicitCode> {
+public:
+ bool shouldVisitImplicitCode() const { return true; }
+
+ bool VisitParmVarDecl(ParmVarDecl *ParamVar) {
+ Match(ParamVar->getNameAsString(), ParamVar->getLocStart());
+ return true;
+ }
+};
+
class CXXMemberCallVisitor
: public ExpectedLocationVisitor<CXXMemberCallVisitor> {
public:
@@ -144,6 +155,20 @@ public:
}
};
+// Test RAV visits parameter variable declaration of the implicit
+// copy assignment operator.
+TEST(RecursiveASTVisitor, VisitsParmVarDeclForImplicitCode) {
+ ParmVarDeclVisitorForImplicitCode Visitor;
+ // Match parameter variable name of implicit copy assignment operator.
+ // This parameter name does not have a valid IdentifierInfo, and shares
+ // same SourceLocation with its class declaration, so we match an empty name
+ // with the class' source location.
+ Visitor.ExpectMatch("", 1, 7);
+ EXPECT_TRUE(Visitor.runOver(
+ "class X {};\n"
+ "void foo(X a, X b) {a = b;}"));
+}
+
TEST(RecursiveASTVisitor, VisitsBaseClassDeclarations) {
TypeLocVisitor Visitor;
Visitor.ExpectMatch("class X", 1, 30);
diff --git a/unittests/Tooling/TestVisitor.h b/unittests/Tooling/TestVisitor.h
index 5ee118ebdc..ec751c350e 100644
--- a/unittests/Tooling/TestVisitor.h
+++ b/unittests/Tooling/TestVisitor.h
@@ -31,7 +31,7 @@ namespace clang {
/// This is a drop-in replacement for RecursiveASTVisitor itself, with the
/// additional capability of running it over a snippet of code.
///
-/// Visits template instantiations (but not implicit code) by default.
+/// Visits template instantiations and implicit code by default.
template <typename T>
class TestVisitor : public RecursiveASTVisitor<T> {
public:
@@ -56,6 +56,10 @@ public:
return true;
}
+ bool shouldVisitImplicitCode() const {
+ return true;
+ }
+
protected:
virtual ASTFrontendAction* CreateTestAction() {
return new TestAction(this);