1 //===- unittests/StaticAnalyzer/SymbolReaperTest.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 SuperRegionLivenessConsumer : public ExprEngineConsumer { 19 void performTest(const Decl *D) { 20 const auto *FD = findDeclByName<FieldDecl>(D, "x"); 21 const auto *VD = findDeclByName<VarDecl>(D, "s"); 22 assert(FD && VD); 23 24 // The variable must belong to a stack frame, 25 // otherwise SymbolReaper would think it's a global. 26 const StackFrameContext *SFC = 27 Eng.getAnalysisDeclContextManager().getStackFrame(D); 28 29 // Create regions for 's' and 's.x'. 30 const VarRegion *VR = Eng.getRegionManager().getVarRegion(VD, SFC); 31 const FieldRegion *FR = Eng.getRegionManager().getFieldRegion(FD, VR); 32 33 // Pass a null location context to the SymbolReaper so that 34 // it was thinking that the variable is dead. 35 SymbolReaper SymReaper((StackFrameContext *)nullptr, (Stmt *)nullptr, 36 Eng.getSymbolManager(), Eng.getStoreManager()); 37 38 SymReaper.markLive(FR); 39 EXPECT_TRUE(SymReaper.isLiveRegion(VR)); 40 } 41 42 public: 43 SuperRegionLivenessConsumer(CompilerInstance &C) : ExprEngineConsumer(C) {} 44 ~SuperRegionLivenessConsumer() override {} 45 46 bool HandleTopLevelDecl(DeclGroupRef DG) override { 47 for (const auto *D : DG) 48 performTest(D); 49 return true; 50 } 51 }; 52 53 class SuperRegionLivenessAction : public ASTFrontendAction { 54 public: 55 SuperRegionLivenessAction() {} 56 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler, 57 StringRef File) override { 58 return llvm::make_unique<SuperRegionLivenessConsumer>(Compiler); 59 } 60 }; 61 62 // Test that marking s.x as live would also make s live. 63 TEST(SymbolReaper, SuperRegionLiveness) { 64 EXPECT_TRUE(tooling::runToolOnCode(new SuperRegionLivenessAction, 65 "void foo() { struct S { int x; } s; }")); 66 } 67 68 } // namespace 69 } // namespace ento 70 } // namespace clang 71