[analyzer] Make default bindings to variables actually work.
Default RegionStore bindings represent values that can be obtained by loading
from anywhere within the region, not just the specific offset within the region
that they are said to be bound to. For example, default-binding a character \0
to an int (eg., via memset()) means that the whole int is 0, not just
that its lower byte is 0.
Even though memset and bzero were modeled this way, it didn't work correctly
when applied to simple variables. Eg., in
int x;
memset(x, 0, sizeof(x));
we did produce a default binding, but were unable to read it later, and 'x'
was perceived as an uninitialized variable even after memset.
At the same time, if we replace 'x' with a variable of a structure or array
type, accessing fields or elements of such variable was working correctly,
which was enough for most cases. So this was only a problem for variables of
simple integer/enumeration/floating-point/pointer types.
Fix loading default bindings from RegionStore for regions of simple variables.
Add a unit test to document the API contract as well.
Differential Revision: https://reviews.llvm.org/D60742
llvm-svn: 358722
2019-04-19 07:35:56 +08:00
|
|
|
//===- unittests/StaticAnalyzer/StoreTest.cpp -----------------------------===//
|
|
|
|
//
|
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "Reusables.h"
|
|
|
|
|
|
|
|
#include "clang/Tooling/Tooling.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
namespace ento {
|
|
|
|
namespace {
|
|
|
|
|
2020-04-28 17:21:39 +08:00
|
|
|
class StoreTestConsumer : public ExprEngineConsumer {
|
|
|
|
public:
|
|
|
|
StoreTestConsumer(CompilerInstance &C) : ExprEngineConsumer(C) {}
|
|
|
|
|
|
|
|
bool HandleTopLevelDecl(DeclGroupRef DG) override {
|
|
|
|
for (const auto *D : DG)
|
|
|
|
performTest(D);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
virtual void performTest(const Decl *D) = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class ConsumerTy> class TestAction : public ASTFrontendAction {
|
|
|
|
public:
|
|
|
|
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
|
|
|
|
StringRef File) override {
|
|
|
|
return std::make_unique<ConsumerTy>(Compiler);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
[analyzer] Make default bindings to variables actually work.
Default RegionStore bindings represent values that can be obtained by loading
from anywhere within the region, not just the specific offset within the region
that they are said to be bound to. For example, default-binding a character \0
to an int (eg., via memset()) means that the whole int is 0, not just
that its lower byte is 0.
Even though memset and bzero were modeled this way, it didn't work correctly
when applied to simple variables. Eg., in
int x;
memset(x, 0, sizeof(x));
we did produce a default binding, but were unable to read it later, and 'x'
was perceived as an uninitialized variable even after memset.
At the same time, if we replace 'x' with a variable of a structure or array
type, accessing fields or elements of such variable was working correctly,
which was enough for most cases. So this was only a problem for variables of
simple integer/enumeration/floating-point/pointer types.
Fix loading default bindings from RegionStore for regions of simple variables.
Add a unit test to document the API contract as well.
Differential Revision: https://reviews.llvm.org/D60742
llvm-svn: 358722
2019-04-19 07:35:56 +08:00
|
|
|
// Test that we can put a value into an int-type variable and load it
|
|
|
|
// back from that variable. Test what happens if default bindings are used.
|
2020-04-28 17:21:39 +08:00
|
|
|
class VariableBindConsumer : public StoreTestConsumer {
|
|
|
|
void performTest(const Decl *D) override {
|
|
|
|
StoreManager &SManager = Eng.getStoreManager();
|
|
|
|
SValBuilder &Builder = Eng.getSValBuilder();
|
|
|
|
MemRegionManager &MRManager = SManager.getRegionManager();
|
|
|
|
const ASTContext &ASTCtxt = Eng.getContext();
|
[analyzer] Make default bindings to variables actually work.
Default RegionStore bindings represent values that can be obtained by loading
from anywhere within the region, not just the specific offset within the region
that they are said to be bound to. For example, default-binding a character \0
to an int (eg., via memset()) means that the whole int is 0, not just
that its lower byte is 0.
Even though memset and bzero were modeled this way, it didn't work correctly
when applied to simple variables. Eg., in
int x;
memset(x, 0, sizeof(x));
we did produce a default binding, but were unable to read it later, and 'x'
was perceived as an uninitialized variable even after memset.
At the same time, if we replace 'x' with a variable of a structure or array
type, accessing fields or elements of such variable was working correctly,
which was enough for most cases. So this was only a problem for variables of
simple integer/enumeration/floating-point/pointer types.
Fix loading default bindings from RegionStore for regions of simple variables.
Add a unit test to document the API contract as well.
Differential Revision: https://reviews.llvm.org/D60742
llvm-svn: 358722
2019-04-19 07:35:56 +08:00
|
|
|
|
|
|
|
const auto *VDX0 = findDeclByName<VarDecl>(D, "x0");
|
|
|
|
const auto *VDY0 = findDeclByName<VarDecl>(D, "y0");
|
|
|
|
const auto *VDZ0 = findDeclByName<VarDecl>(D, "z0");
|
|
|
|
const auto *VDX1 = findDeclByName<VarDecl>(D, "x1");
|
|
|
|
const auto *VDY1 = findDeclByName<VarDecl>(D, "y1");
|
2020-04-28 17:21:39 +08:00
|
|
|
|
|
|
|
ASSERT_TRUE(VDX0 && VDY0 && VDZ0 && VDX1 && VDY1);
|
[analyzer] Make default bindings to variables actually work.
Default RegionStore bindings represent values that can be obtained by loading
from anywhere within the region, not just the specific offset within the region
that they are said to be bound to. For example, default-binding a character \0
to an int (eg., via memset()) means that the whole int is 0, not just
that its lower byte is 0.
Even though memset and bzero were modeled this way, it didn't work correctly
when applied to simple variables. Eg., in
int x;
memset(x, 0, sizeof(x));
we did produce a default binding, but were unable to read it later, and 'x'
was perceived as an uninitialized variable even after memset.
At the same time, if we replace 'x' with a variable of a structure or array
type, accessing fields or elements of such variable was working correctly,
which was enough for most cases. So this was only a problem for variables of
simple integer/enumeration/floating-point/pointer types.
Fix loading default bindings from RegionStore for regions of simple variables.
Add a unit test to document the API contract as well.
Differential Revision: https://reviews.llvm.org/D60742
llvm-svn: 358722
2019-04-19 07:35:56 +08:00
|
|
|
|
|
|
|
const StackFrameContext *SFC =
|
|
|
|
Eng.getAnalysisDeclContextManager().getStackFrame(D);
|
|
|
|
|
2020-04-28 17:21:39 +08:00
|
|
|
Loc LX0 = loc::MemRegionVal(MRManager.getVarRegion(VDX0, SFC));
|
|
|
|
Loc LY0 = loc::MemRegionVal(MRManager.getVarRegion(VDY0, SFC));
|
|
|
|
Loc LZ0 = loc::MemRegionVal(MRManager.getVarRegion(VDZ0, SFC));
|
|
|
|
Loc LX1 = loc::MemRegionVal(MRManager.getVarRegion(VDX1, SFC));
|
|
|
|
Loc LY1 = loc::MemRegionVal(MRManager.getVarRegion(VDY1, SFC));
|
[analyzer] Make default bindings to variables actually work.
Default RegionStore bindings represent values that can be obtained by loading
from anywhere within the region, not just the specific offset within the region
that they are said to be bound to. For example, default-binding a character \0
to an int (eg., via memset()) means that the whole int is 0, not just
that its lower byte is 0.
Even though memset and bzero were modeled this way, it didn't work correctly
when applied to simple variables. Eg., in
int x;
memset(x, 0, sizeof(x));
we did produce a default binding, but were unable to read it later, and 'x'
was perceived as an uninitialized variable even after memset.
At the same time, if we replace 'x' with a variable of a structure or array
type, accessing fields or elements of such variable was working correctly,
which was enough for most cases. So this was only a problem for variables of
simple integer/enumeration/floating-point/pointer types.
Fix loading default bindings from RegionStore for regions of simple variables.
Add a unit test to document the API contract as well.
Differential Revision: https://reviews.llvm.org/D60742
llvm-svn: 358722
2019-04-19 07:35:56 +08:00
|
|
|
|
2020-04-28 17:21:39 +08:00
|
|
|
Store StInit = SManager.getInitialStore(SFC).getStore();
|
|
|
|
SVal Zero = Builder.makeZeroVal(ASTCtxt.IntTy);
|
|
|
|
SVal One = Builder.makeIntVal(1, ASTCtxt.IntTy);
|
|
|
|
SVal NarrowZero = Builder.makeZeroVal(ASTCtxt.CharTy);
|
[analyzer] Make default bindings to variables actually work.
Default RegionStore bindings represent values that can be obtained by loading
from anywhere within the region, not just the specific offset within the region
that they are said to be bound to. For example, default-binding a character \0
to an int (eg., via memset()) means that the whole int is 0, not just
that its lower byte is 0.
Even though memset and bzero were modeled this way, it didn't work correctly
when applied to simple variables. Eg., in
int x;
memset(x, 0, sizeof(x));
we did produce a default binding, but were unable to read it later, and 'x'
was perceived as an uninitialized variable even after memset.
At the same time, if we replace 'x' with a variable of a structure or array
type, accessing fields or elements of such variable was working correctly,
which was enough for most cases. So this was only a problem for variables of
simple integer/enumeration/floating-point/pointer types.
Fix loading default bindings from RegionStore for regions of simple variables.
Add a unit test to document the API contract as well.
Differential Revision: https://reviews.llvm.org/D60742
llvm-svn: 358722
2019-04-19 07:35:56 +08:00
|
|
|
|
|
|
|
// Bind(Zero)
|
2020-04-28 17:21:39 +08:00
|
|
|
Store StX0 = SManager.Bind(StInit, LX0, Zero).getStore();
|
|
|
|
EXPECT_EQ(Zero, SManager.getBinding(StX0, LX0, ASTCtxt.IntTy));
|
[analyzer] Make default bindings to variables actually work.
Default RegionStore bindings represent values that can be obtained by loading
from anywhere within the region, not just the specific offset within the region
that they are said to be bound to. For example, default-binding a character \0
to an int (eg., via memset()) means that the whole int is 0, not just
that its lower byte is 0.
Even though memset and bzero were modeled this way, it didn't work correctly
when applied to simple variables. Eg., in
int x;
memset(x, 0, sizeof(x));
we did produce a default binding, but were unable to read it later, and 'x'
was perceived as an uninitialized variable even after memset.
At the same time, if we replace 'x' with a variable of a structure or array
type, accessing fields or elements of such variable was working correctly,
which was enough for most cases. So this was only a problem for variables of
simple integer/enumeration/floating-point/pointer types.
Fix loading default bindings from RegionStore for regions of simple variables.
Add a unit test to document the API contract as well.
Differential Revision: https://reviews.llvm.org/D60742
llvm-svn: 358722
2019-04-19 07:35:56 +08:00
|
|
|
|
|
|
|
// BindDefaultInitial(Zero)
|
|
|
|
Store StY0 =
|
2020-04-28 17:21:39 +08:00
|
|
|
SManager.BindDefaultInitial(StInit, LY0.getAsRegion(), Zero).getStore();
|
|
|
|
EXPECT_EQ(Zero, SManager.getBinding(StY0, LY0, ASTCtxt.IntTy));
|
|
|
|
EXPECT_EQ(Zero, *SManager.getDefaultBinding(StY0, LY0.getAsRegion()));
|
[analyzer] Make default bindings to variables actually work.
Default RegionStore bindings represent values that can be obtained by loading
from anywhere within the region, not just the specific offset within the region
that they are said to be bound to. For example, default-binding a character \0
to an int (eg., via memset()) means that the whole int is 0, not just
that its lower byte is 0.
Even though memset and bzero were modeled this way, it didn't work correctly
when applied to simple variables. Eg., in
int x;
memset(x, 0, sizeof(x));
we did produce a default binding, but were unable to read it later, and 'x'
was perceived as an uninitialized variable even after memset.
At the same time, if we replace 'x' with a variable of a structure or array
type, accessing fields or elements of such variable was working correctly,
which was enough for most cases. So this was only a problem for variables of
simple integer/enumeration/floating-point/pointer types.
Fix loading default bindings from RegionStore for regions of simple variables.
Add a unit test to document the API contract as well.
Differential Revision: https://reviews.llvm.org/D60742
llvm-svn: 358722
2019-04-19 07:35:56 +08:00
|
|
|
|
|
|
|
// BindDefaultZero()
|
2020-04-28 17:21:39 +08:00
|
|
|
Store StZ0 = SManager.BindDefaultZero(StInit, LZ0.getAsRegion()).getStore();
|
[analyzer] Make default bindings to variables actually work.
Default RegionStore bindings represent values that can be obtained by loading
from anywhere within the region, not just the specific offset within the region
that they are said to be bound to. For example, default-binding a character \0
to an int (eg., via memset()) means that the whole int is 0, not just
that its lower byte is 0.
Even though memset and bzero were modeled this way, it didn't work correctly
when applied to simple variables. Eg., in
int x;
memset(x, 0, sizeof(x));
we did produce a default binding, but were unable to read it later, and 'x'
was perceived as an uninitialized variable even after memset.
At the same time, if we replace 'x' with a variable of a structure or array
type, accessing fields or elements of such variable was working correctly,
which was enough for most cases. So this was only a problem for variables of
simple integer/enumeration/floating-point/pointer types.
Fix loading default bindings from RegionStore for regions of simple variables.
Add a unit test to document the API contract as well.
Differential Revision: https://reviews.llvm.org/D60742
llvm-svn: 358722
2019-04-19 07:35:56 +08:00
|
|
|
// BindDefaultZero wipes the region with '0 S8b', not with out Zero.
|
|
|
|
// Direct load, however, does give us back the object of the type
|
|
|
|
// that we specify for loading.
|
2020-04-28 17:21:39 +08:00
|
|
|
EXPECT_EQ(Zero, SManager.getBinding(StZ0, LZ0, ASTCtxt.IntTy));
|
|
|
|
EXPECT_EQ(NarrowZero, *SManager.getDefaultBinding(StZ0, LZ0.getAsRegion()));
|
[analyzer] Make default bindings to variables actually work.
Default RegionStore bindings represent values that can be obtained by loading
from anywhere within the region, not just the specific offset within the region
that they are said to be bound to. For example, default-binding a character \0
to an int (eg., via memset()) means that the whole int is 0, not just
that its lower byte is 0.
Even though memset and bzero were modeled this way, it didn't work correctly
when applied to simple variables. Eg., in
int x;
memset(x, 0, sizeof(x));
we did produce a default binding, but were unable to read it later, and 'x'
was perceived as an uninitialized variable even after memset.
At the same time, if we replace 'x' with a variable of a structure or array
type, accessing fields or elements of such variable was working correctly,
which was enough for most cases. So this was only a problem for variables of
simple integer/enumeration/floating-point/pointer types.
Fix loading default bindings from RegionStore for regions of simple variables.
Add a unit test to document the API contract as well.
Differential Revision: https://reviews.llvm.org/D60742
llvm-svn: 358722
2019-04-19 07:35:56 +08:00
|
|
|
|
|
|
|
// Bind(One)
|
2020-04-28 17:21:39 +08:00
|
|
|
Store StX1 = SManager.Bind(StInit, LX1, One).getStore();
|
|
|
|
EXPECT_EQ(One, SManager.getBinding(StX1, LX1, ASTCtxt.IntTy));
|
[analyzer] Make default bindings to variables actually work.
Default RegionStore bindings represent values that can be obtained by loading
from anywhere within the region, not just the specific offset within the region
that they are said to be bound to. For example, default-binding a character \0
to an int (eg., via memset()) means that the whole int is 0, not just
that its lower byte is 0.
Even though memset and bzero were modeled this way, it didn't work correctly
when applied to simple variables. Eg., in
int x;
memset(x, 0, sizeof(x));
we did produce a default binding, but were unable to read it later, and 'x'
was perceived as an uninitialized variable even after memset.
At the same time, if we replace 'x' with a variable of a structure or array
type, accessing fields or elements of such variable was working correctly,
which was enough for most cases. So this was only a problem for variables of
simple integer/enumeration/floating-point/pointer types.
Fix loading default bindings from RegionStore for regions of simple variables.
Add a unit test to document the API contract as well.
Differential Revision: https://reviews.llvm.org/D60742
llvm-svn: 358722
2019-04-19 07:35:56 +08:00
|
|
|
|
|
|
|
// BindDefaultInitial(One)
|
|
|
|
Store StY1 =
|
2020-04-28 17:21:39 +08:00
|
|
|
SManager.BindDefaultInitial(StInit, LY1.getAsRegion(), One).getStore();
|
|
|
|
EXPECT_EQ(One, SManager.getBinding(StY1, LY1, ASTCtxt.IntTy));
|
|
|
|
EXPECT_EQ(One, *SManager.getDefaultBinding(StY1, LY1.getAsRegion()));
|
[analyzer] Make default bindings to variables actually work.
Default RegionStore bindings represent values that can be obtained by loading
from anywhere within the region, not just the specific offset within the region
that they are said to be bound to. For example, default-binding a character \0
to an int (eg., via memset()) means that the whole int is 0, not just
that its lower byte is 0.
Even though memset and bzero were modeled this way, it didn't work correctly
when applied to simple variables. Eg., in
int x;
memset(x, 0, sizeof(x));
we did produce a default binding, but were unable to read it later, and 'x'
was perceived as an uninitialized variable even after memset.
At the same time, if we replace 'x' with a variable of a structure or array
type, accessing fields or elements of such variable was working correctly,
which was enough for most cases. So this was only a problem for variables of
simple integer/enumeration/floating-point/pointer types.
Fix loading default bindings from RegionStore for regions of simple variables.
Add a unit test to document the API contract as well.
Differential Revision: https://reviews.llvm.org/D60742
llvm-svn: 358722
2019-04-19 07:35:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
2020-04-28 17:21:39 +08:00
|
|
|
using StoreTestConsumer::StoreTestConsumer;
|
|
|
|
};
|
[analyzer] Make default bindings to variables actually work.
Default RegionStore bindings represent values that can be obtained by loading
from anywhere within the region, not just the specific offset within the region
that they are said to be bound to. For example, default-binding a character \0
to an int (eg., via memset()) means that the whole int is 0, not just
that its lower byte is 0.
Even though memset and bzero were modeled this way, it didn't work correctly
when applied to simple variables. Eg., in
int x;
memset(x, 0, sizeof(x));
we did produce a default binding, but were unable to read it later, and 'x'
was perceived as an uninitialized variable even after memset.
At the same time, if we replace 'x' with a variable of a structure or array
type, accessing fields or elements of such variable was working correctly,
which was enough for most cases. So this was only a problem for variables of
simple integer/enumeration/floating-point/pointer types.
Fix loading default bindings from RegionStore for regions of simple variables.
Add a unit test to document the API contract as well.
Differential Revision: https://reviews.llvm.org/D60742
llvm-svn: 358722
2019-04-19 07:35:56 +08:00
|
|
|
|
2020-04-28 17:21:39 +08:00
|
|
|
TEST(Store, VariableBind) {
|
|
|
|
EXPECT_TRUE(tooling::runToolOnCode(
|
|
|
|
std::make_unique<TestAction<VariableBindConsumer>>(),
|
|
|
|
"void foo() { int x0, y0, z0, x1, y1; }"));
|
|
|
|
}
|
|
|
|
|
|
|
|
class LiteralCompoundConsumer : public StoreTestConsumer {
|
|
|
|
void performTest(const Decl *D) override {
|
|
|
|
StoreManager &SManager = Eng.getStoreManager();
|
|
|
|
SValBuilder &Builder = Eng.getSValBuilder();
|
|
|
|
MemRegionManager &MRManager = SManager.getRegionManager();
|
|
|
|
ASTContext &ASTCtxt = Eng.getContext();
|
|
|
|
|
|
|
|
using namespace ast_matchers;
|
|
|
|
|
|
|
|
const auto *CL = findNode<CompoundLiteralExpr>(D, compoundLiteralExpr());
|
|
|
|
|
|
|
|
const StackFrameContext *SFC =
|
|
|
|
Eng.getAnalysisDeclContextManager().getStackFrame(D);
|
|
|
|
|
|
|
|
QualType Int = ASTCtxt.IntTy;
|
|
|
|
|
|
|
|
// Get region for 'test'
|
|
|
|
const SubRegion *CLRegion = MRManager.getCompoundLiteralRegion(CL, SFC);
|
|
|
|
|
|
|
|
// Get value for 'test[0]'
|
|
|
|
NonLoc Zero = Builder.makeIntVal(0, false);
|
|
|
|
loc::MemRegionVal ZeroElement(
|
|
|
|
MRManager.getElementRegion(ASTCtxt.IntTy, Zero, CLRegion, ASTCtxt));
|
|
|
|
|
|
|
|
Store StInit = SManager.getInitialStore(SFC).getStore();
|
|
|
|
// Let's bind constant 1 to 'test[0]'
|
|
|
|
SVal One = Builder.makeIntVal(1, Int);
|
|
|
|
Store StX = SManager.Bind(StInit, ZeroElement, One).getStore();
|
|
|
|
|
|
|
|
// And make sure that we can read this binding back as it was
|
|
|
|
EXPECT_EQ(One, SManager.getBinding(StX, ZeroElement, Int));
|
[analyzer] Make default bindings to variables actually work.
Default RegionStore bindings represent values that can be obtained by loading
from anywhere within the region, not just the specific offset within the region
that they are said to be bound to. For example, default-binding a character \0
to an int (eg., via memset()) means that the whole int is 0, not just
that its lower byte is 0.
Even though memset and bzero were modeled this way, it didn't work correctly
when applied to simple variables. Eg., in
int x;
memset(x, 0, sizeof(x));
we did produce a default binding, but were unable to read it later, and 'x'
was perceived as an uninitialized variable even after memset.
At the same time, if we replace 'x' with a variable of a structure or array
type, accessing fields or elements of such variable was working correctly,
which was enough for most cases. So this was only a problem for variables of
simple integer/enumeration/floating-point/pointer types.
Fix loading default bindings from RegionStore for regions of simple variables.
Add a unit test to document the API contract as well.
Differential Revision: https://reviews.llvm.org/D60742
llvm-svn: 358722
2019-04-19 07:35:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
2020-04-28 17:21:39 +08:00
|
|
|
using StoreTestConsumer::StoreTestConsumer;
|
[analyzer] Make default bindings to variables actually work.
Default RegionStore bindings represent values that can be obtained by loading
from anywhere within the region, not just the specific offset within the region
that they are said to be bound to. For example, default-binding a character \0
to an int (eg., via memset()) means that the whole int is 0, not just
that its lower byte is 0.
Even though memset and bzero were modeled this way, it didn't work correctly
when applied to simple variables. Eg., in
int x;
memset(x, 0, sizeof(x));
we did produce a default binding, but were unable to read it later, and 'x'
was perceived as an uninitialized variable even after memset.
At the same time, if we replace 'x' with a variable of a structure or array
type, accessing fields or elements of such variable was working correctly,
which was enough for most cases. So this was only a problem for variables of
simple integer/enumeration/floating-point/pointer types.
Fix loading default bindings from RegionStore for regions of simple variables.
Add a unit test to document the API contract as well.
Differential Revision: https://reviews.llvm.org/D60742
llvm-svn: 358722
2019-04-19 07:35:56 +08:00
|
|
|
};
|
|
|
|
|
2020-04-28 17:21:39 +08:00
|
|
|
TEST(Store, LiteralCompound) {
|
|
|
|
EXPECT_TRUE(tooling::runToolOnCode(
|
|
|
|
std::make_unique<TestAction<LiteralCompoundConsumer>>(),
|
|
|
|
"void foo() { int *test = (int[]){ 1, 2, 3 }; }", "input.c"));
|
[analyzer] Make default bindings to variables actually work.
Default RegionStore bindings represent values that can be obtained by loading
from anywhere within the region, not just the specific offset within the region
that they are said to be bound to. For example, default-binding a character \0
to an int (eg., via memset()) means that the whole int is 0, not just
that its lower byte is 0.
Even though memset and bzero were modeled this way, it didn't work correctly
when applied to simple variables. Eg., in
int x;
memset(x, 0, sizeof(x));
we did produce a default binding, but were unable to read it later, and 'x'
was perceived as an uninitialized variable even after memset.
At the same time, if we replace 'x' with a variable of a structure or array
type, accessing fields or elements of such variable was working correctly,
which was enough for most cases. So this was only a problem for variables of
simple integer/enumeration/floating-point/pointer types.
Fix loading default bindings from RegionStore for regions of simple variables.
Add a unit test to document the API contract as well.
Differential Revision: https://reviews.llvm.org/D60742
llvm-svn: 358722
2019-04-19 07:35:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
} // namespace ento
|
|
|
|
} // namespace clang
|