From a624d5fe08ca0e8bf755a33b4849ff03d511958e Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Fri, 30 Aug 2013 15:39:01 +0000 Subject: [PATCH] re PR c++/51424 ([C++11] G++ should diagnose self-delegating constructors) /cp 2013-08-30 Paolo Carlini 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 PR c++/51424 * g++.dg/cpp0x/dc8.C: New. * g++.dg/template/meminit1.C: Adjust. From-SVN: r202110 --- gcc/cp/ChangeLog | 8 +++ gcc/cp/call.c | 8 +++ gcc/cp/cp-tree.h | 2 + gcc/cp/init.c | 5 +- gcc/testsuite/ChangeLog | 6 +++ gcc/testsuite/g++.dg/cpp0x/dc8.C | 66 ++++++++++++++++++++++++ gcc/testsuite/g++.dg/template/meminit1.C | 2 +- 7 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/dc8.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1e6d62104f8..e52dfa7c2c4 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2013-08-30 Paolo Carlini + + 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 * cxx-pretty-print.h (cxx_pretty_printer::declaration): Declare as diff --git a/gcc/cp/call.c b/gcc/cp/call.c index f8fab082813..3ed73b80374 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -7442,6 +7442,14 @@ build_special_member_call (tree instance, tree name, vec **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 73f6a6ad43b..3e4f188b93f 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 156b4a1e082..f261f99b82b 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 a46bb121a8e..f8a1f4964d2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2013-08-30 Paolo Carlini + + PR c++/51424 + * g++.dg/cpp0x/dc8.C: New. + * g++.dg/template/meminit1.C: Adjust. + 2013-08-30 Teresa Johnson * 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 00000000000..e483f3e4eeb --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/dc8.C @@ -0,0 +1,66 @@ +// PR c++/51424 +// { dg-do compile { target c++11 } } + +template +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 s1; +S s2(1); diff --git a/gcc/testsuite/g++.dg/template/meminit1.C b/gcc/testsuite/g++.dg/template/meminit1.C index 19a1e546d52..1dc96c472ad 100644 --- a/gcc/testsuite/g++.dg/template/meminit1.C +++ b/gcc/testsuite/g++.dg/template/meminit1.C @@ -3,6 +3,6 @@ template struct S { S() : S() {} // { dg-message "delegating constructors" } -}; +}; // { dg-error "delegates to itself" "" { target *-*-* } 5 } S s;