brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.6 KiB · 1448c2b Raw
158 lines · cpp
1//===- unittests/StaticAnalyzer/StoreTest.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-exception6//7//===----------------------------------------------------------------------===//8 9#include "Reusables.h"10 11#include "clang/Tooling/Tooling.h"12#include "gtest/gtest.h"13 14namespace clang {15namespace ento {16namespace {17 18class StoreTestConsumer : public ExprEngineConsumer {19public:20  StoreTestConsumer(CompilerInstance &C) : ExprEngineConsumer(C) {}21 22  bool HandleTopLevelDecl(DeclGroupRef DG) override {23    for (const auto *D : DG)24      performTest(D);25    return true;26  }27 28private:29  virtual void performTest(const Decl *D) = 0;30};31 32template <class ConsumerTy> class TestAction : public ASTFrontendAction {33public:34  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,35                                                 StringRef File) override {36    return std::make_unique<ConsumerTy>(Compiler);37  }38};39 40// Test that we can put a value into an int-type variable and load it41// back from that variable. Test what happens if default bindings are used.42class VariableBindConsumer : public StoreTestConsumer {43  void performTest(const Decl *D) override {44    StoreManager &SManager = Eng.getStoreManager();45    SValBuilder &Builder = Eng.getSValBuilder();46    MemRegionManager &MRManager = SManager.getRegionManager();47    const ASTContext &ASTCtxt = Eng.getContext();48 49    const auto *VDX0 = findDeclByName<VarDecl>(D, "x0");50    const auto *VDY0 = findDeclByName<VarDecl>(D, "y0");51    const auto *VDZ0 = findDeclByName<VarDecl>(D, "z0");52    const auto *VDX1 = findDeclByName<VarDecl>(D, "x1");53    const auto *VDY1 = findDeclByName<VarDecl>(D, "y1");54 55    ASSERT_TRUE(VDX0 && VDY0 && VDZ0 && VDX1 && VDY1);56 57    const StackFrameContext *SFC =58        Eng.getAnalysisDeclContextManager().getStackFrame(D);59 60    Loc LX0 = loc::MemRegionVal(MRManager.getVarRegion(VDX0, SFC));61    Loc LY0 = loc::MemRegionVal(MRManager.getVarRegion(VDY0, SFC));62    Loc LZ0 = loc::MemRegionVal(MRManager.getVarRegion(VDZ0, SFC));63    Loc LX1 = loc::MemRegionVal(MRManager.getVarRegion(VDX1, SFC));64    Loc LY1 = loc::MemRegionVal(MRManager.getVarRegion(VDY1, SFC));65 66    Store StInit = SManager.getInitialStore(SFC).getStore();67    SVal Zero = Builder.makeZeroVal(ASTCtxt.IntTy);68    SVal One = Builder.makeIntVal(1, ASTCtxt.IntTy);69    SVal NarrowZero = Builder.makeZeroVal(ASTCtxt.CharTy);70 71    // Bind(Zero)72    Store StX0 = SManager.Bind(StInit, LX0, Zero).ResultingStore.getStore();73    EXPECT_EQ(Zero, SManager.getBinding(StX0, LX0, ASTCtxt.IntTy));74 75    // BindDefaultInitial(Zero)76    Store StY0 = SManager.BindDefaultInitial(StInit, LY0.getAsRegion(), Zero)77                     .ResultingStore.getStore();78    EXPECT_EQ(Zero, SManager.getBinding(StY0, LY0, ASTCtxt.IntTy));79    EXPECT_EQ(Zero, *SManager.getDefaultBinding(StY0, LY0.getAsRegion()));80 81    // BindDefaultZero()82    Store StZ0 = SManager.BindDefaultZero(StInit, LZ0.getAsRegion())83                     .ResultingStore.getStore();84    // BindDefaultZero wipes the region with '0 S8b', not with out Zero.85    // Direct load, however, does give us back the object of the type86    // that we specify for loading.87    EXPECT_EQ(Zero, SManager.getBinding(StZ0, LZ0, ASTCtxt.IntTy));88    EXPECT_EQ(NarrowZero, *SManager.getDefaultBinding(StZ0, LZ0.getAsRegion()));89 90    // Bind(One)91    Store StX1 = SManager.Bind(StInit, LX1, One).ResultingStore.getStore();92    EXPECT_EQ(One, SManager.getBinding(StX1, LX1, ASTCtxt.IntTy));93 94    // BindDefaultInitial(One)95    Store StY1 = SManager.BindDefaultInitial(StInit, LY1.getAsRegion(), One)96                     .ResultingStore.getStore();97    EXPECT_EQ(One, SManager.getBinding(StY1, LY1, ASTCtxt.IntTy));98    EXPECT_EQ(One, *SManager.getDefaultBinding(StY1, LY1.getAsRegion()));99  }100 101public:102  using StoreTestConsumer::StoreTestConsumer;103};104 105TEST(Store, VariableBind) {106  EXPECT_TRUE(tooling::runToolOnCode(107      std::make_unique<TestAction<VariableBindConsumer>>(),108      "void foo() { int x0, y0, z0, x1, y1; }"));109}110 111class LiteralCompoundConsumer : public StoreTestConsumer {112  void performTest(const Decl *D) override {113    StoreManager &SManager = Eng.getStoreManager();114    SValBuilder &Builder = Eng.getSValBuilder();115    MemRegionManager &MRManager = SManager.getRegionManager();116    ASTContext &ASTCtxt = Eng.getContext();117 118    using namespace ast_matchers;119 120    const auto *CL = findNode<CompoundLiteralExpr>(D, compoundLiteralExpr());121 122    const StackFrameContext *SFC =123        Eng.getAnalysisDeclContextManager().getStackFrame(D);124 125    QualType Int = ASTCtxt.IntTy;126 127    // Get region for 'test'128    const SubRegion *CLRegion = MRManager.getCompoundLiteralRegion(CL, SFC);129 130    // Get value for 'test[0]'131    NonLoc Zero = Builder.makeIntVal(0, false);132    loc::MemRegionVal ZeroElement(133        MRManager.getElementRegion(ASTCtxt.IntTy, Zero, CLRegion, ASTCtxt));134 135    Store StInit = SManager.getInitialStore(SFC).getStore();136    // Let's bind constant 1 to 'test[0]'137    SVal One = Builder.makeIntVal(1, Int);138    Store StX =139        SManager.Bind(StInit, ZeroElement, One).ResultingStore.getStore();140 141    // And make sure that we can read this binding back as it was142    EXPECT_EQ(One, SManager.getBinding(StX, ZeroElement, Int));143  }144 145public:146  using StoreTestConsumer::StoreTestConsumer;147};148 149TEST(Store, LiteralCompound) {150  EXPECT_TRUE(tooling::runToolOnCode(151      std::make_unique<TestAction<LiteralCompoundConsumer>>(),152      "void foo() { int *test = (int[]){ 1, 2, 3 }; }", "input.c"));153}154 155} // namespace156} // namespace ento157} // namespace clang158