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