1 //===- unittest/Tooling/RecursiveASTVisitorTests/ConstructExpr.cpp --------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "TestVisitor.h" 10 11 using namespace clang; 12 13 namespace { 14 15 /// \brief A visitor that optionally includes implicit code and matches 16 /// CXXConstructExpr. 17 /// 18 /// The name recorded for the match is the name of the class whose constructor 19 /// is invoked by the CXXConstructExpr, not the name of the class whose 20 /// constructor the CXXConstructExpr is contained in. 21 class ConstructExprVisitor 22 : public ExpectedLocationVisitor<ConstructExprVisitor> { 23 public: 24 ConstructExprVisitor() : ShouldVisitImplicitCode(false) {} 25 26 bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; } 27 28 void setShouldVisitImplicitCode(bool NewValue) { 29 ShouldVisitImplicitCode = NewValue; 30 } 31 32 bool VisitCXXConstructExpr(CXXConstructExpr* Expr) { 33 if (const CXXConstructorDecl* Ctor = Expr->getConstructor()) { 34 if (const CXXRecordDecl* Class = Ctor->getParent()) { 35 Match(Class->getName(), Expr->getLocation()); 36 } 37 } 38 return true; 39 } 40 41 private: 42 bool ShouldVisitImplicitCode; 43 }; 44 45 TEST(RecursiveASTVisitor, CanVisitImplicitMemberInitializations) { 46 ConstructExprVisitor Visitor; 47 Visitor.setShouldVisitImplicitCode(true); 48 Visitor.ExpectMatch("WithCtor", 2, 8); 49 // Simple has a constructor that implicitly initializes 'w'. Test 50 // that a visitor that visits implicit code visits that initialization. 51 // Note: Clang lazily instantiates implicit declarations, so we need 52 // to use them in order to force them to appear in the AST. 53 EXPECT_TRUE(Visitor.runOver( 54 "struct WithCtor { WithCtor(); }; \n" 55 "struct Simple { WithCtor w; }; \n" 56 "int main() { Simple s; }\n")); 57 } 58 59 // The same as CanVisitImplicitMemberInitializations, but checking that the 60 // visits are omitted when the visitor does not include implicit code. 61 TEST(RecursiveASTVisitor, CanSkipImplicitMemberInitializations) { 62 ConstructExprVisitor Visitor; 63 Visitor.setShouldVisitImplicitCode(false); 64 Visitor.DisallowMatch("WithCtor", 2, 8); 65 // Simple has a constructor that implicitly initializes 'w'. Test 66 // that a visitor that skips implicit code skips that initialization. 67 // Note: Clang lazily instantiates implicit declarations, so we need 68 // to use them in order to force them to appear in the AST. 69 EXPECT_TRUE(Visitor.runOver( 70 "struct WithCtor { WithCtor(); }; \n" 71 "struct Simple { WithCtor w; }; \n" 72 "int main() { Simple s; }\n")); 73 } 74 75 } // end anonymous namespace 76