aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2011-05-10 13:58:46 -0400
committerJason Merrill <jason@gcc.gnu.org>2011-05-10 13:58:46 -0400
commit955524371fecf607a7eacdc838594ce44c4a9c46 (patch)
treed6b97fffd003379dcbb4cc87d3424a063bd83702 /gcc
parentb4359e45b9d1bdb218cac9d5bd311fedf1568d32 (diff)
downloadgcc-955524371fecf607a7eacdc838594ce44c4a9c46.zip
gcc-955524371fecf607a7eacdc838594ce44c4a9c46.tar.gz
gcc-955524371fecf607a7eacdc838594ce44c4a9c46.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/class.c21
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl.c4
-rw-r--r--gcc/cp/init.c23
-rw-r--r--gcc/cp/typeck2.c4
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted25.C10
-rw-r--r--gcc/testsuite/g++.dg/template/crash7.C9
9 files changed, 65 insertions, 21 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 34359f0..580a3fc 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,16 @@
2011-05-10 Jason Merrill <jason@redhat.com>
+ 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 198eca6..293dd1c 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 efcdeef..1705232 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 ab36d18..eff2360 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 b71ddfc..7d7adbe 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 ec6b5d3..26b9816 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 4a63e60..45739d0 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,8 @@
2011-05-10 Jason Merrill <jason@redhat.com>
+ * g++.dg/cpp0x/defaulted25.C: New.
+ * g++.dg/template/crash7.C: Adjust.
+
* g++.dg/cpp0x/variadic108.C: New.
2011-05-10 Ville Voutilainen <ville.voutilainen@gmail.com>
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted25.C b/gcc/testsuite/g++.dg/cpp0x/defaulted25.C
new file mode 100644
index 0000000..2a38fed
--- /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 ae07d91..7fda9a9 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 <typename> struct A
-{ // { not-dg-error "candidates" }
+template <typename> struct A // { dg-message "A.void.::A.const A" }
+{
template <typename> A(typename A::X) {} // { dg-error "no type" }
};
-A<void> 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<void> a; // { dg-error "instantiated|no match" }
+// { dg-prune-output "note" }