Clang Project

clang_source_code/unittests/Tooling/RecursiveASTVisitorTests/ConstructExpr.cpp
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
11using namespace clang;
12
13namespace {
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.
21class ConstructExprVisitor
22    : public ExpectedLocationVisitor<ConstructExprVisitor> {
23public:
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
45TEST(RecursiveASTVisitor, CanVisitImplicitMemberInitializations) {
46  ConstructExprVisitor Visitor;
47  Visitor.setShouldVisitImplicitCode(true);
48  Visitor.ExpectMatch("WithCtor"28);
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.
61TEST(RecursiveASTVisitor, CanSkipImplicitMemberInitializations) {
62  ConstructExprVisitor Visitor;
63  Visitor.setShouldVisitImplicitCode(false);
64  Visitor.DisallowMatch("WithCtor"28);
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