@@ -1635,7 +1635,58 @@ bool SetThreeWayComparisonField(InterpState &S, CodePtr OpPC,
1635
1635
return true ;
1636
1636
}
1637
1637
1638
- bool DoMemcpy (InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest) {
1638
+ static bool copyComposite (InterpState &S, CodePtr OpPC, const Pointer &Src,
1639
+ Pointer &Dest, bool Activate);
1640
+ static bool copyRecord (InterpState &S, CodePtr OpPC, const Pointer &Src,
1641
+ Pointer &Dest, bool Activate = false ) {
1642
+ [[maybe_unused]] const Descriptor *SrcDesc = Src.getFieldDesc ();
1643
+ const Descriptor *DestDesc = Dest.getFieldDesc ();
1644
+
1645
+ auto copyField = [&](const Record::Field &F, bool Activate) -> bool {
1646
+ Pointer DestField = Dest.atField (F.Offset );
1647
+ if (std::optional<PrimType> FT = S.Ctx .classify (F.Decl ->getType ())) {
1648
+ TYPE_SWITCH (*FT, {
1649
+ DestField.deref <T>() = Src.atField (F.Offset ).deref <T>();
1650
+ if (Src.atField (F.Offset ).isInitialized ())
1651
+ DestField.initialize ();
1652
+ if (Activate)
1653
+ DestField.activate ();
1654
+ });
1655
+ return true ;
1656
+ }
1657
+ // Composite field.
1658
+ return copyComposite (S, OpPC, Src.atField (F.Offset ), DestField, Activate);
1659
+ };
1660
+
1661
+ assert (SrcDesc->isRecord ());
1662
+ assert (SrcDesc->ElemRecord == DestDesc->ElemRecord );
1663
+ const Record *R = DestDesc->ElemRecord ;
1664
+ for (const Record::Field &F : R->fields ()) {
1665
+ if (R->isUnion ()) {
1666
+ // For unions, only copy the active field.
1667
+ const Pointer &SrcField = Src.atField (F.Offset );
1668
+ if (SrcField.isActive ()) {
1669
+ if (!copyField (F, /* Activate=*/ true ))
1670
+ return false ;
1671
+ }
1672
+ } else {
1673
+ if (!copyField (F, Activate))
1674
+ return false ;
1675
+ }
1676
+ }
1677
+
1678
+ for (const Record::Base &B : R->bases ()) {
1679
+ Pointer DestBase = Dest.atField (B.Offset );
1680
+ if (!copyRecord (S, OpPC, Src.atField (B.Offset ), DestBase, Activate))
1681
+ return false ;
1682
+ }
1683
+
1684
+ Dest.initialize ();
1685
+ return true ;
1686
+ }
1687
+
1688
+ static bool copyComposite (InterpState &S, CodePtr OpPC, const Pointer &Src,
1689
+ Pointer &Dest, bool Activate = false ) {
1639
1690
assert (Src.isLive () && Dest.isLive ());
1640
1691
1641
1692
[[maybe_unused]] const Descriptor *SrcDesc = Src.getFieldDesc ();
@@ -1657,44 +1708,14 @@ bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest) {
1657
1708
return true ;
1658
1709
}
1659
1710
1660
- if (DestDesc->isRecord ()) {
1661
- auto copyField = [&](const Record::Field &F, bool Activate) -> bool {
1662
- Pointer DestField = Dest.atField (F.Offset );
1663
- if (std::optional<PrimType> FT = S.Ctx .classify (F.Decl ->getType ())) {
1664
- TYPE_SWITCH (*FT, {
1665
- DestField.deref <T>() = Src.atField (F.Offset ).deref <T>();
1666
- DestField.initialize ();
1667
- if (Activate)
1668
- DestField.activate ();
1669
- });
1670
- return true ;
1671
- }
1672
- return Invalid (S, OpPC);
1673
- };
1674
-
1675
- assert (SrcDesc->isRecord ());
1676
- assert (SrcDesc->ElemRecord == DestDesc->ElemRecord );
1677
- const Record *R = DestDesc->ElemRecord ;
1678
- for (const Record::Field &F : R->fields ()) {
1679
- if (R->isUnion ()) {
1680
- // For unions, only copy the active field.
1681
- const Pointer &SrcField = Src.atField (F.Offset );
1682
- if (SrcField.isActive ()) {
1683
- if (!copyField (F, /* Activate=*/ true ))
1684
- return false ;
1685
- }
1686
- } else {
1687
- if (!copyField (F, /* Activate=*/ false ))
1688
- return false ;
1689
- }
1690
- }
1691
- return true ;
1692
- }
1693
-
1694
- // FIXME: Composite types.
1695
-
1711
+ if (DestDesc->isRecord ())
1712
+ return copyRecord (S, OpPC, Src, Dest, Activate);
1696
1713
return Invalid (S, OpPC);
1697
1714
}
1698
1715
1716
+ bool DoMemcpy (InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest) {
1717
+ return copyComposite (S, OpPC, Src, Dest);
1718
+ }
1719
+
1699
1720
} // namespace interp
1700
1721
} // namespace clang
0 commit comments