From 8b7dd15ad19c3bdcbf3a705f730160332816f7c1 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Thu, 30 Apr 2026 07:42:57 -0700 Subject: [PATCH] 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 --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/Sema/SemaDeclCXX.cpp | 2 +- clang/test/SemaCXX/GH37979.cpp | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 clang/test/SemaCXX/GH37979.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 84b8554db57b..c408196c3816 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -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 ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 159afdacdd11..2ff426622593 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -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); diff --git a/clang/test/SemaCXX/GH37979.cpp b/clang/test/SemaCXX/GH37979.cpp new file mode 100644 index 000000000000..526db3739cf8 --- /dev/null +++ b/clang/test/SemaCXX/GH37979.cpp @@ -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 +}