StoreTest.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  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-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "Reusables.h"
  9. #include "clang/Tooling/Tooling.h"
  10. #include "gtest/gtest.h"
  11. namespace clang {
  12. namespace ento {
  13. namespace {
  14. // Test that we can put a value into an int-type variable and load it
  15. // back from that variable. Test what happens if default bindings are used.
  16. class VariableBindConsumer : public ExprEngineConsumer {
  17. void performTest(const Decl *D) {
  18. StoreManager &StMgr = Eng.getStoreManager();
  19. SValBuilder &SVB = Eng.getSValBuilder();
  20. MemRegionManager &MRMgr = StMgr.getRegionManager();
  21. const ASTContext &ACtx = Eng.getContext();
  22. const auto *VDX0 = findDeclByName<VarDecl>(D, "x0");
  23. const auto *VDY0 = findDeclByName<VarDecl>(D, "y0");
  24. const auto *VDZ0 = findDeclByName<VarDecl>(D, "z0");
  25. const auto *VDX1 = findDeclByName<VarDecl>(D, "x1");
  26. const auto *VDY1 = findDeclByName<VarDecl>(D, "y1");
  27. assert(VDX0 && VDY0 && VDZ0 && VDX1 && VDY1);
  28. const StackFrameContext *SFC =
  29. Eng.getAnalysisDeclContextManager().getStackFrame(D);
  30. Loc LX0 = loc::MemRegionVal(MRMgr.getVarRegion(VDX0, SFC));
  31. Loc LY0 = loc::MemRegionVal(MRMgr.getVarRegion(VDY0, SFC));
  32. Loc LZ0 = loc::MemRegionVal(MRMgr.getVarRegion(VDZ0, SFC));
  33. Loc LX1 = loc::MemRegionVal(MRMgr.getVarRegion(VDX1, SFC));
  34. Loc LY1 = loc::MemRegionVal(MRMgr.getVarRegion(VDY1, SFC));
  35. Store StInit = StMgr.getInitialStore(SFC).getStore();
  36. SVal Zero = SVB.makeZeroVal(ACtx.IntTy);
  37. SVal One = SVB.makeIntVal(1, ACtx.IntTy);
  38. SVal NarrowZero = SVB.makeZeroVal(ACtx.CharTy);
  39. // Bind(Zero)
  40. Store StX0 =
  41. StMgr.Bind(StInit, LX0, Zero).getStore();
  42. ASSERT_EQ(Zero, StMgr.getBinding(StX0, LX0, ACtx.IntTy));
  43. // BindDefaultInitial(Zero)
  44. Store StY0 =
  45. StMgr.BindDefaultInitial(StInit, LY0.getAsRegion(), Zero).getStore();
  46. ASSERT_EQ(Zero, StMgr.getBinding(StY0, LY0, ACtx.IntTy));
  47. ASSERT_EQ(Zero, *StMgr.getDefaultBinding(StY0, LY0.getAsRegion()));
  48. // BindDefaultZero()
  49. Store StZ0 =
  50. StMgr.BindDefaultZero(StInit, LZ0.getAsRegion()).getStore();
  51. // BindDefaultZero wipes the region with '0 S8b', not with out Zero.
  52. // Direct load, however, does give us back the object of the type
  53. // that we specify for loading.
  54. ASSERT_EQ(Zero, StMgr.getBinding(StZ0, LZ0, ACtx.IntTy));
  55. ASSERT_EQ(NarrowZero, *StMgr.getDefaultBinding(StZ0, LZ0.getAsRegion()));
  56. // Bind(One)
  57. Store StX1 =
  58. StMgr.Bind(StInit, LX1, One).getStore();
  59. ASSERT_EQ(One, StMgr.getBinding(StX1, LX1, ACtx.IntTy));
  60. // BindDefaultInitial(One)
  61. Store StY1 =
  62. StMgr.BindDefaultInitial(StInit, LY1.getAsRegion(), One).getStore();
  63. ASSERT_EQ(One, StMgr.getBinding(StY1, LY1, ACtx.IntTy));
  64. ASSERT_EQ(One, *StMgr.getDefaultBinding(StY1, LY1.getAsRegion()));
  65. }
  66. public:
  67. VariableBindConsumer(CompilerInstance &C) : ExprEngineConsumer(C) {}
  68. bool HandleTopLevelDecl(DeclGroupRef DG) override {
  69. for (const auto *D : DG)
  70. performTest(D);
  71. return true;
  72. }
  73. };
  74. class VariableBindAction : public ASTFrontendAction {
  75. public:
  76. std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
  77. StringRef File) override {
  78. return std::make_unique<VariableBindConsumer>(Compiler);
  79. }
  80. };
  81. TEST(Store, VariableBind) {
  82. EXPECT_TRUE(tooling::runToolOnCode(std::make_unique<VariableBindAction>(),
  83. "void foo() { int x0, y0, z0, x1, y1; }"));
  84. }
  85. } // namespace
  86. } // namespace ento
  87. } // namespace clang