aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2010-06-30 00:51:29 +0000
committerJason Merrill <jason@redhat.com>2010-06-30 00:51:29 +0000
commit365a4a5d4fa754ee4b76b6f12bd226d39052d873 (patch)
tree9475890307f4ab29171a55ba449382044eb779cb
parent25c04b525a4a34c2308a679f7069c75ccf340831 (diff)
Enable implicitly deleted functions (N2346)
* class.c (check_bases_and_members): Adjust lambda flags. * method.c (implicitly_declare_fn): Set DECL_DELETED_FN if appropriate. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@161581 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog4
-rw-r--r--gcc/cp/class.c7
-rw-r--r--gcc/cp/method.c2
-rw-r--r--gcc/testsuite/ChangeLog19
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted17.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit1.C26
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit2.C33
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ctor-neg.C4
-rw-r--r--gcc/testsuite/g++.dg/ext/has_virtual_destructor.C6
-rw-r--r--gcc/testsuite/g++.dg/init/ctor4.C4
-rw-r--r--gcc/testsuite/g++.dg/init/synth2.C2
-rw-r--r--gcc/testsuite/g++.dg/lto/20081118_1.C1
-rw-r--r--gcc/testsuite/g++.dg/other/error13.C4
-rw-r--r--gcc/testsuite/g++.dg/other/unused1.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.bob/inherit2.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.bugs/900205_04.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.jason/opeq3.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.law/ctors17.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.oliva/delete1.C3
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/assign1.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/crash20.C5
21 files changed, 125 insertions, 29 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 9ac64c4b6a0..8c9b424f545 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,9 @@
2010-06-29 Jason Merrill <jason@redhat.com>
+ Enable implicitly deleted functions (N2346)
+ * class.c (check_bases_and_members): Adjust lambda flags.
+ * method.c (implicitly_declare_fn): Set DECL_DELETED_FN if appropriate.
+
* decl2.c (mark_used): Adjust error for use of deleted function.
Machinery to support implicit delete/move.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 6f6aab6d63f..031a4ea79c3 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -4563,10 +4563,9 @@ check_bases_and_members (tree t)
/* "The closure type associated with a lambda-expression has a deleted
default constructor and a deleted copy assignment operator." */
TYPE_NEEDS_CONSTRUCTING (t) = 1;
- TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 0;
- CLASSTYPE_LAZY_DEFAULT_CTOR (t) = 0;
- TYPE_HAS_COPY_ASSIGN (t) = 0;
- CLASSTYPE_LAZY_COPY_ASSIGN (t) = 0;
+ TYPE_HAS_COMPLEX_DFLT (t) = 1;
+ TYPE_HAS_COMPLEX_COPY_ASSIGN (t) = 1;
+ CLASSTYPE_LAZY_MOVE_ASSIGN (t) = 0;
/* "This class type is not an aggregate." */
CLASSTYPE_NON_AGGREGATE (t) = 1;
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 64f7b7f041b..ad41e9acc57 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1408,6 +1408,8 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p)
DECL_IN_AGGR_P (fn) = 1;
DECL_ARTIFICIAL (fn) = 1;
DECL_DEFAULTED_FN (fn) = 1;
+ if (cxx_dialect >= cxx0x)
+ DECL_DELETED_FN (fn) = deleted_p;
DECL_NOT_REALLY_EXTERN (fn) = 1;
DECL_DECLARED_INLINE_P (fn) = 1;
gcc_assert (!TREE_USED (fn));
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index cf7180a3a57..7b7dc7b1cd4 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,24 @@
2010-06-29 Jason Merrill <jason@redhat.com>
+ Enable implicitly deleted functions (N2346)
+ * g++.dg/cpp0x/defaulted17.C: New.
+ * g++.dg/cpp0x/implicit1.C: New.
+ * g++.dg/cpp0x/implicit2.C: New.
+ * g++.dg/cpp0x/lambda/lambda-ctor-neg.C: Adjust.
+ * g++.dg/ext/has_virtual_destructor.C: Adjust.
+ * g++.dg/init/ctor4.C: Adjust.
+ * g++.dg/init/synth2.C: Adjust.
+ * g++.dg/lto/20081118_1.C: Adjust.
+ * g++.dg/other/error13.C: Adjust.
+ * g++.dg/other/unused1.C: Adjust.
+ * g++.old-deja/g++.bob/inherit2.C: Adjust.
+ * g++.old-deja/g++.bugs/900205_04.C: Adjust.
+ * g++.old-deja/g++.jason/opeq3.C: Adjust.
+ * g++.old-deja/g++.law/ctors17.C: Adjust.
+ * g++.old-deja/g++.oliva/delete1.C: Adjust.
+ * g++.old-deja/g++.pt/assign1.C: Adjust.
+ * g++.old-deja/g++.pt/crash20.C: Adjust.
+
* g++.dg/cpp0x/defaulted10.C: Adjust for new deleted message.
* g++.dg/cpp0x/defaulted13.C: Adjust.
* g++.dg/cpp0x/defaulted2.C: Adjust.
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted17.C b/gcc/testsuite/g++.dg/cpp0x/defaulted17.C
new file mode 100644
index 00000000000..79e91a0eb61
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted17.C
@@ -0,0 +1,12 @@
+// { dg-options -std=c++0x }
+
+struct A // { dg-error "const|operator=" }
+{
+ const int i;
+};
+
+int main()
+{
+ A a = { 0 };
+ a = a; // { dg-error "deleted" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit1.C b/gcc/testsuite/g++.dg/cpp0x/implicit1.C
new file mode 100644
index 00000000000..2efbde6a93a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit1.C
@@ -0,0 +1,26 @@
+// Test for implicitly deleted destructors.
+// { dg-options "-std=c++0x" }
+// { dg-prune-output "default definition would be ill-formed" }
+// { dg-prune-output "within this context" }
+
+class C
+{
+ void operator delete (void *); // { dg-error "private" }
+public:
+ virtual ~C(); // { dg-error "overriding" }
+};
+
+struct D: C { }; // { dg-error "deleted" }
+D d; // { dg-error "deleted" }
+
+struct E
+{
+ ~E() = delete; // { dg-error "declared here" }
+};
+
+struct F
+{
+ virtual ~F(); // { dg-error "overriding" }
+};
+
+struct G: E, F { }; // { dg-error "deleted" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit2.C b/gcc/testsuite/g++.dg/cpp0x/implicit2.C
new file mode 100644
index 00000000000..f24a78838fa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit2.C
@@ -0,0 +1,33 @@
+// Test that the synthesized C copy constructor calls the A template
+// constructor and has the appropriate exception specification.
+// { dg-options -std=c++0x }
+// { dg-do run }
+
+int r = 1;
+
+struct A
+{
+ A() {}
+ A(const A&) throw () { }
+ template <class T>
+ A(T& t) { r = 0; }
+};
+
+struct B
+{
+ B() {}
+ B(B&) throw () { }
+};
+
+struct C: A, B { };
+
+#define SA(E) static_assert(E, #E)
+
+C c;
+SA (!noexcept(C(c)));
+
+int main()
+{
+ (C(c));
+ return r;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ctor-neg.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ctor-neg.C
index c38f2955d46..76ed7445f45 100644
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ctor-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ctor-neg.C
@@ -3,7 +3,7 @@
void f()
{
int i;
- auto lam = [i]{}; // { dg-message "note" }
+ auto lam = [i]{}; // { dg-message "" }
decltype(lam) lam2 = { 1 }; // { dg-error "" "not an aggregate" }
decltype(lam) lam3; // { dg-error "" "deleted default ctor" }
lam3 = lam; // { dg-error "" "deleted assignment op" }
@@ -12,7 +12,7 @@ void f()
template <class T>
void g(T i)
{
- auto lam = [i]{}; // { dg-message "note" }
+ auto lam = [i]{}; // { dg-message "" }
decltype(lam) lam2 = { 1 }; // { dg-error "" "not an aggregate" }
decltype(lam) lam3; // { dg-error "" "deleted default ctor" }
lam3 = lam; // { dg-error "" "deleted assignment op" }
diff --git a/gcc/testsuite/g++.dg/ext/has_virtual_destructor.C b/gcc/testsuite/g++.dg/ext/has_virtual_destructor.C
index c263a94fd04..093e7f5004d 100644
--- a/gcc/testsuite/g++.dg/ext/has_virtual_destructor.C
+++ b/gcc/testsuite/g++.dg/ext/has_virtual_destructor.C
@@ -14,15 +14,15 @@ union U
double b;
};
-class B
+struct B
{
virtual ~B() { }
};
-class C
+struct C
: public B { };
-class D
+struct D
{
~D() { }
};
diff --git a/gcc/testsuite/g++.dg/init/ctor4.C b/gcc/testsuite/g++.dg/init/ctor4.C
index 0671dd8537d..1c92bb973d3 100644
--- a/gcc/testsuite/g++.dg/init/ctor4.C
+++ b/gcc/testsuite/g++.dg/init/ctor4.C
@@ -6,7 +6,7 @@ public:
foo();
};
-class bar: public foo {// { dg-error "uninitialized" }
+class bar: public foo { // { dg-error "reference|bar::bar" }
private:
int &a;
};
@@ -16,5 +16,5 @@ foo::foo() {
int main(int argc, char **argv)
{
- bar x; // { dg-message "synthesized" }
+ bar x; // { dg-message "synthesized|deleted" }
}
diff --git a/gcc/testsuite/g++.dg/init/synth2.C b/gcc/testsuite/g++.dg/init/synth2.C
index 507db34aa0c..9e8a08a6ea3 100644
--- a/gcc/testsuite/g++.dg/init/synth2.C
+++ b/gcc/testsuite/g++.dg/init/synth2.C
@@ -5,7 +5,7 @@ struct G {
G(G&); // { dg-message "" "candidate" }
};
-class A // { dg-error "no match" }
+class A // { dg-error "" }
{
const G g;
};
diff --git a/gcc/testsuite/g++.dg/lto/20081118_1.C b/gcc/testsuite/g++.dg/lto/20081118_1.C
index b9e56a48b9b..a1bf08186df 100644
--- a/gcc/testsuite/g++.dg/lto/20081118_1.C
+++ b/gcc/testsuite/g++.dg/lto/20081118_1.C
@@ -1,4 +1,5 @@
class object {
+public:
virtual ~object() {}
};
diff --git a/gcc/testsuite/g++.dg/other/error13.C b/gcc/testsuite/g++.dg/other/error13.C
index 89e88478679..784550180ff 100644
--- a/gcc/testsuite/g++.dg/other/error13.C
+++ b/gcc/testsuite/g++.dg/other/error13.C
@@ -5,6 +5,6 @@ struct A // { dg-message "note" }
A(void x); // { dg-error "invalid use|incomplete type|candidates" }
};
-struct B : A {}; // { dg-error "no matching function for call" }
+struct B : A {}; // { dg-error "no matching function for call|deleted" }
-B b; // { dg-message "synthesized method" }
+B b; // { dg-message "synthesized method|deleted" }
diff --git a/gcc/testsuite/g++.dg/other/unused1.C b/gcc/testsuite/g++.dg/other/unused1.C
index d652f41a1de..2a3ca1be749 100644
--- a/gcc/testsuite/g++.dg/other/unused1.C
+++ b/gcc/testsuite/g++.dg/other/unused1.C
@@ -32,7 +32,7 @@ int bar4 (void)
return const_cast<printer *>(dotmatrix)->i;
}
-class class1 { virtual ~class1(); } *c1;
+class class1 { public: virtual ~class1(); } *c1;
class class2 : class1 { char j; };
int bar5 (void)
{
diff --git a/gcc/testsuite/g++.old-deja/g++.bob/inherit2.C b/gcc/testsuite/g++.old-deja/g++.bob/inherit2.C
index c0a821bb6b1..6e26ecfa639 100644
--- a/gcc/testsuite/g++.old-deja/g++.bob/inherit2.C
+++ b/gcc/testsuite/g++.old-deja/g++.bob/inherit2.C
@@ -10,7 +10,7 @@ private:
const A& operator =(const A &) { abort(); }
};
-class B : public A { // { dg-error "within" }
+class B : public A { // { dg-error "" }
public:
B(void) {}
};
@@ -20,5 +20,5 @@ void f(B b) { // { dg-error "initializing" }
void g() {
B h;
- f(h); // { dg-message "synthesized" "synth" }
+ f(h); // { dg-message "synthesized|deleted" "synth" }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900205_04.C b/gcc/testsuite/g++.old-deja/g++.bugs/900205_04.C
index 8d91db67ae8..4290144f89f 100644
--- a/gcc/testsuite/g++.old-deja/g++.bugs/900205_04.C
+++ b/gcc/testsuite/g++.old-deja/g++.bugs/900205_04.C
@@ -23,9 +23,9 @@ struct0::struct0 (int, void *) // { dg-message "note" }
{
}
-struct struct0_derived_struct_0 : public struct0 { // { dg-error "no matching" }
+struct struct0_derived_struct_0 : public struct0 { // { dg-error "no matching|deleted" }
};
-struct0_derived_struct_0 object; // { dg-message "synthesized" }
+struct0_derived_struct_0 object; // { dg-message "synthesized|deleted" }
int main () { return 0; }
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/opeq3.C b/gcc/testsuite/g++.old-deja/g++.jason/opeq3.C
index 7a50abb2567..b4e6e2550c0 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/opeq3.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/opeq3.C
@@ -1,7 +1,7 @@
// { dg-do assemble }
// Bug: g++ generates code for assignment in invalid situations.
-class X { // { dg-error "assignment" }
+class X { // { dg-error "reference|operator=" }
int& a;
public:
X(int& i): a(i) { }
@@ -11,5 +11,5 @@ void foo ()
{
int one=1, two=2;
X a(one), b(two);
- a = b; // { dg-message "synthesized" }
+ a = b; // { dg-message "synthesized|deleted" }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.law/ctors17.C b/gcc/testsuite/g++.old-deja/g++.law/ctors17.C
index 3d63d01c0a9..0d61c49abd7 100644
--- a/gcc/testsuite/g++.old-deja/g++.law/ctors17.C
+++ b/gcc/testsuite/g++.old-deja/g++.law/ctors17.C
@@ -6,10 +6,12 @@
// Subject: gcc 2.4.3.1: illegal constructor call not rejected
// Date: Tue, 15 Jun 1993 18:34:14 +0200 (MET DST)
+// C++0x mode doesn't print the deleted copy constructor as a candidate.
+// { dg-prune-output ":14:" }
#include <fstream>
-class X : public std::ifstream { // { dg-message "note" } candidate
+class X : public std::ifstream {
public:
X(int a, const char *b) {} // { dg-message "note" } candidate
};
diff --git a/gcc/testsuite/g++.old-deja/g++.oliva/delete1.C b/gcc/testsuite/g++.old-deja/g++.oliva/delete1.C
index 3912dbad5ed..368a87a2a9a 100644
--- a/gcc/testsuite/g++.old-deja/g++.oliva/delete1.C
+++ b/gcc/testsuite/g++.old-deja/g++.oliva/delete1.C
@@ -28,5 +28,4 @@ struct baz : foo {
virtual ~baz() {} // { dg-error "" } delete is private in vdtor
} baz_;
-struct bad : baz {} bad_; // { dg-error "" } delete is private in vdtor
-// { dg-message "synthesized" "note" { target *-*-* } 31 }
+struct bad : baz {} bad_; // { dg-message "" } delete is private in vdtor
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/assign1.C b/gcc/testsuite/g++.old-deja/g++.pt/assign1.C
index 464b7c692d0..854d8ee27a9 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/assign1.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/assign1.C
@@ -2,7 +2,7 @@
// Origin: Mark Mitchell <mark@codesourcery.com>
template <class T>
-struct S { // { dg-error "assignment" }
+struct S { // { dg-error "const|operator=" }
S();
T t;
};
@@ -10,5 +10,5 @@ struct S { // { dg-error "assignment" }
void f()
{
S<const int> s;
- s = s; // { dg-message "synthesized" }
+ s = s; // { dg-message "synthesized|deleted" }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash20.C b/gcc/testsuite/g++.old-deja/g++.pt/crash20.C
index 0a3220921ce..a5175b9909b 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/crash20.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/crash20.C
@@ -1,8 +1,7 @@
// { dg-do compile }
template <class T = int>
-struct A { // { dg-error "assignment" "assignment" }
-// { dg-message "instantiated" "inst" { target *-*-* } 4 }
+struct A { // { dg-message "const|operator=" "assignment" }
const T x;
A() : x(0) { } A(T x) : x(x) { }
};
@@ -11,7 +10,7 @@ template <class B>
void func ()
{
B y;
- y = B(); // { dg-message "synthesized" }
+ y = B(); // { dg-message "synthesized|deleted" }
}
int main (void) { func< A<> >(); }