xref: /llvm-project/clang/unittests/StaticAnalyzer/SymbolReaperTest.cpp (revision b22804b35464049ca92107d45042d2a5bbd292f6)
12ed0e79bSArtem Dergachev //===- unittests/StaticAnalyzer/SymbolReaperTest.cpp ----------------------===//
22ed0e79bSArtem Dergachev //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62ed0e79bSArtem Dergachev //
72ed0e79bSArtem Dergachev //===----------------------------------------------------------------------===//
82ed0e79bSArtem Dergachev 
97cc87be4SArtem Dergachev #include "Reusables.h"
107cc87be4SArtem Dergachev 
112ed0e79bSArtem Dergachev #include "clang/Tooling/Tooling.h"
122ed0e79bSArtem Dergachev #include "gtest/gtest.h"
132ed0e79bSArtem Dergachev 
142ed0e79bSArtem Dergachev namespace clang {
152ed0e79bSArtem Dergachev namespace ento {
162ed0e79bSArtem Dergachev namespace {
172ed0e79bSArtem Dergachev 
182ed0e79bSArtem Dergachev class SuperRegionLivenessConsumer : public ExprEngineConsumer {
performTest(const Decl * D)192ed0e79bSArtem Dergachev   void performTest(const Decl *D) {
202ed0e79bSArtem Dergachev     const auto *FD = findDeclByName<FieldDecl>(D, "x");
212ed0e79bSArtem Dergachev     const auto *VD = findDeclByName<VarDecl>(D, "s");
222ed0e79bSArtem Dergachev     assert(FD && VD);
232ed0e79bSArtem Dergachev 
242ed0e79bSArtem Dergachev     // The variable must belong to a stack frame,
252ed0e79bSArtem Dergachev     // otherwise SymbolReaper would think it's a global.
262ed0e79bSArtem Dergachev     const StackFrameContext *SFC =
272ed0e79bSArtem Dergachev         Eng.getAnalysisDeclContextManager().getStackFrame(D);
282ed0e79bSArtem Dergachev 
292ed0e79bSArtem Dergachev     // Create regions for 's' and 's.x'.
302ed0e79bSArtem Dergachev     const VarRegion *VR = Eng.getRegionManager().getVarRegion(VD, SFC);
312ed0e79bSArtem Dergachev     const FieldRegion *FR = Eng.getRegionManager().getFieldRegion(FD, VR);
322ed0e79bSArtem Dergachev 
332ed0e79bSArtem Dergachev     // Pass a null location context to the SymbolReaper so that
342ed0e79bSArtem Dergachev     // it was thinking that the variable is dead.
352ed0e79bSArtem Dergachev     SymbolReaper SymReaper((StackFrameContext *)nullptr, (Stmt *)nullptr,
362ed0e79bSArtem Dergachev                            Eng.getSymbolManager(), Eng.getStoreManager());
372ed0e79bSArtem Dergachev 
382ed0e79bSArtem Dergachev     SymReaper.markLive(FR);
392ed0e79bSArtem Dergachev     EXPECT_TRUE(SymReaper.isLiveRegion(VR));
402ed0e79bSArtem Dergachev   }
412ed0e79bSArtem Dergachev 
422ed0e79bSArtem Dergachev public:
SuperRegionLivenessConsumer(CompilerInstance & C)432ed0e79bSArtem Dergachev   SuperRegionLivenessConsumer(CompilerInstance &C) : ExprEngineConsumer(C) {}
~SuperRegionLivenessConsumer()442ed0e79bSArtem Dergachev   ~SuperRegionLivenessConsumer() override {}
452ed0e79bSArtem Dergachev 
HandleTopLevelDecl(DeclGroupRef DG)462ed0e79bSArtem Dergachev   bool HandleTopLevelDecl(DeclGroupRef DG) override {
472ed0e79bSArtem Dergachev     for (const auto *D : DG)
482ed0e79bSArtem Dergachev       performTest(D);
492ed0e79bSArtem Dergachev     return true;
502ed0e79bSArtem Dergachev   }
512ed0e79bSArtem Dergachev };
522ed0e79bSArtem Dergachev 
532ed0e79bSArtem Dergachev class SuperRegionLivenessAction : public ASTFrontendAction {
542ed0e79bSArtem Dergachev public:
SuperRegionLivenessAction()552ed0e79bSArtem Dergachev   SuperRegionLivenessAction() {}
CreateASTConsumer(CompilerInstance & Compiler,StringRef File)562ed0e79bSArtem Dergachev   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
572ed0e79bSArtem Dergachev                                                  StringRef File) override {
582b3d49b6SJonas Devlieghere     return std::make_unique<SuperRegionLivenessConsumer>(Compiler);
592ed0e79bSArtem Dergachev   }
602ed0e79bSArtem Dergachev };
612ed0e79bSArtem Dergachev 
622ed0e79bSArtem Dergachev // Test that marking s.x as live would also make s live.
TEST(SymbolReaper,SuperRegionLiveness)632ed0e79bSArtem Dergachev TEST(SymbolReaper, SuperRegionLiveness) {
64*b22804b3SDmitri Gribenko   EXPECT_TRUE(
65*b22804b3SDmitri Gribenko       tooling::runToolOnCode(std::make_unique<SuperRegionLivenessAction>(),
662ed0e79bSArtem Dergachev                              "void foo() { struct S { int x; } s; }"));
672ed0e79bSArtem Dergachev }
682ed0e79bSArtem Dergachev 
692ed0e79bSArtem Dergachev } // namespace
702ed0e79bSArtem Dergachev } // namespace ento
712ed0e79bSArtem Dergachev } // namespace clang
72