[clang] [Clang] Ensure "=default"ed function can be deleted when used as an extension in C++03 (PR #90725)
Mital Ashok via cfe-commits
cfe-commits at lists.llvm.org
Wed May 1 04:52:08 PDT 2024
https://github.com/MitalAshok created https://github.com/llvm/llvm-project/pull/90725
Fixes #90605
>From 0793795ba7d5d5974b1403cd6ead0221fc20c5bb Mon Sep 17 00:00:00 2001
From: Mital Ashok <mital at mitalashok.co.uk>
Date: Wed, 1 May 2024 12:45:54 +0100
Subject: [PATCH] [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 at -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 at -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
More information about the cfe-commits
mailing list