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.
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
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);
;
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);
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))))
{
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
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)
{
finish_expr_stmt (init);
}
}
- else if (TYPE_NEEDS_CONSTRUCTING (type))
+ else if (type_build_ctor_call (type))
{
if (TREE_CODE (type) == ARRAY_TYPE)
{
/* 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);
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)
{
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,
{
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,
{
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)
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))))
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,
}
else
{
- gcc_assert (TYPE_NEEDS_CONSTRUCTING (type));
+ gcc_assert (type_build_ctor_call (type));
elt_init = build_aggr_init (to, init, 0, complain);
}
{
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
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
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>
--- /dev/null
+// PR c++/48930
+// { dg-options -std=c++0x }
+// { dg-prune-output "note" }
+
+struct A
+{
+ A(const A&) = default;
+};
+
+A a; // { dg-error "no match" }
// 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" }