================
@@ -901,6 +901,33 @@ void 
CIRGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &args) {
   assert(!cir::MissingFeatures::incrementProfileCounter());
   assert(!cir::MissingFeatures::runCleanupsScope());
 
+  // For a memcpy-equivalent special member (a union, or a trivially-copyable
+  // record) the synthesized body either copies nothing -- a union body is just
+  // `return *this` -- or relies on a memcpy the AST does not spell out as
+  // field assignments.  Mirror classic CodeGen's AssignmentMemcpyizer: copy
+  // the whole object once, then fall through to emit the trailing
+  // `return *this`.  Emitting the copy but skipping the return would leave the
+  // result reference uninitialized.
+  if (assignOp->isMemcpyEquivalentSpecialMember(getContext())) {
+    CanQualType recordTy =
+        getContext().getCanonicalTagType(assignOp->getParent());
+    LValue dest = makeNaturalAlignAddrLValue(loadCXXThis(), recordTy);
+    // The source is the trailing reference parameter; load it to get the
+    // referent's address before copying (mirrors the copy-constructor path).
+    mlir::Value srcPtr = builder.createLoad(getLoc(assignOp->getLocation()),
+                                            getAddrOfLocalVar(args.back()));
+    LValue src = makeNaturalAlignAddrLValue(srcPtr, recordTy);
+    emitAggregateAssign(dest, src, recordTy);
+
+    for (Stmt *s : rootCS->body())
+      if (isa<ReturnStmt>(s))
+        if (emitStmt(s, /*useCurrentScope=*/true).failed())
+          cgm.errorNYI(s->getSourceRange(),
+                       std::string("emitImplicitAssignmentOperatorBody: ") +
+                           s->getStmtClassName());
----------------
andykaylor wrote:

I thought the whole point of this change was that the AST didn't contain the 
necessary expressions. For example, for the union test case, I'm seeing this:

```
| |-CXXMethodDecl <line:1:7> col:7 implicit used constexpr operator= 'YYSTYPE 
&(const YYSTYPE &) noexcept' inline default trivial external-linkage
| | |-ParmVarDecl <col:7> col:7 'const YYSTYPE &'
| | `-CompoundStmt <col:7>
| |   `-ReturnStmt <col:7>
| |     `-UnaryOperator <col:7> 'YYSTYPE' lvalue prefix '*' cannot overflow
| |       `-CXXThisExpr <col:7> 'YYSTYPE *' this
```
What I'm wondering is whether the real fix for this should be in the AST rather 
than in CIR codegen. I do see that the array case you added contains a builtin 
memcpy call, but that just reinforces my belief that the union case should have 
a more complete body in the AST. The fact that we're assuming that an aggregate 
copy is needed in all cases and ignoring something the AST provided in a subset 
of those cases just seems entirely wrong.

https://github.com/llvm/llvm-project/pull/198918
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to