r190528 - Teach RAV to visit parameter variable declarations of implicit functions. Fixes PR16182.

Michael Han fragmentshaders at gmail.com
Wed Sep 11 08:53:30 PDT 2013


Author: hanm
Date: Wed Sep 11 10:53:29 2013
New Revision: 190528

URL: http://llvm.org/viewvc/llvm-project?rev=190528&view=rev
Log:
Teach RAV to visit parameter variable declarations of implicit functions. Fixes PR16182.

Normally RAV visits parameter variable declarations of a function by traversing the TypeLoc of
the parameter declarations. However, for implicit functions, their parameters don't have any
TypeLoc, because they are implicit.

So for implicit functions, we visit their parameter variable declarations by traversing them through
the function declaration, and visit them accordingly.

Reviewed by Richard Smith and Manuel Klimek.



Modified:
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
    cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
    cfe/trunk/unittests/Tooling/RecursiveASTVisitorTest.cpp
    cfe/trunk/unittests/Tooling/TestVisitor.h

Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=190528&r1=190527&r2=190528&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Wed Sep 11 10:53:29 2013
@@ -1776,6 +1776,14 @@ bool RecursiveASTVisitor<Derived>::Trave
   // 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)) {

Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp?rev=190528&r1=190527&r2=190528&view=diff
==============================================================================
--- cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp Wed Sep 11 10:53:29 2013
@@ -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));
 }

Modified: cfe/trunk/unittests/Tooling/RecursiveASTVisitorTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/RecursiveASTVisitorTest.cpp?rev=190528&r1=190527&r2=190528&view=diff
==============================================================================
--- cfe/trunk/unittests/Tooling/RecursiveASTVisitorTest.cpp (original)
+++ cfe/trunk/unittests/Tooling/RecursiveASTVisitorTest.cpp Wed Sep 11 10:53:29 2013
@@ -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);

Modified: cfe/trunk/unittests/Tooling/TestVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/TestVisitor.h?rev=190528&r1=190527&r2=190528&view=diff
==============================================================================
--- cfe/trunk/unittests/Tooling/TestVisitor.h (original)
+++ cfe/trunk/unittests/Tooling/TestVisitor.h Wed Sep 11 10:53:29 2013
@@ -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);





More information about the cfe-commits mailing list