@@ -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
@@ -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);
@@ -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))))
{
@@ -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);
}
@@ -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
new file mode 100644
@@ -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" }
@@ -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" }