[clang] [clang][dataflow] Copy records relative to the destination type for c… (PR #160557)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 24 09:53:53 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-analysis
Author: Samira Bakon (bazuzi)
<details>
<summary>Changes</summary>
…opy/move assignments.
This mirrors the handling of copy/move constructors.
Also fix a couple capitalizations of variables in an adjacent and related test.
---
Full diff: https://github.com/llvm/llvm-project/pull/160557.diff
2 Files Affected:
- (modified) clang/lib/Analysis/FlowSensitive/Transfer.cpp (+6-1)
- (modified) clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (+30-3)
``````````diff
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");
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/160557
More information about the cfe-commits
mailing list