forked from OSchip/llvm-project
Revert "[clang][dataflow] Add support for global storage values"
This reverts commit 7ea103de14
.
This commit is contained in:
parent
5a74e6a21c
commit
169e1aba55
|
@ -49,11 +49,6 @@ enum class SkipPast {
|
|||
};
|
||||
|
||||
/// Holds the state of the program (store and heap) at a given program point.
|
||||
///
|
||||
/// WARNING: Symbolic values that are created by the environment for static
|
||||
/// local and global variables are not currently invalidated on function calls.
|
||||
/// This is unsound and should be taken into account when designing dataflow
|
||||
/// analyses.
|
||||
class Environment {
|
||||
public:
|
||||
/// Supplements `Environment` with non-standard comparison and join
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
|
@ -57,55 +56,10 @@ static bool equivalentValues(QualType Type, Value *Val1, Value *Val2,
|
|||
return Model.compareEquivalent(Type, *Val1, *Val2);
|
||||
}
|
||||
|
||||
/// Initializes a global storage value.
|
||||
static void initGlobalVar(const VarDecl &D, Environment &Env) {
|
||||
if (!D.hasGlobalStorage() ||
|
||||
Env.getStorageLocation(D, SkipPast::None) != nullptr)
|
||||
return;
|
||||
|
||||
auto &Loc = Env.createStorageLocation(D);
|
||||
Env.setStorageLocation(D, Loc);
|
||||
if (auto *Val = Env.createValue(D.getType()))
|
||||
Env.setValue(Loc, *Val);
|
||||
}
|
||||
|
||||
/// Initializes a global storage value.
|
||||
static void initGlobalVar(const Decl &D, Environment &Env) {
|
||||
if (auto *V = dyn_cast<VarDecl>(&D))
|
||||
initGlobalVar(*V, Env);
|
||||
}
|
||||
|
||||
/// Initializes global storage values that are declared or referenced from
|
||||
/// sub-statements of `S`.
|
||||
// FIXME: Add support for resetting globals after function calls to enable
|
||||
// the implementation of sound analyses.
|
||||
static void initGlobalVars(const Stmt &S, Environment &Env) {
|
||||
for (auto *Child : S.children()) {
|
||||
if (Child != nullptr)
|
||||
initGlobalVars(*Child, Env);
|
||||
}
|
||||
|
||||
if (auto *DS = dyn_cast<DeclStmt>(&S)) {
|
||||
if (DS->isSingleDecl()) {
|
||||
const auto &D = *cast<VarDecl>(DS->getSingleDecl());
|
||||
initGlobalVar(D, Env);
|
||||
} else {
|
||||
for (auto *D : DS->getDeclGroup())
|
||||
initGlobalVar(*D, Env);
|
||||
}
|
||||
} else if (auto *E = dyn_cast<DeclRefExpr>(&S)) {
|
||||
initGlobalVar(*E->getDecl(), Env);
|
||||
} else if (auto *E = dyn_cast<MemberExpr>(&S)) {
|
||||
initGlobalVar(*E->getMemberDecl(), Env);
|
||||
}
|
||||
}
|
||||
|
||||
Environment::Environment(DataflowAnalysisContext &DACtx,
|
||||
const DeclContext &DeclCtx)
|
||||
: Environment(DACtx) {
|
||||
if (const auto *FuncDecl = dyn_cast<FunctionDecl>(&DeclCtx)) {
|
||||
assert(FuncDecl->getBody() != nullptr);
|
||||
initGlobalVars(*FuncDecl->getBody(), *this);
|
||||
for (const auto *ParamDecl : FuncDecl->parameters()) {
|
||||
assert(ParamDecl != nullptr);
|
||||
auto &ParamLoc = createStorageLocation(*ParamDecl);
|
||||
|
|
|
@ -136,11 +136,6 @@ public:
|
|||
// Group decls are converted into single decls in the CFG so the cast below
|
||||
// is safe.
|
||||
const auto &D = *cast<VarDecl>(S->getSingleDecl());
|
||||
|
||||
// Static local vars are already initialized in `Environment`.
|
||||
if (D.hasGlobalStorage())
|
||||
return;
|
||||
|
||||
auto &Loc = Env.createStorageLocation(D);
|
||||
Env.setStorageLocation(D, Loc);
|
||||
|
||||
|
@ -296,24 +291,6 @@ public:
|
|||
if (Member->isFunctionOrFunctionTemplate())
|
||||
return;
|
||||
|
||||
if (auto *D = dyn_cast<VarDecl>(Member)) {
|
||||
if (D->hasGlobalStorage()) {
|
||||
auto *VarDeclLoc = Env.getStorageLocation(*D, SkipPast::None);
|
||||
if (VarDeclLoc == nullptr)
|
||||
return;
|
||||
|
||||
if (VarDeclLoc->getType()->isReferenceType()) {
|
||||
Env.setStorageLocation(*S, *VarDeclLoc);
|
||||
} else {
|
||||
auto &Loc = Env.createStorageLocation(*S);
|
||||
Env.setStorageLocation(*S, Loc);
|
||||
Env.setValue(Loc, Env.takeOwnership(
|
||||
std::make_unique<ReferenceValue>(*VarDeclLoc)));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// The receiver can be either a value or a pointer to a value. Skip past the
|
||||
// indirection to handle both cases.
|
||||
auto *BaseLoc = cast_or_null<AggregateStorageLocation>(
|
||||
|
|
|
@ -2153,171 +2153,4 @@ TEST_F(TransferTest, AssignFromBoolNegation) {
|
|||
});
|
||||
}
|
||||
|
||||
TEST_F(TransferTest, StaticIntSingleVarDecl) {
|
||||
std::string Code = R"(
|
||||
void target() {
|
||||
static int Foo;
|
||||
// [[p]]
|
||||
}
|
||||
)";
|
||||
runDataflow(Code,
|
||||
[](llvm::ArrayRef<
|
||||
std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
|
||||
Results,
|
||||
ASTContext &ASTCtx) {
|
||||
ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
|
||||
const Environment &Env = Results[0].second.Env;
|
||||
|
||||
const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
|
||||
ASSERT_THAT(FooDecl, NotNull());
|
||||
|
||||
const StorageLocation *FooLoc =
|
||||
Env.getStorageLocation(*FooDecl, SkipPast::None);
|
||||
ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
|
||||
|
||||
const Value *FooVal = Env.getValue(*FooLoc);
|
||||
EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(TransferTest, StaticIntGroupVarDecl) {
|
||||
std::string Code = R"(
|
||||
void target() {
|
||||
static int Foo, Bar;
|
||||
(void)0;
|
||||
// [[p]]
|
||||
}
|
||||
)";
|
||||
runDataflow(Code,
|
||||
[](llvm::ArrayRef<
|
||||
std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
|
||||
Results,
|
||||
ASTContext &ASTCtx) {
|
||||
ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
|
||||
const Environment &Env = Results[0].second.Env;
|
||||
|
||||
const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
|
||||
ASSERT_THAT(FooDecl, NotNull());
|
||||
|
||||
const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
|
||||
ASSERT_THAT(BarDecl, NotNull());
|
||||
|
||||
const StorageLocation *FooLoc =
|
||||
Env.getStorageLocation(*FooDecl, SkipPast::None);
|
||||
ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
|
||||
|
||||
const StorageLocation *BarLoc =
|
||||
Env.getStorageLocation(*BarDecl, SkipPast::None);
|
||||
ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
|
||||
|
||||
const Value *FooVal = Env.getValue(*FooLoc);
|
||||
EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
|
||||
|
||||
const Value *BarVal = Env.getValue(*BarLoc);
|
||||
EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
|
||||
|
||||
EXPECT_NE(FooVal, BarVal);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(TransferTest, GlobalIntVarDecl) {
|
||||
std::string Code = R"(
|
||||
static int Foo;
|
||||
|
||||
void target() {
|
||||
int Bar = Foo;
|
||||
int Baz = Foo;
|
||||
// [[p]]
|
||||
}
|
||||
)";
|
||||
runDataflow(Code,
|
||||
[](llvm::ArrayRef<
|
||||
std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
|
||||
Results,
|
||||
ASTContext &ASTCtx) {
|
||||
ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
|
||||
const Environment &Env = Results[0].second.Env;
|
||||
|
||||
const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
|
||||
ASSERT_THAT(BarDecl, NotNull());
|
||||
|
||||
const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
|
||||
ASSERT_THAT(BazDecl, NotNull());
|
||||
|
||||
const Value *BarVal =
|
||||
cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
|
||||
const Value *BazVal =
|
||||
cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
|
||||
EXPECT_EQ(BarVal, BazVal);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(TransferTest, StaticMemberIntVarDecl) {
|
||||
std::string Code = R"(
|
||||
struct A {
|
||||
static int Foo;
|
||||
};
|
||||
|
||||
void target(A a) {
|
||||
int Bar = a.Foo;
|
||||
int Baz = a.Foo;
|
||||
// [[p]]
|
||||
}
|
||||
)";
|
||||
runDataflow(Code,
|
||||
[](llvm::ArrayRef<
|
||||
std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
|
||||
Results,
|
||||
ASTContext &ASTCtx) {
|
||||
ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
|
||||
const Environment &Env = Results[0].second.Env;
|
||||
|
||||
const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
|
||||
ASSERT_THAT(BarDecl, NotNull());
|
||||
|
||||
const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
|
||||
ASSERT_THAT(BazDecl, NotNull());
|
||||
|
||||
const Value *BarVal =
|
||||
cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
|
||||
const Value *BazVal =
|
||||
cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
|
||||
EXPECT_EQ(BarVal, BazVal);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(TransferTest, StaticMemberRefVarDecl) {
|
||||
std::string Code = R"(
|
||||
struct A {
|
||||
static int &Foo;
|
||||
};
|
||||
|
||||
void target(A a) {
|
||||
int Bar = a.Foo;
|
||||
int Baz = a.Foo;
|
||||
// [[p]]
|
||||
}
|
||||
)";
|
||||
runDataflow(Code,
|
||||
[](llvm::ArrayRef<
|
||||
std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
|
||||
Results,
|
||||
ASTContext &ASTCtx) {
|
||||
ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
|
||||
const Environment &Env = Results[0].second.Env;
|
||||
|
||||
const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
|
||||
ASSERT_THAT(BarDecl, NotNull());
|
||||
|
||||
const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
|
||||
ASSERT_THAT(BazDecl, NotNull());
|
||||
|
||||
const Value *BarVal =
|
||||
cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
|
||||
const Value *BazVal =
|
||||
cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
|
||||
EXPECT_EQ(BarVal, BazVal);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
Loading…
Reference in New Issue