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:
ConstructExprVisitor()24   ConstructExprVisitor() : ShouldVisitImplicitCode(false) {}
25 
shouldVisitImplicitCode() const26   bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; }
27 
setShouldVisitImplicitCode(bool NewValue)28   void setShouldVisitImplicitCode(bool NewValue) {
29     ShouldVisitImplicitCode = NewValue;
30   }
31 
VisitCXXConstructExpr(CXXConstructExpr * Expr)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 
TEST(RecursiveASTVisitor,CanVisitImplicitMemberInitializations)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.
TEST(RecursiveASTVisitor,CanSkipImplicitMemberInitializations)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