diff options
author | Paolo Carlini <paolo.carlini@oracle.com> | 2013-08-30 15:39:01 +0000 |
---|---|---|
committer | Paolo Carlini <paolo@gcc.gnu.org> | 2013-08-30 15:39:01 +0000 |
commit | a624d5fe08ca0e8bf755a33b4849ff03d511958e (patch) | |
tree | 5fc09f4993648c27925c4b8d44f6a5721dd0baec /gcc | |
parent | 8f0e4d72f2905596ecb212e8824a0a0e1489bab8 (diff) | |
download | gcc-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/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/call.c | 8 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 2 | ||||
-rw-r--r-- | gcc/cp/init.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/dc8.C | 66 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/meminit1.C | 2 |
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; |