Skip to content

Commit 0793795

Browse files
committed
[Clang] Ensure "=default"ed function can be deleted when used as an extension in C++03
Fixes #90605
1 parent 803e03f commit 0793795

File tree

3 files changed

+47
-4
lines changed

3 files changed

+47
-4
lines changed

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9767,7 +9767,9 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD,
97679767
return false;
97689768
CXXRecordDecl *RD = MD->getParent();
97699769
assert(!RD->isDependentType() && "do deletion after instantiation");
9770-
if (!LangOpts.CPlusPlus || (!LangOpts.CPlusPlus11 && !RD->isLambda()) ||
9770+
if (!LangOpts.CPlusPlus ||
9771+
(!LangOpts.CPlusPlus11 && !RD->isLambda() &&
9772+
!MD->isExplicitlyDefaulted()) ||
97719773
RD->isInvalidDecl())
97729774
return false;
97739775

clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
2+
// RUN: %clang_cc1 -std=c++03 -Wno-c++11-extensions -fsyntax-only -verify %s
3+
4+
#if __cplusplus < 201103L
5+
#define static_assert _Static_assert
6+
#define nullptr 0
7+
#define noexcept throw()
8+
#endif
29

310
struct non_copiable {
411
non_copiable(const non_copiable&) = delete; // expected-note {{marked deleted here}}
@@ -25,10 +32,12 @@ void fn1 () {
2532
non_const_copy ncc;
2633
non_const_copy ncc2 = ncc;
2734
ncc = ncc2;
35+
#if __cplusplus >= 201103L
2836
const non_const_copy cncc{};
37+
#endif
2938
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}}
30-
non_const_copy ncc3 = cncc; // expected-error {{no matching}}
31-
ncc = cncc; // expected-error {{no viable overloaded}}
39+
non_const_copy ncc3 = cncc1; // expected-error {{no matching}}
40+
ncc = cncc1; // expected-error {{no viable overloaded}}
3241
};
3342

3443
struct no_fields { };
@@ -196,7 +205,7 @@ struct except_spec_d_match : except_spec_a, except_spec_b {
196205
struct S { S(); };
197206
S::S() __attribute((noreturn)) = default;
198207

199-
using size_t = decltype(sizeof(0));
208+
using size_t = __SIZE_TYPE__;
200209
void *operator new(size_t) = delete; // expected-error {{deleted definition must be first declaration}} expected-note {{implicit}}
201210
void operator delete(void *) noexcept = delete; // expected-error {{deleted definition must be first declaration}} expected-note {{implicit}}
202211

@@ -217,3 +226,22 @@ namespace deleted_overrides_deleted {
217226
template<typename T> struct B : A { virtual void f() = delete; };
218227
template struct B<int>;
219228
}
229+
230+
namespace GH90605 {
231+
struct Element {
232+
Element& operator=(const Element&) = delete; // #GH90605-Element-assign
233+
};
234+
235+
struct S {
236+
Element i; // #GH90605-i
237+
238+
S& operator=(const S&) = default;
239+
// expected-warning@-1 {{explicitly defaulted copy assignment operator is implicitly deleted}}
240+
// expected-note@#GH90605-i {{copy assignment operator of 'S' is implicitly deleted because field 'i' has a deleted copy assignment operator}}
241+
// expected-note@#GH90605-Element-assign {{'operator=' has been explicitly marked deleted here}}
242+
// expected-note@-4 {{replace 'default' with 'delete'}}
243+
};
244+
245+
static_assert(!__is_trivially_assignable(S&, const S&), "");
246+
static_assert(!__is_assignable(S&, const S&), "");
247+
}

clang/test/SemaCXX/cxx0x-defaulted-functions.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -fcxx-exceptions -Wno-deprecated-builtins %s
2+
// RUN: %clang_cc1 -std=c++03 -Wno-c++11-extensions -fsyntax-only -verify -fcxx-exceptions -Wno-deprecated-builtins %s
3+
4+
#if __cplusplus < 201103L
5+
#define static_assert _Static_assert
6+
#endif
27

38
void fn() = default; // expected-error {{only special member}}
49
struct foo {
@@ -43,6 +48,7 @@ void tester() {
4348
b = c;
4449
}
4550

51+
#if __cplusplus >= 201103L
4652
template<typename T> struct S : T {
4753
constexpr S() = default; // expected-note {{previous declaration is here}}
4854
constexpr S(const S&) = default; // expected-note {{previous declaration is here}}
@@ -118,6 +124,7 @@ namespace DefaultedFnExceptionSpec {
118124
*p = *p; // expected-note {{instantiation of}}
119125
}
120126
}
127+
#endif
121128

122129
namespace PR13527 {
123130
struct X {
@@ -135,6 +142,7 @@ namespace PR13527 {
135142
X &X::operator=(X&&) = default; // expected-error {{redefinition}}
136143
X::~X() = default; // expected-error {{redefinition}}
137144

145+
#if __cplusplus >= 201103L
138146
struct Y {
139147
Y() = default;
140148
Y(const Y&) = default;
@@ -149,6 +157,7 @@ namespace PR13527 {
149157
Y &Y::operator=(const Y&) noexcept = default; // expected-error {{definition of explicitly defaulted}}
150158
Y &Y::operator=(Y&&) noexcept = default; // expected-error {{definition of explicitly defaulted}}
151159
Y::~Y() = default; // expected-error {{definition of explicitly defaulted}}
160+
#endif
152161
}
153162

154163
namespace PR27699 {
@@ -185,6 +194,7 @@ extern "C" { // expected-note {{extern "C" language linkage specification begins
185194
void PR13573(const _Tp&) = delete;
186195
}
187196

197+
#if __cplusplus >= 201103L
188198
namespace PR15597 {
189199
template<typename T> struct A {
190200
A() noexcept(true) = default;
@@ -197,6 +207,7 @@ namespace PR15597 {
197207
A<int> a;
198208
B<int> b;
199209
}
210+
#endif
200211

201212
namespace PR27941 {
202213
struct ExplicitBool {
@@ -245,6 +256,7 @@ E<Type>::E(const int&) {} // expected-error {{definition of explicitly defaulte
245256

246257
}
247258

259+
#if __cplusplus >= 201103L
248260
namespace P1286R2 {
249261
struct X {
250262
X();
@@ -286,3 +298,4 @@ struct B {
286298
auto operator = (RM<B>) -> RV<B> = delete;
287299
};
288300
}
301+
#endif

0 commit comments

Comments
 (0)