Skip to content

Commit f1226ee

Browse files
authored
[clang][dataflow] Consider CXXDefaultInitExpr to be an "original record ctor". (#78423)
The CFG doesn't contain a CFGElement for the `CXXDefaultInitExpr::getInit()`, so it makes sense to consider the `CXXDefaultInitExpr` to be the expression that originally constructs the object.
1 parent 1b1b525 commit f1226ee

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,7 @@ static bool isOriginalRecordConstructor(const Expr &RecordPRValue) {
747747
return !Init->isSemanticForm() || !Init->isTransparent();
748748
return isa<CXXConstructExpr>(RecordPRValue) || isa<CallExpr>(RecordPRValue) ||
749749
isa<LambdaExpr>(RecordPRValue) ||
750+
isa<CXXDefaultInitExpr>(RecordPRValue) ||
750751
// The framework currently does not propagate the objects created in
751752
// the two branches of a `ConditionalOperator` because there is no way
752753
// to reconcile their storage locations, which are different. We

clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2684,6 +2684,48 @@ TEST(TransferTest, ResultObjectLocation) {
26842684
});
26852685
}
26862686

2687+
TEST(TransferTest, ResultObjectLocationForDefaultInitExpr) {
2688+
std::string Code = R"(
2689+
struct S {};
2690+
struct target {
2691+
target () {
2692+
(void)0;
2693+
// [[p]]
2694+
}
2695+
S s = {};
2696+
};
2697+
)";
2698+
2699+
using ast_matchers::cxxCtorInitializer;
2700+
using ast_matchers::match;
2701+
using ast_matchers::selectFirst;
2702+
runDataflow(
2703+
Code,
2704+
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2705+
ASTContext &ASTCtx) {
2706+
const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2707+
2708+
const ValueDecl *SField = findValueDecl(ASTCtx, "s");
2709+
2710+
auto *CtorInit = selectFirst<CXXCtorInitializer>(
2711+
"ctor_initializer",
2712+
match(cxxCtorInitializer().bind("ctor_initializer"), ASTCtx));
2713+
ASSERT_NE(CtorInit, nullptr);
2714+
2715+
auto *DefaultInit = cast<CXXDefaultInitExpr>(CtorInit->getInit());
2716+
2717+
RecordStorageLocation &Loc = Env.getResultObjectLocation(*DefaultInit);
2718+
2719+
// FIXME: The result object location for the `CXXDefaultInitExpr` should
2720+
// be the location of the member variable being initialized, but we
2721+
// don't do this correctly yet; see also comments in
2722+
// `builtinTransferInitializer()`.
2723+
// For the time being, we just document the current erroneous behavior
2724+
// here (this should be `EXPECT_EQ` when the behavior is fixed).
2725+
EXPECT_NE(&Loc, Env.getThisPointeeStorageLocation()->getChild(*SField));
2726+
});
2727+
}
2728+
26872729
TEST(TransferTest, StaticCast) {
26882730
std::string Code = R"(
26892731
void target(int Foo) {

0 commit comments

Comments
 (0)