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