xref: /llvm-project/clang/unittests/StaticAnalyzer/ParamRegionTest.cpp (revision b2a37cfe2bda0bc8c4d2e981922b5ac59c429bdc)
198db1f99SAdam Balogh //===- unittests/StaticAnalyzer/ParamRegionTest.cpp -----------------------===//
298db1f99SAdam Balogh //
398db1f99SAdam Balogh // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
498db1f99SAdam Balogh // See https://llvm.org/LICENSE.txt for license information.
598db1f99SAdam Balogh // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
698db1f99SAdam Balogh //
798db1f99SAdam Balogh //===----------------------------------------------------------------------===//
898db1f99SAdam Balogh 
998db1f99SAdam Balogh #include "Reusables.h"
1098db1f99SAdam Balogh 
1198db1f99SAdam Balogh #include "clang/Tooling/Tooling.h"
1298db1f99SAdam Balogh #include "gtest/gtest.h"
1398db1f99SAdam Balogh 
1498db1f99SAdam Balogh namespace clang {
1598db1f99SAdam Balogh namespace ento {
1698db1f99SAdam Balogh namespace {
1798db1f99SAdam Balogh 
1898db1f99SAdam Balogh class ParamRegionTestConsumer : public ExprEngineConsumer {
checkForSameParamRegions(MemRegionManager & MRMgr,const StackFrameContext * SFC,const ParmVarDecl * PVD)195419a312SAdam Balogh   void checkForSameParamRegions(MemRegionManager &MRMgr,
205419a312SAdam Balogh                                 const StackFrameContext *SFC,
215419a312SAdam Balogh                                 const ParmVarDecl *PVD) {
22*b2a37cfeSAdam Balogh     ASSERT_TRUE(llvm::all_of(PVD->redecls(), [&](const clang::VarDecl *D2) {
23f529c0a8SSimon Pilgrim       return MRMgr.getVarRegion(PVD, SFC) ==
24948b206fSSimon Pilgrim              MRMgr.getVarRegion(cast<ParmVarDecl>(D2), SFC);
25f529c0a8SSimon Pilgrim     }));
265419a312SAdam Balogh   }
275419a312SAdam Balogh 
performTest(const Decl * D)2898db1f99SAdam Balogh   void performTest(const Decl *D) {
2998db1f99SAdam Balogh     StoreManager &StMgr = Eng.getStoreManager();
3098db1f99SAdam Balogh     MemRegionManager &MRMgr = StMgr.getRegionManager();
3198db1f99SAdam Balogh     const StackFrameContext *SFC =
3298db1f99SAdam Balogh         Eng.getAnalysisDeclContextManager().getStackFrame(D);
3398db1f99SAdam Balogh 
3498db1f99SAdam Balogh     if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
3598db1f99SAdam Balogh       for (const auto *P : FD->parameters()) {
3698db1f99SAdam Balogh         if (SFC->inTopFrame())
37ccd19220SSterling Augustine           assert(isa<NonParamVarRegion>(MRMgr.getVarRegion(P, SFC)));
3898db1f99SAdam Balogh         else
39ccd19220SSterling Augustine           assert(isa<ParamVarRegion>(MRMgr.getVarRegion(P, SFC)));
405419a312SAdam Balogh         checkForSameParamRegions(MRMgr, SFC, P);
4198db1f99SAdam Balogh       }
4298db1f99SAdam Balogh     } else if (const auto *CD = dyn_cast<CXXConstructorDecl>(D)) {
4398db1f99SAdam Balogh       for (const auto *P : CD->parameters()) {
4498db1f99SAdam Balogh         if (SFC->inTopFrame())
45ccd19220SSterling Augustine           assert(isa<NonParamVarRegion>(MRMgr.getVarRegion(P, SFC)));
4698db1f99SAdam Balogh         else
47ccd19220SSterling Augustine           assert(isa<ParamVarRegion>(MRMgr.getVarRegion(P, SFC)));
485419a312SAdam Balogh         checkForSameParamRegions(MRMgr, SFC, P);
4998db1f99SAdam Balogh       }
5098db1f99SAdam Balogh     } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
5198db1f99SAdam Balogh       for (const auto *P : MD->parameters()) {
5298db1f99SAdam Balogh         if (SFC->inTopFrame())
53ccd19220SSterling Augustine           assert(isa<NonParamVarRegion>(MRMgr.getVarRegion(P, SFC)));
5498db1f99SAdam Balogh         else
55ccd19220SSterling Augustine           assert(isa<ParamVarRegion>(MRMgr.getVarRegion(P, SFC)));
565419a312SAdam Balogh         checkForSameParamRegions(MRMgr, SFC, P);
5798db1f99SAdam Balogh       }
5898db1f99SAdam Balogh     }
5998db1f99SAdam Balogh   }
6098db1f99SAdam Balogh 
6198db1f99SAdam Balogh public:
ParamRegionTestConsumer(CompilerInstance & C)6298db1f99SAdam Balogh   ParamRegionTestConsumer(CompilerInstance &C) : ExprEngineConsumer(C) {}
6398db1f99SAdam Balogh 
HandleTopLevelDecl(DeclGroupRef DG)6498db1f99SAdam Balogh   bool HandleTopLevelDecl(DeclGroupRef DG) override {
6598db1f99SAdam Balogh     for (const auto *D : DG) {
6698db1f99SAdam Balogh       performTest(D);
6798db1f99SAdam Balogh     }
6898db1f99SAdam Balogh     return true;
6998db1f99SAdam Balogh   }
7098db1f99SAdam Balogh };
7198db1f99SAdam Balogh 
7298db1f99SAdam Balogh class ParamRegionTestAction : public ASTFrontendAction {
7398db1f99SAdam Balogh public:
CreateASTConsumer(CompilerInstance & Compiler,StringRef File)7498db1f99SAdam Balogh   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
7598db1f99SAdam Balogh                                                  StringRef File) override {
7698db1f99SAdam Balogh     return std::make_unique<ParamRegionTestConsumer>(Compiler);
7798db1f99SAdam Balogh   }
7898db1f99SAdam Balogh };
7998db1f99SAdam Balogh 
TEST(ParamRegion,ParamRegionTest)8098db1f99SAdam Balogh TEST(ParamRegion, ParamRegionTest) {
8198db1f99SAdam Balogh   EXPECT_TRUE(
8298db1f99SAdam Balogh       tooling::runToolOnCode(std::make_unique<ParamRegionTestAction>(),
835419a312SAdam Balogh                              R"(void foo(int n);
845419a312SAdam Balogh                                 void baz(int p);
855419a312SAdam Balogh 
865419a312SAdam Balogh                                 void foo(int n) {
8798db1f99SAdam Balogh                                   auto lambda = [n](int m) {
8898db1f99SAdam Balogh                                     return n + m;
8998db1f99SAdam Balogh                                   };
9098db1f99SAdam Balogh 
9198db1f99SAdam Balogh                                   int k = lambda(2);
9298db1f99SAdam Balogh                                 }
9398db1f99SAdam Balogh 
9498db1f99SAdam Balogh                                 void bar(int l) {
9598db1f99SAdam Balogh                                   foo(l);
9698db1f99SAdam Balogh                                 }
9798db1f99SAdam Balogh 
9898db1f99SAdam Balogh                                 struct S {
9998db1f99SAdam Balogh                                   int n;
10098db1f99SAdam Balogh                                   S(int nn): n(nn) {}
10198db1f99SAdam Balogh                                 };
10298db1f99SAdam Balogh 
10398db1f99SAdam Balogh                                 void baz(int p) {
10498db1f99SAdam Balogh                                   S s(p);
1055419a312SAdam Balogh                                 }
1065419a312SAdam Balogh 
1075419a312SAdam Balogh                                 void bar(int l);
1085419a312SAdam Balogh                                 void baz(int p);)"));
10998db1f99SAdam Balogh   EXPECT_TRUE(
11098db1f99SAdam Balogh       tooling::runToolOnCode(std::make_unique<ParamRegionTestAction>(),
11198db1f99SAdam Balogh                              R"(@interface O
11298db1f99SAdam Balogh                                 + alloc;
11398db1f99SAdam Balogh                                 - initWithInt:(int)q;
11498db1f99SAdam Balogh                                 @end
11598db1f99SAdam Balogh 
11698db1f99SAdam Balogh                                 void qix(int r) {
11798db1f99SAdam Balogh                                   O *o = [[O alloc] initWithInt:r];
11898db1f99SAdam Balogh                                 })",
11998db1f99SAdam Balogh                              "input.m"));
12098db1f99SAdam Balogh }
12198db1f99SAdam Balogh 
12298db1f99SAdam Balogh } // namespace
12398db1f99SAdam Balogh } // namespace ento
12498db1f99SAdam Balogh } // namespace clang
125