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 14 namespace clang { 15 namespace ento { 16 namespace { 17 18 class 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)) { FileExporterXSLT(const QString & xsltFilename,QObject * parent)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, P); 41 } 42 } else if (const auto *CD = dyn_cast<CXXConstructorDecl>(D)) { ~FileExporterXSLT()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>(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, P); 57 } 58 } 59 } 60 61 public: 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 72 class ParamRegionTestAction : public ASTFrontendAction { 73 public: 74 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler, 75 StringRef File) override { 76 return std::make_unique<ParamRegionTestConsumer>(Compiler); 77 } 78 }; 79 80 TEST(ParamRegion, ParamRegionTest) { 81 EXPECT_TRUE( save(QIODevice * iodevice,const QSharedPointer<const Element> element,const File * bibtexfile,QStringList * errorLog)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 cancel()116 void qix(int r) { 117 O *o = [[O alloc] initWithInt:r]; 118 })", 119 "input.m")); 120 } FileExporterHTML(QObject * parent)121 122 } // namespace 123 } // namespace ento 124 } // namespace clang 125