mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-15 12:39:19 +00:00
[clang][dataflow] Add transfer function for addrof
This is part of the implementation of the dataflow analysis framework. See "[RFC] A dataflow analysis framework for Clang AST" on cfe-dev. Reviewed-by: xazax.hun Differential Revision: https://reviews.llvm.org/D117496
This commit is contained in:
parent
541322540e
commit
59e031ff90
@ -174,19 +174,45 @@ public:
|
||||
}
|
||||
|
||||
void VisitUnaryOperator(const UnaryOperator *S) {
|
||||
if (S->getOpcode() == UO_Deref) {
|
||||
assert(S->getSubExpr() != nullptr);
|
||||
// The CFG does not contain `ParenExpr` as top-level statements in basic
|
||||
// blocks, however sub-expressions can still be of that type.
|
||||
assert(S->getSubExpr() != nullptr);
|
||||
const Expr *SubExpr = S->getSubExpr()->IgnoreParens();
|
||||
assert(SubExpr != nullptr);
|
||||
|
||||
switch (S->getOpcode()) {
|
||||
case UO_Deref: {
|
||||
const auto *SubExprVal = cast_or_null<PointerValue>(
|
||||
Env.getValue(*S->getSubExpr(), SkipPast::Reference));
|
||||
Env.getValue(*SubExpr, SkipPast::Reference));
|
||||
if (SubExprVal == nullptr)
|
||||
return;
|
||||
break;
|
||||
|
||||
auto &Loc = Env.createStorageLocation(*S);
|
||||
Env.setStorageLocation(*S, Loc);
|
||||
Env.setValue(Loc, Env.takeOwnership(std::make_unique<ReferenceValue>(
|
||||
SubExprVal->getPointeeLoc())));
|
||||
break;
|
||||
}
|
||||
case UO_AddrOf: {
|
||||
// Do not form a pointer to a reference. If `SubExpr` is assigned a
|
||||
// `ReferenceValue` then form a value that points to the location of its
|
||||
// pointee.
|
||||
StorageLocation *PointeeLoc =
|
||||
Env.getStorageLocation(*SubExpr, SkipPast::Reference);
|
||||
if (PointeeLoc == nullptr)
|
||||
break;
|
||||
|
||||
auto &PointerLoc = Env.createStorageLocation(*S);
|
||||
auto &PointerVal =
|
||||
Env.takeOwnership(std::make_unique<PointerValue>(*PointeeLoc));
|
||||
Env.setStorageLocation(*S, PointerLoc);
|
||||
Env.setValue(PointerLoc, PointerVal);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// FIXME: Add support for UO_LNot.
|
||||
break;
|
||||
}
|
||||
// FIXME: Add support for UO_AddrOf, UO_LNot.
|
||||
}
|
||||
|
||||
void VisitCXXThisExpr(const CXXThisExpr *S) {
|
||||
|
@ -1699,4 +1699,63 @@ TEST_F(TransferTest, StaticCast) {
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(TransferTest, AddrOfValue) {
|
||||
std::string Code = R"(
|
||||
void target() {
|
||||
int Foo;
|
||||
int *Bar = &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 ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
|
||||
ASSERT_THAT(BarDecl, NotNull());
|
||||
|
||||
const auto *FooLoc = cast<ScalarStorageLocation>(
|
||||
Env.getStorageLocation(*FooDecl, SkipPast::None));
|
||||
const auto *BarVal =
|
||||
cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
|
||||
EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(TransferTest, AddrOfReference) {
|
||||
std::string Code = R"(
|
||||
void target(int *Foo) {
|
||||
int *Bar = &(*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 ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
|
||||
ASSERT_THAT(BarDecl, NotNull());
|
||||
|
||||
const auto *FooVal =
|
||||
cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None));
|
||||
const auto *BarVal =
|
||||
cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
|
||||
EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
Loading…
x
Reference in New Issue
Block a user