https://github.com/MitalAshok updated 
https://github.com/llvm/llvm-project/pull/90725

>From 0793795ba7d5d5974b1403cd6ead0221fc20c5bb Mon Sep 17 00:00:00 2001
From: Mital Ashok <mi...@mitalashok.co.uk>
Date: Wed, 1 May 2024 12:45:54 +0100
Subject: [PATCH 1/2] [Clang] Ensure "=default"ed function can be deleted when
 used as an extension in C++03

Fixes #90605
---
 clang/lib/Sema/SemaDeclCXX.cpp                |  4 ++-
 .../SemaCXX/cxx0x-cursory-default-delete.cpp  | 34 +++++++++++++++++--
 .../SemaCXX/cxx0x-defaulted-functions.cpp     | 13 +++++++
 3 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 157d42c09cfcd8..e3c90c8ee1d644 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -9767,7 +9767,9 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD,
     return false;
   CXXRecordDecl *RD = MD->getParent();
   assert(!RD->isDependentType() && "do deletion after instantiation");
-  if (!LangOpts.CPlusPlus || (!LangOpts.CPlusPlus11 && !RD->isLambda()) ||
+  if (!LangOpts.CPlusPlus ||
+      (!LangOpts.CPlusPlus11 && !RD->isLambda() &&
+       !MD->isExplicitlyDefaulted()) ||
       RD->isInvalidDecl())
     return false;
 
diff --git a/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp 
b/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp
index 6ae146f0d08c7d..f884725a234671 100644
--- a/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp
+++ b/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp
@@ -1,4 +1,11 @@
 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++03 -Wno-c++11-extensions -fsyntax-only -verify %s
+
+#if __cplusplus < 201103L
+#define static_assert _Static_assert
+#define nullptr 0
+#define noexcept throw()
+#endif
 
 struct non_copiable {
   non_copiable(const non_copiable&) = delete; // expected-note {{marked 
deleted here}}
@@ -25,10 +32,12 @@ void fn1 () {
   non_const_copy ncc;
   non_const_copy ncc2 = ncc;
   ncc = ncc2;
+#if __cplusplus >= 201103L
   const non_const_copy cncc{};
+#endif
   const non_const_copy cncc1; // expected-error {{default initialization of an 
object of const type 'const non_const_copy' without a user-provided default 
constructor}}
-  non_const_copy ncc3 = cncc; // expected-error {{no matching}}
-  ncc = cncc; // expected-error {{no viable overloaded}}
+  non_const_copy ncc3 = cncc1; // expected-error {{no matching}}
+  ncc = cncc1; // expected-error {{no viable overloaded}}
 };
 
 struct no_fields { };
@@ -196,7 +205,7 @@ struct except_spec_d_match : except_spec_a, except_spec_b {
 struct S { S(); };
 S::S() __attribute((noreturn)) = default;
 
-using size_t = decltype(sizeof(0));
+using size_t = __SIZE_TYPE__;
 void *operator new(size_t) = delete; // expected-error {{deleted definition 
must be first declaration}} expected-note {{implicit}}
 void operator delete(void *) noexcept = delete; // expected-error {{deleted 
definition must be first declaration}} expected-note {{implicit}}
 
@@ -217,3 +226,22 @@ namespace deleted_overrides_deleted {
   template<typename T> struct B : A { virtual void f() = delete; };
   template struct B<int>;
 }
+
+namespace GH90605 {
+struct Element {
+    Element& operator=(const Element&) = delete; // #GH90605-Element-assign
+};
+
+struct S {
+    Element i; // #GH90605-i
+
+    S& operator=(const S&) = default;
+// expected-warning@-1 {{explicitly defaulted copy assignment operator is 
implicitly deleted}}
+//   expected-note@#GH90605-i {{copy assignment operator of 'S' is implicitly 
deleted because field 'i' has a deleted copy assignment operator}}
+//   expected-note@#GH90605-Element-assign {{'operator=' has been explicitly 
marked deleted here}}
+//   expected-note@-4 {{replace 'default' with 'delete'}}
+};
+
+static_assert(!__is_trivially_assignable(S&, const S&), "");
+static_assert(!__is_assignable(S&, const S&), "");
+}
diff --git a/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp 
b/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
index 0c3dd1ea7aa274..30d54920a1a686 100644
--- a/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
+++ b/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
@@ -1,4 +1,9 @@
 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -fcxx-exceptions 
-Wno-deprecated-builtins %s
+// RUN: %clang_cc1 -std=c++03 -Wno-c++11-extensions -fsyntax-only -verify 
-fcxx-exceptions -Wno-deprecated-builtins %s
+
+#if __cplusplus < 201103L
+#define static_assert _Static_assert
+#endif
 
 void fn() = default; // expected-error {{only special member}}
 struct foo {
@@ -43,6 +48,7 @@ void tester() {
   b = c;
 }
 
+#if __cplusplus >= 201103L
 template<typename T> struct S : T {
   constexpr S() = default;         // expected-note {{previous declaration is 
here}}
   constexpr S(const S&) = default; // expected-note {{previous declaration is 
here}}
@@ -118,6 +124,7 @@ namespace DefaultedFnExceptionSpec {
     *p = *p; // expected-note {{instantiation of}}
   }
 }
+#endif
 
 namespace PR13527 {
   struct X {
@@ -135,6 +142,7 @@ namespace PR13527 {
   X &X::operator=(X&&) = default; // expected-error {{redefinition}}
   X::~X() = default; // expected-error {{redefinition}}
 
+#if __cplusplus >= 201103L
   struct Y {
     Y() = default;
     Y(const Y&) = default;
@@ -149,6 +157,7 @@ namespace PR13527 {
   Y &Y::operator=(const Y&) noexcept = default; // expected-error {{definition 
of explicitly defaulted}}
   Y &Y::operator=(Y&&) noexcept = default; // expected-error {{definition of 
explicitly defaulted}}
   Y::~Y() = default; // expected-error {{definition of explicitly defaulted}}
+#endif
 }
 
 namespace PR27699 {
@@ -185,6 +194,7 @@ extern "C" { // expected-note {{extern "C" language linkage 
specification begins
  void PR13573(const _Tp&) = delete;
 }
 
+#if __cplusplus >= 201103L
 namespace PR15597 {
   template<typename T> struct A {
     A() noexcept(true) = default;
@@ -197,6 +207,7 @@ namespace PR15597 {
   A<int> a;
   B<int> b;
 }
+#endif
 
 namespace PR27941 {
 struct ExplicitBool {
@@ -245,6 +256,7 @@ E<Type>::E(const int&) {}  // expected-error {{definition 
of explicitly defaulte
 
 }
 
+#if __cplusplus >= 201103L
 namespace P1286R2 {
   struct X {
     X();
@@ -286,3 +298,4 @@ struct B {
   auto operator = (RM<B>) -> RV<B> = delete;
 };
 }
+#endif

>From cb60e46f60debd6e7bd3f3665326fd0bf6103b3d Mon Sep 17 00:00:00 2001
From: Mital Ashok <mi...@mitalashok.co.uk>
Date: Wed, 1 May 2024 15:50:24 +0100
Subject: [PATCH 2/2] Change some tests' expected messages

Now that `= default` will be deleted when ill-formed when used as an extension
---
 clang/test/CXX/drs/dr16xx.cpp                 | 70 ++++++-------------
 clang/test/CXX/drs/dr21xx.cpp                 | 14 ++--
 .../SemaCXX/cxx0x-cursory-default-delete.cpp  |  2 +-
 3 files changed, 25 insertions(+), 61 deletions(-)

diff --git a/clang/test/CXX/drs/dr16xx.cpp b/clang/test/CXX/drs/dr16xx.cpp
index cf6b45ceabf2cc..ed59e456770e07 100644
--- a/clang/test/CXX/drs/dr16xx.cpp
+++ b/clang/test/CXX/drs/dr16xx.cpp
@@ -192,36 +192,24 @@ namespace cwg1658 { // cwg1658: 5
     struct E : A { E(); virtual void foo() = 0; }; // #cwg1658-E1
     E::E() = default; // #cwg1658-E1-ctor
     // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}}
-    // cxx98-error@-2 {{base class 'A' has private default constructor}}
-    //   cxx98-note@-3 {{in defaulted default constructor for 
'cwg1658::DefCtor::E' first required here}}
-    //   cxx98-note@#cwg1658-A1 {{implicitly declared private here}}
-    // since-cxx11-error@#cwg1658-E1-ctor {{defaulting this default 
constructor would delete it after its first declaration}}
-    //   since-cxx11-note@#cwg1658-E1 {{default constructor of 'E' is 
implicitly deleted because base class 'A' has an inaccessible default 
constructor}}
+    // expected-error@#cwg1658-E1-ctor {{defaulting this default constructor 
would delete it after its first declaration}}
+    //   expected-note@#cwg1658-E1 {{default constructor of 'E' is implicitly 
deleted because base class 'A' has an inaccessible default constructor}}
     struct F : virtual A { F(); }; // #cwg1658-F1
     F::F() = default; // #cwg1658-F1-ctor
     // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}}
-    // cxx98-error@-2 {{inherited virtual base class 'A' has private default 
constructor}}
-    //   cxx98-note@-3 {{in defaulted default constructor for 
'cwg1658::DefCtor::F' first required here}}
-    //   cxx98-note@#cwg1658-A1 {{implicitly declared private here}}
-    // since-cxx11-error@#cwg1658-F1-ctor {{defaulting this default 
constructor would delete it after its first declaration}}
-    //   since-cxx11-note@#cwg1658-F1 {{default constructor of 'F' is 
implicitly deleted because base class 'A' has an inaccessible default 
constructor}}
+    // expected-error@#cwg1658-F1-ctor {{defaulting this default constructor 
would delete it after its first declaration}}
+    //   expected-note@#cwg1658-F1 {{default constructor of 'F' is implicitly 
deleted because base class 'A' has an inaccessible default constructor}}
 
     struct G : B { G(); virtual void foo() = 0; }; // #cwg1658-G1
     G::G() = default; // #cwg1658-G1-ctor
     // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}}
-    // cxx98-error@#cwg1658-G1 {{base class 'B' has private destructor}}
-    //   cxx98-note@#cwg1658-G1-ctor {{in defaulted default constructor for 
'cwg1658::DefCtor::G' first required here}}
-    //   cxx98-note@#cwg1658-B1 {{implicitly declared private here}}
-    // since-cxx11-error@#cwg1658-G1-ctor {{defaulting this default 
constructor would delete it after its first declaration}}
-    //   since-cxx11-note@#cwg1658-G1 {{default constructor of 'G' is 
implicitly deleted because base class 'B' has an inaccessible destructor}}
+    // expected-error@#cwg1658-G1-ctor {{defaulting this default constructor 
would delete it after its first declaration}}
+    //   expected-note@#cwg1658-G1 {{default constructor of 'G' is implicitly 
deleted because base class 'B' has an inaccessible destructor}}
     struct H : virtual B { H(); }; // #cwg1658-H1
     H::H() = default; // #cwg1658-H1-ctor
     // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}}
-    // cxx98-error@#cwg1658-H1 {{base class 'B' has private destructor}}
-    //   cxx98-note@#cwg1658-H1-ctor {{in defaulted default constructor for 
'cwg1658::DefCtor::H' first required here}}
-    //   cxx98-note@#cwg1658-B1 {{implicitly declared private here}}
-    // since-cxx11-error@#cwg1658-H1-ctor {{defaulting this default 
constructor would delete it after its first declaration}}
-    //   since-cxx11-note@#cwg1658-H1 {{default constructor of 'H' is 
implicitly deleted because base class 'B' has an inaccessible destructor}}
+    // expected-error@#cwg1658-H1-ctor {{defaulting this default constructor 
would delete it after its first declaration}}
+    //   expected-note@#cwg1658-H1 {{default constructor of 'H' is implicitly 
deleted because base class 'B' has an inaccessible destructor}}
   }
 
   namespace Dtor {
@@ -234,19 +222,13 @@ namespace cwg1658 { // cwg1658: 5
     struct G : B { ~G(); virtual void foo() = 0; }; // #cwg1658-G2
     G::~G() = default; // #cwg1658-G2-dtor
     // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}}
-    // cxx98-error@#cwg1658-G2 {{base class 'B' has private destructor}}
-    //   cxx98-note@#cwg1658-G2-dtor {{in defaulted destructor for 
'cwg1658::Dtor::G' first required here}}
-    //   cxx98-note@#cwg1658-B2 {{implicitly declared private here}}
-    // since-cxx11-error@#cwg1658-G2-dtor {{defaulting this destructor would 
delete it after its first declaration}}
-    //   since-cxx11-note@#cwg1658-G2 {{destructor of 'G' is implicitly 
deleted because base class 'B' has an inaccessible destructor}}
+    // expected-error@#cwg1658-G2-dtor {{defaulting this destructor would 
delete it after its first declaration}}
+    //   expected-note@#cwg1658-G2 {{destructor of 'G' is implicitly deleted 
because base class 'B' has an inaccessible destructor}}
     struct H : virtual B { ~H(); }; // #cwg1658-H2
     H::~H() = default; // #cwg1658-H2-dtor
     // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}}
-    // cxx98-error@#cwg1658-H2 {{base class 'B' has private destructor}}
-    //   cxx98-note@#cwg1658-H2-dtor {{in defaulted destructor for 
'cwg1658::Dtor::H' first required here}}
-    //   cxx98-note@#cwg1658-B2 {{implicitly declared private here}}
-    // since-cxx11-error@#cwg1658-H2-dtor {{defaulting this destructor would 
delete it after its first declaration}}
-    //   since-cxx11-note@#cwg1658-H2 {{destructor of 'H' is implicitly 
deleted because base class 'B' has an inaccessible destructor}}
+    // expected-error@#cwg1658-H2-dtor {{defaulting this destructor would 
delete it after its first declaration}}
+    //   expected-note@#cwg1658-H2 {{destructor of 'H' is implicitly deleted 
because base class 'B' has an inaccessible destructor}}
   }
 
   namespace MemInit {
@@ -291,36 +273,24 @@ namespace cwg1658 { // cwg1658: 5
     // cxx98-error@-1 {{rvalue references are a C++11 extension}}
     E::E(const E&) = default; // #cwg1658-E5-copy-ctor
     // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}}
-    // cxx98-error@-2 {{base class 'A' has private copy constructor}}
-    //   cxx98-note@-3 {{in defaulted copy constructor for 
'cwg1658::CopyCtor::E' first required here}}
-    //   cxx98-note@#cwg1658-A5 {{implicitly declared private here}}
-    // since-cxx11-error@#cwg1658-E5-copy-ctor {{defaulting this copy 
constructor would delete it after its first declaration}}
-    //   since-cxx11-note@#cwg1658-E5 {{copy constructor of 'E' is implicitly 
deleted because base class 'A' has an inaccessible copy constructor}}
+    // expected-error@#cwg1658-E5-copy-ctor {{defaulting this copy constructor 
would delete it after its first declaration}}
+    //   expected-note@#cwg1658-E5 {{copy constructor of 'E' is implicitly 
deleted because base class 'A' has an inaccessible copy constructor}}
     E::E(E&&) = default; // #cwg1658-E5-move-ctor
     // cxx98-error@-1 {{rvalue references are a C++11 extension}}
     // cxx98-error@-2 {{defaulted function definitions are a C++11 extension}}
-    // cxx98-error@-3 {{base class 'A' has private move constructor}}
-    //   cxx98-note@-4 {{in defaulted move constructor for 
'cwg1658::CopyCtor::E' first required here}}
-    //   cxx98-note@#cwg1658-A5 {{implicitly declared private here}}
-    // since-cxx11-error@#cwg1658-E5-move-ctor {{defaulting this move 
constructor would delete it after its first declaration}}
-    //   since-cxx11-note@#cwg1658-E5 {{move constructor of 'E' is implicitly 
deleted because base class 'A' has an inaccessible move constructor}}
+    // expected-error@#cwg1658-E5-move-ctor {{defaulting this move constructor 
would delete it after its first declaration}}
+    //   expected-note@#cwg1658-E5 {{move constructor of 'E' is implicitly 
deleted because base class 'A' has an inaccessible move constructor}}
     struct F : virtual A { F(const F&); F(F&&); }; // #cwg1658-F5
     // cxx98-error@-1 {{rvalue references are a C++11 extension}}
     F::F(const F&) = default; // #cwg1658-F5-copy-ctor
     // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}}
-    // cxx98-error@-2 {{inherited virtual base class 'A' has private copy 
constructor}}
-    //   cxx98-note@-3 {{in defaulted copy constructor for 
'cwg1658::CopyCtor::F' first required here}}
-    //   cxx98-note@#cwg1658-A5 {{implicitly declared private here}}
-    // since-cxx11-error@#cwg1658-F5-copy-ctor {{defaulting this copy 
constructor would delete it after its first declaration}}
-    //   since-cxx11-note@#cwg1658-F5 {{copy constructor of 'F' is implicitly 
deleted because base class 'A' has an inaccessible copy constructor}}
+    // expected-error@#cwg1658-F5-copy-ctor {{defaulting this copy constructor 
would delete it after its first declaration}}
+    //   expected-note@#cwg1658-F5 {{copy constructor of 'F' is implicitly 
deleted because base class 'A' has an inaccessible copy constructor}}
     F::F(F&&) = default; // #cwg1658-F5-move-ctor
     // cxx98-error@-1 {{rvalue references are a C++11 extension}}
     // cxx98-error@-2 {{defaulted function definitions are a C++11 extension}}
-    // cxx98-error@-3 {{inherited virtual base class 'A' has private move 
constructor}}
-    //   cxx98-note@-4 {{in defaulted move constructor for 
'cwg1658::CopyCtor::F' first required here}}
-    //   cxx98-note@#cwg1658-A5 {{implicitly declared private here}}
-    // since-cxx11-error@#cwg1658-F5-move-ctor {{defaulting this move 
constructor would delete it after its first declaration}}
-    //   since-cxx11-note@#cwg1658-F5 {{move constructor of 'F' is implicitly 
deleted because base class 'A' has an inaccessible move constructor}}
+    // expected-error@#cwg1658-F5-move-ctor {{defaulting this move constructor 
would delete it after its first declaration}}
+    //   expected-note@#cwg1658-F5 {{move constructor of 'F' is implicitly 
deleted because base class 'A' has an inaccessible move constructor}}
   }
 
   // assignment case is superseded by cwg2180
diff --git a/clang/test/CXX/drs/dr21xx.cpp b/clang/test/CXX/drs/dr21xx.cpp
index 082deb42e4fa09..84086ea2f21b73 100644
--- a/clang/test/CXX/drs/dr21xx.cpp
+++ b/clang/test/CXX/drs/dr21xx.cpp
@@ -246,19 +246,13 @@ namespace cwg2180 { // cwg2180: yes
   };
   B &B::operator=(const B&) = default; // #cwg2180-B-copy
   // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}}
-  // cxx98-error@-2 {{'operator=' is a private member of 'cwg2180::A'}}
-  //   cxx98-note@-3 {{in defaulted copy assignment operator for 'cwg2180::B' 
first required here}}
-  //   cxx98-note@#cwg2180-A-copy {{implicitly declared private here}}
-  // since-cxx11-error@#cwg2180-B-copy {{defaulting this copy assignment 
operator would delete it after its first declaration}}
-  //   since-cxx11-note@#cwg2180-B {{copy assignment operator of 'B' is 
implicitly deleted because base class 'A' has an inaccessible copy assignment 
operator}}
+  // expected-error@#cwg2180-B-copy {{defaulting this copy assignment operator 
would delete it after its first declaration}}
+  //   expected-note@#cwg2180-B {{copy assignment operator of 'B' is 
implicitly deleted because base class 'A' has an inaccessible copy assignment 
operator}}
   B &B::operator=(B&&) = default; // #cwg2180-B-move
   // cxx98-error@-1 {{rvalue references are a C++11 extension}}
   // cxx98-error@-2 {{defaulted function definitions are a C++11 extension}}
-  // cxx98-error@-3 {{'operator=' is a private member of 'cwg2180::A'}}
-  //   cxx98-note@-4 {{in defaulted move assignment operator for 'cwg2180::B' 
first required here}}
-  //   cxx98-note@#cwg2180-A-move {{implicitly declared private here}}
-  // since-cxx11-error@#cwg2180-B-move {{defaulting this move assignment 
operator would delete it after its first declaration}}
-  //   since-cxx11-note@#cwg2180-B {{move assignment operator of 'B' is 
implicitly deleted because base class 'A' has an inaccessible move assignment 
operator}}
+  // expected-error@#cwg2180-B-move {{defaulting this move assignment operator 
would delete it after its first declaration}}
+  //   expected-note@#cwg2180-B {{move assignment operator of 'B' is 
implicitly deleted because base class 'A' has an inaccessible move assignment 
operator}}
 }
 
 namespace cwg2199 { // cwg2199: 3.8
diff --git a/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp 
b/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp
index f884725a234671..313a4253641ae1 100644
--- a/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp
+++ b/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp
@@ -2,7 +2,7 @@
 // RUN: %clang_cc1 -std=c++03 -Wno-c++11-extensions -fsyntax-only -verify %s
 
 #if __cplusplus < 201103L
-#define static_assert _Static_assert
+#define static_assert __extension__ _Static_assert
 #define nullptr 0
 #define noexcept throw()
 #endif

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to