Skip to content

Commit f95aaca

Browse files
authored
[clang][dataflow] Copy records relative to the destination type for c… (llvm#160557)
…opy/move assignments. This mirrors the handling of copy/move constructors. Also fix a couple capitalizations of variables in an adjacent and related test.
1 parent 89eeecd commit f95aaca

File tree

2 files changed

+36
-4
lines changed

2 files changed

+36
-4
lines changed

clang/lib/Analysis/FlowSensitive/Transfer.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,12 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
657657
if (LocSrc == nullptr || LocDst == nullptr)
658658
return;
659659

660-
copyRecord(*LocSrc, *LocDst, Env);
660+
// If the destination object here is of a derived class, `Arg0` may be a
661+
// cast of that object to a base class, and the source object may be of a
662+
// sibling derived class. To handle these cases, ensure we are copying
663+
// only the fields for `Arg0`'s type, not the type of the underlying
664+
// `RecordStorageLocation`.
665+
copyRecord(*LocSrc, *LocDst, Env, Arg0->getType());
661666

662667
// The assignment operator can have an arbitrary return type. We model the
663668
// return value only if the return type is the same as or a base class of

clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1554,8 +1554,8 @@ TEST(TransferTest, BaseClassInitializerFromSiblingDerivedInstance) {
15541554
struct DerivedTwo : public Base {
15551555
int DerivedTwoField;
15561556
1557-
DerivedTwo(const DerivedOne& d1)
1558-
: Base(d1), DerivedTwoField(d1.DerivedOneField) {
1557+
DerivedTwo(const DerivedOne& D1)
1558+
: Base(D1), DerivedTwoField(D1.DerivedOneField) {
15591559
(void)BaseField;
15601560
}
15611561
};
@@ -1565,7 +1565,34 @@ TEST(TransferTest, BaseClassInitializerFromSiblingDerivedInstance) {
15651565
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
15661566
ASTContext &ASTCtx) {
15671567
// Regression test only; we used to crash when transferring the base
1568-
// class initializer from the DerivedToBase-cast `d1`.
1568+
// class initializer from the DerivedToBase-cast `D1`.
1569+
},
1570+
LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "DerivedTwo");
1571+
}
1572+
1573+
TEST(TransferTest, CopyAssignmentToDerivedToBase) {
1574+
std::string Code = R"cc(
1575+
struct Base {};
1576+
1577+
struct DerivedOne : public Base {
1578+
int DerivedOneField;
1579+
};
1580+
1581+
struct DerivedTwo : public Base {
1582+
int DerivedTwoField;
1583+
1584+
explicit DerivedTwo(const DerivedOne& D1) {
1585+
*static_cast<Base*>(this) = D1;
1586+
}
1587+
};
1588+
)cc";
1589+
1590+
runDataflow(
1591+
Code,
1592+
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1593+
ASTContext &ASTCtx) {
1594+
// Regression test only; we used to crash when transferring the copy
1595+
// assignment operator in the constructor for `DerivedTwo`.
15691596
},
15701597
LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "DerivedTwo");
15711598
}

0 commit comments

Comments
 (0)