1//===- unittests/StaticAnalyzer/ParamRegionTest.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 "Reusables.h"
10
11#include "clang/Tooling/Tooling.h"
12#include "gtest/gtest.h"
13
14namespace clang {
15namespace ento {
16namespace {
17
18class ParamRegionTestConsumer : public ExprEngineConsumer {
19 void checkForSameParamRegions(MemRegionManager &MRMgr,
20 const StackFrameContext *SFC,
21 const ParmVarDecl *PVD) {
22 ASSERT_TRUE(llvm::all_of(PVD->redecls(), [&](const clang::VarDecl *D2) {
23 return MRMgr.getVarRegion(PVD, SFC) ==
24 MRMgr.getVarRegion(cast<ParmVarDecl>(D2), SFC);
25 }));
26 }
27
28 void performTest(const Decl *D) {
29 StoreManager &StMgr = Eng.getStoreManager();
30 MemRegionManager &MRMgr = StMgr.getRegionManager();
31 const StackFrameContext *SFC =
32 Eng.getAnalysisDeclContextManager().getStackFrame(D);
33
34 if (const auto *FD = dyn_cast<FunctionDecl>(Val: D)) {
35 for (const auto *P : FD->parameters()) {
36 if (SFC->inTopFrame())
37 assert(isa<NonParamVarRegion>(MRMgr.getVarRegion(P, SFC)));
38 else
39 assert(isa<ParamVarRegion>(MRMgr.getVarRegion(P, SFC)));
40 checkForSameParamRegions(MRMgr, SFC, PVD: P);
41 }
42 } else if (const auto *CD = dyn_cast<CXXConstructorDecl>(Val: D)) {
43 for (const auto *P : CD->parameters()) {
44 if (SFC->inTopFrame())
45 assert(isa<NonParamVarRegion>(MRMgr.getVarRegion(P, SFC)));
46 else
47 assert(isa<ParamVarRegion>(MRMgr.getVarRegion(P, SFC)));
48 checkForSameParamRegions(MRMgr, SFC, P);
49 }
50 } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(Val: D)) {
51 for (const auto *P : MD->parameters()) {
52 if (SFC->inTopFrame())
53 assert(isa<NonParamVarRegion>(MRMgr.getVarRegion(P, SFC)));
54 else
55 assert(isa<ParamVarRegion>(MRMgr.getVarRegion(P, SFC)));
56 checkForSameParamRegions(MRMgr, SFC, PVD: P);
57 }
58 }
59 }
60
61public:
62 ParamRegionTestConsumer(CompilerInstance &C) : ExprEngineConsumer(C) {}
63
64 bool HandleTopLevelDecl(DeclGroupRef DG) override {
65 for (const auto *D : DG) {
66 performTest(D);
67 }
68 return true;
69 }
70};
71
72class ParamRegionTestAction : public ASTFrontendAction {
73public:
74 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
75 StringRef File) override {
76 return std::make_unique<ParamRegionTestConsumer>(args&: Compiler);
77 }
78};
79
80TEST(ParamRegion, ParamRegionTest) {
81 EXPECT_TRUE(
82 tooling::runToolOnCode(std::make_unique<ParamRegionTestAction>(),
83 R"(void foo(int n);
84 void baz(int p);
85
86 void foo(int n) {
87 auto lambda = [n](int m) {
88 return n + m;
89 };
90
91 int k = lambda(2);
92 }
93
94 void bar(int l) {
95 foo(l);
96 }
97
98 struct S {
99 int n;
100 S(int nn): n(nn) {}
101 };
102
103 void baz(int p) {
104 S s(p);
105 }
106
107 void bar(int l);
108 void baz(int p);)"));
109 EXPECT_TRUE(
110 tooling::runToolOnCode(std::make_unique<ParamRegionTestAction>(),
111 R"(@interface O
112 + alloc;
113 - initWithInt:(int)q;
114 @end
115
116 void qix(int r) {
117 O *o = [[O alloc] initWithInt:r];
118 })",
119 "input.m"));
120}
121
122} // namespace
123} // namespace ento
124} // namespace clang
125

source code of clang/unittests/StaticAnalyzer/ParamRegionTest.cpp