]> granicus.if.org Git - clang/commitdiff
Rename shouldVisitImplicitDeclarations to shouldVisitImplicitCode.
authorDaniel Jasper <djasper@google.com>
Wed, 13 Jun 2012 07:12:33 +0000 (07:12 +0000)
committerDaniel Jasper <djasper@google.com>
Wed, 13 Jun 2012 07:12:33 +0000 (07:12 +0000)
Fix RecursiveASTVisitor to visit CXXForRangeStmts accordingly to visit
implicit or explicit code.

The key bug that inspired this was the Visitor not visiting the range
initializer of such a loop, which is explicit code.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@158395 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/RecursiveASTVisitor.h
unittests/Tooling/RecursiveASTVisitorTest.cpp

index de042cafb6d112830ef0882bebe27a3a848e63d4..2014f071523425357b05ad539728b00f7c32b765 100644 (file)
@@ -149,8 +149,8 @@ public:
   bool shouldWalkTypesOfTypeLocs() const { return true; }
 
   /// \brief Return whether this visitor should recurse into implicit
-  /// declarations, e.g., implicit constructors and destructors.
-  bool shouldVisitImplicitDeclarations() const { return false; }
+  /// 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.
@@ -607,7 +607,7 @@ bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) {
 
   // As a syntax visitor, by default we want to ignore declarations for
   // implicit declarations (ones not typed explicitly by the user).
-  if (!getDerived().shouldVisitImplicitDeclarations() && D->isImplicit())
+  if (!getDerived().shouldVisitImplicitCode() && D->isImplicit())
     return true;
 
   switch (D->getKind()) {
@@ -1755,7 +1755,8 @@ template<typename Derived>
 bool RecursiveASTVisitor<Derived>::TraverseVarHelper(VarDecl *D) {
   TRY_TO(TraverseDeclaratorHelper(D));
   // Default params are taken care of when we traverse the ParmVarDecl.
-  if (!isa<ParmVarDecl>(D))
+  if (!isa<ParmVarDecl>(D) &&
+      (!D->isCXXForRangeDecl() || shouldVisitImplicitCode()))
     TRY_TO(TraverseStmt(D->getInit()));
   return true;
 }
@@ -1873,7 +1874,14 @@ DEF_TRAVERSE_STMT(ObjCAtThrowStmt, { })
 DEF_TRAVERSE_STMT(ObjCAtTryStmt, { })
 DEF_TRAVERSE_STMT(ObjCForCollectionStmt, { })
 DEF_TRAVERSE_STMT(ObjCAutoreleasePoolStmt, { })
-DEF_TRAVERSE_STMT(CXXForRangeStmt, { })
+DEF_TRAVERSE_STMT(CXXForRangeStmt, {
+  if (!shouldVisitImplicitCode()) {
+    TRY_TO(TraverseStmt(S->getLoopVarStmt()));
+    TRY_TO(TraverseStmt(S->getRangeInit()));
+    // Visit everything else only if shouldVisitImplicitCode().
+    return true;
+  }
+})
 DEF_TRAVERSE_STMT(MSDependentExistsStmt, {
     TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
     TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo()));
index 52b3987bc84a0851b5bc916b6ecd896ac7d2c28e..9d693095d7cc1c27f118fdb9d5591598cecf5823 100644 (file)
@@ -142,6 +142,14 @@ public:
   }
 };
 
+class VarDeclVisitor : public ExpectedLocationVisitor<VarDeclVisitor> {
+public:
+ bool VisitVarDecl(VarDecl *Variable) {
+   Match(Variable->getNameAsString(), Variable->getLocStart());
+   return true;
+ }
+};
+
 class CXXMemberCallVisitor
   : public ExpectedLocationVisitor<CXXMemberCallVisitor> {
 public:
@@ -250,6 +258,22 @@ TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArguments) {
     "void x(); template <void (*T)()> class X {};\nX<x> y;"));
 }
 
+TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtRange) {
+  DeclRefExprVisitor Visitor;
+  Visitor.ExpectMatch("x", 2, 25);
+  EXPECT_TRUE(Visitor.runOver(
+    "int x[5];\n"
+    "void f() { for (int i : x) {} }"));
+}
+
+TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtLoopVariable) {
+  VarDeclVisitor Visitor;
+  Visitor.ExpectMatch("i", 2, 17);
+  EXPECT_TRUE(Visitor.runOver(
+    "int x[5];\n"
+    "void f() { for (int i : x) {} }"));
+}
+
 TEST(RecursiveASTVisitor, VisitsCallExpr) {
   DeclRefExprVisitor Visitor;
   Visitor.ExpectMatch("x", 1, 22);
@@ -452,7 +476,7 @@ TEST(RecursiveASTVisitor, VisitsClassTemplateTemplateParmDefaultArgument) {
 class ImplicitCtorVisitor
     : public ExpectedLocationVisitor<ImplicitCtorVisitor> {
 public:
-  bool shouldVisitImplicitDeclarations() const { return true; }
+  bool shouldVisitImplicitCode() const { return true; }
 
   bool VisitCXXConstructorDecl(CXXConstructorDecl* Ctor) {
     if (Ctor->isImplicit()) {  // Was not written in source code