From 955524371fecf607a7eacdc838594ce44c4a9c46 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 10 May 2011 13:58:46 -0400 Subject: [PATCH] re PR c++/48930 ([C++0x] Invalid implicitly declared default c'tor) PR c++/48930 * class.c (type_build_ctor_call): New. * cp-tree.h: Declare it. * decl.c (check_initializer): Use it instead of TYPE_NEEDS_CONSTRUCTING. * init.c (build_value_init, build_value_init_noctor): Likewise. (perform_member_init, expand_aggr_init_1, build_new_1): Likewise. (build_vec_init): Likewise. * typeck2.c (process_init_constructor_array): Likewise. (process_init_constructor_record): Likewise. From-SVN: r173628 --- gcc/cp/ChangeLog | 11 +++++++++++ gcc/cp/class.c | 21 +++++++++++++++++++++ gcc/cp/cp-tree.h | 1 + gcc/cp/decl.c | 4 ++-- gcc/cp/init.c | 23 +++++++++++------------ gcc/cp/typeck2.c | 4 ++-- gcc/testsuite/ChangeLog | 3 +++ gcc/testsuite/g++.dg/cpp0x/defaulted25.C | 10 ++++++++++ gcc/testsuite/g++.dg/template/crash7.C | 9 ++++----- 9 files changed, 65 insertions(+), 21 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/defaulted25.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 34359f01fde..580a3fc01cb 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,16 @@ 2011-05-10 Jason Merrill + PR c++/48930 + * class.c (type_build_ctor_call): New. + * cp-tree.h: Declare it. + * decl.c (check_initializer): Use it instead of + TYPE_NEEDS_CONSTRUCTING. + * init.c (build_value_init, build_value_init_noctor): Likewise. + (perform_member_init, expand_aggr_init_1, build_new_1): Likewise. + (build_vec_init): Likewise. + * typeck2.c (process_init_constructor_array): Likewise. + (process_init_constructor_record): Likewise. + PR c++/48736 * pt.c (tsubst_copy_and_build): Handle substitution of a pack expansion producing another expansion. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 198eca65431..293dd1c0bd5 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -4466,6 +4466,27 @@ type_has_move_assign (tree t) return false; } +/* Nonzero if we need to build up a constructor call when initializing an + object of this class, either because it has a user-provided constructor + or because it doesn't have a default constructor (so we need to give an + error if no initializer is provided). Use TYPE_NEEDS_CONSTRUCTING when + what you care about is whether or not an object can be produced by a + constructor (e.g. so we don't set TREE_READONLY on const variables of + such type); use this function when what you care about is whether or not + to try to call a constructor to create an object. The latter case is + the former plus some cases of constructors that cannot be called. */ + +bool +type_build_ctor_call (tree t) +{ + tree inner; + if (TYPE_NEEDS_CONSTRUCTING (t)) + return true; + inner = strip_array_types (t); + return (CLASS_TYPE_P (inner) && !TYPE_HAS_DEFAULT_CONSTRUCTOR (inner) + && !ANON_AGGR_TYPE_P (inner)); +} + /* Remove all zero-width bit-fields from T. */ static void diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index efcdeefd38d..1705232b9c8 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4787,6 +4787,7 @@ extern bool type_has_constexpr_default_constructor (tree); extern bool type_has_virtual_destructor (tree); extern bool type_has_move_constructor (tree); extern bool type_has_move_assign (tree); +extern bool type_build_ctor_call (tree); extern void defaulted_late_check (tree); extern bool defaultable_fn_check (tree); extern void fixup_type_variants (tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index ab36d18552a..eff23608b6a 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5410,7 +5410,7 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup) ; else if (TREE_CODE (type) == REFERENCE_TYPE) init = grok_reference_init (decl, type, init, cleanup); - else if (init || TYPE_NEEDS_CONSTRUCTING (type)) + else if (init || type_build_ctor_call (type)) { if (!init) check_for_uninitialized_const_var (decl); @@ -5445,7 +5445,7 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup) if (type == error_mark_node) return NULL_TREE; - if (TYPE_NEEDS_CONSTRUCTING (type) + if (type_build_ctor_call (type) || (CLASS_TYPE_P (type) && !(init && BRACE_ENCLOSED_INITIALIZER_P (init)))) { diff --git a/gcc/cp/init.c b/gcc/cp/init.c index b71ddfc0f9f..7d7adbe0405 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -341,7 +341,7 @@ build_value_init (tree type, tsubst_flags_t complain) NULL, type, LOOKUP_NORMAL, complain), complain); - else if (TYPE_NEEDS_CONSTRUCTING (type)) + else if (type_build_ctor_call (type)) { /* This is a class that needs constructing, but doesn't have a user-provided constructor. So we need to zero-initialize @@ -371,7 +371,7 @@ build_value_init_noctor (tree type, tsubst_flags_t complain) SFINAE-enabled. */ if (CLASS_TYPE_P (type)) { - gcc_assert (!TYPE_NEEDS_CONSTRUCTING (type)); + gcc_assert (!type_build_ctor_call (type)); if (TREE_CODE (type) != UNION_TYPE) { @@ -530,7 +530,7 @@ perform_member_init (tree member, tree init) finish_expr_stmt (init); } } - else if (TYPE_NEEDS_CONSTRUCTING (type)) + else if (type_build_ctor_call (type)) { if (TREE_CODE (type) == ARRAY_TYPE) { @@ -1568,7 +1568,7 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, /* Fall through. */; /* If there isn't, but we still need to call the constructor, zero out the object first. */ - else if (TYPE_NEEDS_CONSTRUCTING (type)) + else if (type_build_ctor_call (type)) { init = build_zero_init (type, NULL_TREE, /*static_storage_p=*/false); init = build2 (INIT_EXPR, type, exp, init); @@ -2046,7 +2046,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, if (abstract_virtuals_error_sfinae (NULL_TREE, elt_type, complain)) return error_mark_node; - is_initialized = (TYPE_NEEDS_CONSTRUCTING (elt_type) || *init != NULL); + is_initialized = (type_build_ctor_call (elt_type) || *init != NULL); if (*init == NULL) { @@ -2351,7 +2351,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, rebuild it at instantiation time, so just build up a single constructor call to get any appropriate diagnostics. */ init_expr = cp_build_indirect_ref (data_addr, RO_NULL, complain); - if (TYPE_NEEDS_CONSTRUCTING (elt_type)) + if (type_build_ctor_call (elt_type)) init_expr = build_special_member_call (init_expr, complete_ctor_identifier, init, elt_type, @@ -2408,7 +2408,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, { init_expr = cp_build_indirect_ref (data_addr, RO_NULL, complain); - if (TYPE_NEEDS_CONSTRUCTING (type) && !explicit_value_init_p) + if (type_build_ctor_call (type) && !explicit_value_init_p) { init_expr = build_special_member_call (init_expr, complete_ctor_identifier, @@ -3164,8 +3164,7 @@ build_vec_init (tree base, tree maxindex, tree init, { if (init) /* OK, we set base2 above. */; - else if (TYPE_LANG_SPECIFIC (type) - && TYPE_NEEDS_CONSTRUCTING (type) + else if (CLASS_TYPE_P (type) && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type)) { if (complain & tf_error) @@ -3181,7 +3180,7 @@ build_vec_init (tree base, tree maxindex, tree init, We do need to keep going if we're copying an array. */ if (from_array - || ((TYPE_NEEDS_CONSTRUCTING (type) || explicit_value_init_p) + || ((type_build_ctor_call (type) || explicit_value_init_p) && ! (host_integerp (maxindex, 0) && (num_initialized_elts == tree_low_cst (maxindex, 0) + 1)))) @@ -3221,7 +3220,7 @@ build_vec_init (tree base, tree maxindex, tree init, if (from_array == 2) elt_init = cp_build_modify_expr (to, NOP_EXPR, from, complain); - else if (TYPE_NEEDS_CONSTRUCTING (type)) + else if (type_build_ctor_call (type)) elt_init = build_aggr_init (to, from, 0, complain); else if (from) elt_init = cp_build_modify_expr (to, NOP_EXPR, from, @@ -3247,7 +3246,7 @@ build_vec_init (tree base, tree maxindex, tree init, } else { - gcc_assert (TYPE_NEEDS_CONSTRUCTING (type)); + gcc_assert (type_build_ctor_call (type)); elt_init = build_aggr_init (to, init, 0, complain); } diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index ec6b5d37850..26b9816d548 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -1048,7 +1048,7 @@ process_init_constructor_array (tree type, tree init, { tree next; - if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type))) + if (type_build_ctor_call (TREE_TYPE (type))) { /* If this type needs constructors run for default-initialization, we can't rely on the back end to do it for us, so build up @@ -1144,7 +1144,7 @@ process_init_constructor_record (tree type, tree init, LOOKUP_IMPLICIT, complain); ++idx; } - else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field))) + else if (type_build_ctor_call (TREE_TYPE (field))) { /* If this type needs constructors run for default-initialization, we can't rely on the back end to do it diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4a63e60e144..45739d01bfa 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2011-05-10 Jason Merrill + * g++.dg/cpp0x/defaulted25.C: New. + * g++.dg/template/crash7.C: Adjust. + * g++.dg/cpp0x/variadic108.C: New. 2011-05-10 Ville Voutilainen diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted25.C b/gcc/testsuite/g++.dg/cpp0x/defaulted25.C new file mode 100644 index 00000000000..2a38fedb248 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted25.C @@ -0,0 +1,10 @@ +// PR c++/48930 +// { dg-options -std=c++0x } +// { dg-prune-output "note" } + +struct A +{ + A(const A&) = default; +}; + +A a; // { dg-error "no match" } diff --git a/gcc/testsuite/g++.dg/template/crash7.C b/gcc/testsuite/g++.dg/template/crash7.C index ae07d91e739..7fda9a9ba19 100644 --- a/gcc/testsuite/g++.dg/template/crash7.C +++ b/gcc/testsuite/g++.dg/template/crash7.C @@ -5,11 +5,10 @@ // PR c++/10108: ICE in tsubst_decl for error due to non-existence // nested type. -template struct A -{ // { not-dg-error "candidates" } +template struct A // { dg-message "A.void.::A.const A" } +{ template A(typename A::X) {} // { dg-error "no type" } }; -A a; // { not-dg-error "instantiated|no match" } -// We currently don't give the "no match" error because we don't add the -// invalid constructor template to TYPE_METHODS. +A a; // { dg-error "instantiated|no match" } +// { dg-prune-output "note" } -- 2.30.2