From bad2e901c45eefaf6a14d2ecaef2551666c6cedd Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Fri, 22 Jan 2016 15:11:54 +0000 Subject: [PATCH] Let RecursiveASTVisitor visit array index VarDecls An implicit copy ctor creates loop VarDecls that hang off CXXCtorInitializer. RecursiveASTVisitor used to not visit them, so that they didn't show up in the parent map used by ASTMatchers, causing asserts() when the implicit DeclRefExpr() in a CXXCtorInitializer referred to one of these VarDecls. Fixes PR26227. http://reviews.llvm.org/D16413 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@258503 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/RecursiveASTVisitor.h | 4 ++++ unittests/ASTMatchers/ASTMatchersTest.cpp | 8 ++++++++ unittests/Tooling/RecursiveASTVisitorTest.cpp | 19 +++++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 725cf3bcea..0b89a963e3 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -809,6 +809,10 @@ bool RecursiveASTVisitor::TraverseConstructorInitializer( if (Init->isWritten() || getDerived().shouldVisitImplicitCode()) TRY_TO(TraverseStmt(Init->getInit())); + + if (Init->getNumArrayIndices() && getDerived().shouldVisitImplicitCode()) + for (VarDecl *VD : Init->getArrayIndexes()) + TRY_TO(TraverseDecl(VD)); return true; } diff --git a/unittests/ASTMatchers/ASTMatchersTest.cpp b/unittests/ASTMatchers/ASTMatchersTest.cpp index b6983052dd..ab1997ab0f 100644 --- a/unittests/ASTMatchers/ASTMatchersTest.cpp +++ b/unittests/ASTMatchers/ASTMatchersTest.cpp @@ -4217,6 +4217,14 @@ TEST(HasAncestor, MatchesAllAncestors) { hasAncestor(cxxRecordDecl(unless(isTemplateInstantiation()))))))); } +TEST(HasAncestor, ImplicitArrayCopyCtorDeclRefExpr) { + EXPECT_TRUE(matches("struct MyClass {\n" + " int c[1];\n" + " static MyClass Create() { return MyClass(); }\n" + "};", + declRefExpr(to(decl(hasAncestor(decl())))))); +} + TEST(HasParent, MatchesAllParents) { EXPECT_TRUE(matches( "template struct C { static void f() { 42; } };" diff --git a/unittests/Tooling/RecursiveASTVisitorTest.cpp b/unittests/Tooling/RecursiveASTVisitorTest.cpp index 5d0e2bccd4..991ae8bb7f 100644 --- a/unittests/Tooling/RecursiveASTVisitorTest.cpp +++ b/unittests/Tooling/RecursiveASTVisitorTest.cpp @@ -133,4 +133,23 @@ TEST(RecursiveASTVisitor, AttributesAreVisited) { "};\n")); } +// Check to ensure that VarDecls are visited. +class VarDeclVisitor : public ExpectedLocationVisitor { +public: + bool VisitVarDecl(VarDecl *VD) { + Match(VD->getNameAsString(), VD->getLocStart()); + return true; + } +}; + +TEST(RecursiveASTVisitor, ArrayInitializersAreVisited) { + VarDeclVisitor Visitor; + Visitor.ExpectMatch("__i0", 1, 8); + EXPECT_TRUE( + Visitor.runOver("struct MyClass {\n" + " int c[1];\n" + " static MyClass Create() { return MyClass(); }\n" + "};\n")); +} + } // end anonymous namespace -- 2.50.1