[clang] [clang][dataflow] Copy records relative to the destination type for c… (PR #160557)

Samira Bakon via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 24 11:05:04 PDT 2025


https://github.com/bazuzi updated https://github.com/llvm/llvm-project/pull/160557

>From e1f30ab5e9699f8bf476c89320e52350c76dffee Mon Sep 17 00:00:00 2001
From: Samira Bakon <bazuzi at google.com>
Date: Wed, 24 Sep 2025 12:46:15 -0400
Subject: [PATCH 1/2] [clang][dataflow] Copy records relative to the
 destination type for copy/move assignments.

This mirrors the handling of copy/move constructors.
---
 clang/lib/Analysis/FlowSensitive/Transfer.cpp |  7 +++-
 .../Analysis/FlowSensitive/TransferTest.cpp   | 33 +++++++++++++++++--
 2 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
index 60371d9498c25..f59bd6555aff5 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 destination 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");
 }

>From b3a5a0cb79ee3fbed312afd19ea770b9e7eb16bd Mon Sep 17 00:00:00 2001
From: Samira Bakon <bazuzi at google.com>
Date: Wed, 24 Sep 2025 14:04:52 -0400
Subject: [PATCH 2/2] Fix comment

---
 clang/lib/Analysis/FlowSensitive/Transfer.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
index f59bd6555aff5..06f12784aa82d 100644
--- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -658,10 +658,10 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
         return;
 
       // If the destination object here is of a derived class, `Arg0` may be a
-      // cast of that object to a base class, and the destination 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`.
+      // 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



More information about the cfe-commits mailing list