aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPaolo Carlini <paolo.carlini@oracle.com>2013-08-30 15:39:01 +0000
committerPaolo Carlini <paolo@gcc.gnu.org>2013-08-30 15:39:01 +0000
commita624d5fe08ca0e8bf755a33b4849ff03d511958e (patch)
tree5fc09f4993648c27925c4b8d44f6a5721dd0baec /gcc
parent8f0e4d72f2905596ecb212e8824a0a0e1489bab8 (diff)
downloadgcc-a624d5fe08ca0e8bf755a33b4849ff03d511958e.zip
gcc-a624d5fe08ca0e8bf755a33b4849ff03d511958e.tar.gz
gcc-a624d5fe08ca0e8bf755a33b4849ff03d511958e.tar.bz2
re PR c++/51424 ([C++11] G++ should diagnose self-delegating constructors)
/cp 2013-08-30 Paolo Carlini <paolo.carlini@oracle.com> PR c++/51424 * cp-tree.h (LOOKUP_DELEGATING_CONS): Add. * init.c (perform_target_ctor): Use it. * call.c (build_special_member_call): Diagnose self-delegating constructors. /testsuite 2013-08-30 Paolo Carlini <paolo.carlini@oracle.com> PR c++/51424 * g++.dg/cpp0x/dc8.C: New. * g++.dg/template/meminit1.C: Adjust. From-SVN: r202110
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/call.c8
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/init.c5
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/dc8.C66
-rw-r--r--gcc/testsuite/g++.dg/template/meminit1.C2
7 files changed, 94 insertions, 3 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1e6d621..e52dfa7 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+2013-08-30 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/51424
+ * cp-tree.h (LOOKUP_DELEGATING_CONS): Add.
+ * init.c (perform_target_ctor): Use it.
+ * call.c (build_special_member_call): Diagnose self-delegating
+ constructors.
+
2013-08-30 Gabriel Dos Reis <gdr@integrable-solutions.net>
* cxx-pretty-print.h (cxx_pretty_printer::declaration): Declare as
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index f8fab08..3ed73b8 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -7442,6 +7442,14 @@ build_special_member_call (tree instance, tree name, vec<tree, va_gc> **args,
if (allocated != NULL)
release_tree_vector (allocated);
+ if ((complain & tf_error)
+ && (flags & LOOKUP_DELEGATING_CONS)
+ && name == complete_ctor_identifier
+ && TREE_CODE (ret) == CALL_EXPR
+ && (DECL_ABSTRACT_ORIGIN (TREE_OPERAND (CALL_EXPR_FN (ret), 0))
+ == current_function_decl))
+ error ("constructor delegates to itself");
+
return ret;
}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 73f6a6a..3e4f188 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4509,6 +4509,8 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
#define LOOKUP_NO_RVAL_BIND (LOOKUP_EXPLICIT_TMPL_ARGS << 1)
/* Used by case_conversion to disregard non-integral conversions. */
#define LOOKUP_NO_NON_INTEGRAL (LOOKUP_NO_RVAL_BIND << 1)
+/* Used for delegating constructors in order to diagnose self-delegation. */
+#define LOOKUP_DELEGATING_CONS (LOOKUP_NO_NON_INTEGRAL << 1)
#define LOOKUP_NAMESPACES_ONLY(F) \
(((F) & LOOKUP_PREFER_NAMESPACES) && !((F) & LOOKUP_PREFER_TYPES))
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 156b4a1..f261f99 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -500,8 +500,9 @@ perform_target_ctor (tree init)
tree decl = current_class_ref;
tree type = current_class_type;
- finish_expr_stmt (build_aggr_init (decl, init, LOOKUP_NORMAL,
- tf_warning_or_error));
+ finish_expr_stmt (build_aggr_init (decl, init,
+ LOOKUP_NORMAL|LOOKUP_DELEGATING_CONS,
+ tf_warning_or_error));
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
{
tree expr = build_delete (type, decl, sfk_complete_destructor,
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a46bb12..f8a1f49 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2013-08-30 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/51424
+ * g++.dg/cpp0x/dc8.C: New.
+ * g++.dg/template/meminit1.C: Adjust.
+
2013-08-30 Teresa Johnson <tejohnson@google.com>
* gcc.dg/inline-dump.c: Delete inadvertant commit.
diff --git a/gcc/testsuite/g++.dg/cpp0x/dc8.C b/gcc/testsuite/g++.dg/cpp0x/dc8.C
new file mode 100644
index 0000000..e483f3e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/dc8.C
@@ -0,0 +1,66 @@
+// PR c++/51424
+// { dg-do compile { target c++11 } }
+
+template <class T >
+struct S
+{
+ S() : S() {} // { dg-error "delegates to itself" }
+ S(int x) : S(x) {} // { dg-error "delegates to itself" }
+};
+
+struct B1
+{
+ B1() : B1() {} // { dg-error "delegates to itself" }
+ B1(int y) : B1(y) {} // { dg-error "delegates to itself" }
+};
+
+struct V1 : virtual B1
+{
+ V1() : B1() {}
+ V1(int x) : B1(x) {}
+};
+
+struct B2
+{
+ B2() : B2() {} // { dg-error "delegates to itself" }
+ B2(int y) : B2(y) {} // { dg-error "delegates to itself" }
+};
+
+struct V2 : virtual B2
+{
+ V2() : V2() {} // { dg-error "delegates to itself" }
+ V2(int x) : V2(x) {} // { dg-error "delegates to itself" }
+};
+
+struct B3
+{
+ B3() {}
+ B3(int y) {}
+};
+
+struct V3 : virtual B3
+{
+ V3() : V3() {} // { dg-error "delegates to itself" }
+ V3(int x) : V3(x) {} // { dg-error "delegates to itself" }
+};
+
+struct CE1
+{
+ constexpr CE1() : CE1() {} // { dg-error "delegates to itself" }
+ constexpr CE1(int x) : CE1(x) {} // { dg-error "delegates to itself" }
+};
+
+struct CEB2
+{
+ constexpr CEB2() : CEB2() {} // { dg-error "delegates to itself" }
+ constexpr CEB2(int x) : CEB2(x) {} // { dg-error "delegates to itself" }
+};
+
+struct CE2 : CEB2
+{
+ constexpr CE2() : CEB2() {}
+ constexpr CE2(int x) : CEB2(x) {}
+};
+
+S<int> s1;
+S<int> s2(1);
diff --git a/gcc/testsuite/g++.dg/template/meminit1.C b/gcc/testsuite/g++.dg/template/meminit1.C
index 19a1e54..1dc96c4 100644
--- a/gcc/testsuite/g++.dg/template/meminit1.C
+++ b/gcc/testsuite/g++.dg/template/meminit1.C
@@ -3,6 +3,6 @@ template <class T >
struct S
{
S() : S() {} // { dg-message "delegating constructors" }
-};
+}; // { dg-error "delegates to itself" "" { target *-*-* } 5 }
S<int> s;