125 lines · cpp
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-exception6//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>(D)) {35 for (const auto *P : FD->parameters()) {36 if (SFC->inTopFrame())37 assert(isa<NonParamVarRegion>(MRMgr.getVarRegion(P, SFC)));38 else39 assert(isa<ParamVarRegion>(MRMgr.getVarRegion(P, SFC)));40 checkForSameParamRegions(MRMgr, SFC, P);41 }42 } else if (const auto *CD = dyn_cast<CXXConstructorDecl>(D)) {43 for (const auto *P : CD->parameters()) {44 if (SFC->inTopFrame())45 assert(isa<NonParamVarRegion>(MRMgr.getVarRegion(P, SFC)));46 else47 assert(isa<ParamVarRegion>(MRMgr.getVarRegion(P, SFC)));48 checkForSameParamRegions(MRMgr, SFC, P);49 }50 } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {51 for (const auto *P : MD->parameters()) {52 if (SFC->inTopFrame())53 assert(isa<NonParamVarRegion>(MRMgr.getVarRegion(P, SFC)));54 else55 assert(isa<ParamVarRegion>(MRMgr.getVarRegion(P, SFC)));56 checkForSameParamRegions(MRMgr, SFC, 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>(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 O112 + alloc;113 - initWithInt:(int)q;114 @end115 116 void qix(int r) {117 O *o = [[O alloc] initWithInt:r];118 })",119 "input.m"));120}121 122} // namespace123} // namespace ento124} // namespace clang125