Author: Samira Bakon Date: 2025-09-24T18:28:13Z New Revision: f95aacaf0465925e508d019b47efcb635428d049
URL: https://github.com/llvm/llvm-project/commit/f95aacaf0465925e508d019b47efcb635428d049 DIFF: https://github.com/llvm/llvm-project/commit/f95aacaf0465925e508d019b47efcb635428d049.diff LOG: [clang][dataflow] Copy records relative to the destination type for c… (#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. Added: Modified: clang/lib/Analysis/FlowSensitive/Transfer.cpp clang/unittests/Analysis/FlowSensitive/TransferTest.cpp Removed: ################################################################################ diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index 60371d9498c25..06f12784aa82d 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -657,7 +657,12 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> { if (LocSrc == nullptr || LocDst == nullptr) return; - copyRecord(*LocSrc, *LocDst, Env); + // If the destination object here is of a derived class, `Arg0` may be a + // cast of that object to a base class, and the source object may be of a + // sibling derived class. To handle these cases, ensure we are copying + // only the fields for `Arg0`'s type, not the type of the underlying + // `RecordStorageLocation`. + copyRecord(*LocSrc, *LocDst, Env, Arg0->getType()); // The assignment operator can have an arbitrary return type. We model the // return value only if the return type is the same as or a base class of diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index d97e2b0c2425a..cbd55966a3d88 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -1554,8 +1554,8 @@ TEST(TransferTest, BaseClassInitializerFromSiblingDerivedInstance) { struct DerivedTwo : public Base { int DerivedTwoField; - DerivedTwo(const DerivedOne& d1) - : Base(d1), DerivedTwoField(d1.DerivedOneField) { + DerivedTwo(const DerivedOne& D1) + : Base(D1), DerivedTwoField(D1.DerivedOneField) { (void)BaseField; } }; @@ -1565,7 +1565,34 @@ TEST(TransferTest, BaseClassInitializerFromSiblingDerivedInstance) { [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, ASTContext &ASTCtx) { // Regression test only; we used to crash when transferring the base - // class initializer from the DerivedToBase-cast `d1`. + // class initializer from the DerivedToBase-cast `D1`. + }, + LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "DerivedTwo"); +} + +TEST(TransferTest, CopyAssignmentToDerivedToBase) { + std::string Code = R"cc( + struct Base {}; + +struct DerivedOne : public Base { + int DerivedOneField; +}; + +struct DerivedTwo : public Base { + int DerivedTwoField; + + explicit DerivedTwo(const DerivedOne& D1) { + *static_cast<Base*>(this) = D1; + } +}; +)cc"; + + runDataflow( + Code, + [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, + ASTContext &ASTCtx) { + // Regression test only; we used to crash when transferring the copy + // assignment operator in the constructor for `DerivedTwo`. }, LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "DerivedTwo"); } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
