xref: /llvm-project/clang/unittests/StaticAnalyzer/SymbolReaperTest.cpp (revision b22804b35464049ca92107d45042d2a5bbd292f6)
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 {
performTest(const Decl * D)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:
SuperRegionLivenessConsumer(CompilerInstance & C)43   SuperRegionLivenessConsumer(CompilerInstance &C) : ExprEngineConsumer(C) {}
~SuperRegionLivenessConsumer()44   ~SuperRegionLivenessConsumer() override {}
45 
HandleTopLevelDecl(DeclGroupRef DG)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:
SuperRegionLivenessAction()55   SuperRegionLivenessAction() {}
CreateASTConsumer(CompilerInstance & Compiler,StringRef File)56   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
57                                                  StringRef File) override {
58     return std::make_unique<SuperRegionLivenessConsumer>(Compiler);
59   }
60 };
61 
62 // Test that marking s.x as live would also make s live.
TEST(SymbolReaper,SuperRegionLiveness)63 TEST(SymbolReaper, SuperRegionLiveness) {
64   EXPECT_TRUE(
65       tooling::runToolOnCode(std::make_unique<SuperRegionLivenessAction>(),
66                              "void foo() { struct S { int x; } s; }"));
67 }
68 
69 } // namespace
70 } // namespace ento
71 } // namespace clang
72