Fix memcpy-operator= generation with restrict parameters. (#194906)

The below issue (and #63884) both report that we reject (and also
assert, because the memcpy failed) the memcpy we're generating for a
restrict field of a type with an implicit copy constructor.

First, we shouldn't be rejecting it this late, IF we wanted to reject it
(I contend we do not), we should do it at the same time we reject
const-members/make this a deleted operator. Second, of course we
shouldn't fail.

This patch NOW works by just having us skip the premature 'memcpy'
optimization here. In the end, the memcpy is generally skipped by
`CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr` in the example
(as this is a trivial type), but this reverts it to using a 'for' loop
for restrict, as it does for const, and volatile qualified values.

We perhaps might think about doing this for address-spaces/ptr-auth, but
at the moment, this fixes restrict version.

Fixes: #37979
This commit is contained in:
Erich Keane
2026-04-30 07:42:57 -07:00
committed by GitHub
parent fc77aa9f72
commit 8b7dd15ad1
3 changed files with 18 additions and 1 deletions

View File

@@ -571,6 +571,7 @@ Bug Fixes to C++ Support
conforming and could lead to recursive constraint satisfaction checking. (#GH149443)
- Fixed a crash in Itanium C++ name mangling for a lambda in a local class field initializer inside a constructor/destructor. (#GH176395)
- Fixed crashes in Itanium C++ name mangling for lambdas with trailing requires-clauses involving requires-expressions. (#GH100774) (#GH123854)
- Fixed an invalid rejection and assertion failure while generating ``operator=`` for fields with the ``__restrict`` qualifier. (#GH37979)
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@@ -15180,7 +15180,7 @@ buildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
const ExprBuilder &To, const ExprBuilder &From,
bool CopyingBaseSubobject, bool Copying) {
// Maybe we should use a memcpy?
if (T->isArrayType() && !T.isConstQualified() && !T.isVolatileQualified() &&
if (T->isArrayType() && !T.hasQualifiers() &&
T.isTriviallyCopyableType(S.Context))
return buildMemcpyForAssignmentOp(S, Loc, T, To, From);

View File

@@ -0,0 +1,16 @@
// RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s
// RUN: %clang_cc1 -fsyntax-only -ast-dump %s | FileCheck %s
// expected-no-diagnostics
struct Obj { int * __restrict myPtr[2]; };
void do_copy() {
Obj a, b;
a = b;
// CHECK-LABEL: CXXMethodDecl{{.*}} implicit used constexpr operator= 'Obj &(const Obj &) noexcept'
// CHECK-NEXT: ParmVarDecl
// CHECK-NEXT: CompoundStmt
// Make sure that this uses the for-loop in the AST rather than trying to do
// the early builtin_memcpy opt.
// CHECK-NEXT: ForStmt
}