+2011-05-09 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/48737
+ PR c++/48744
+ * decl.c (reshape_init): Take a complain parameter and do
+ not call error if tf_error is not set.
+ (check_initializer, reshape_init_r, reshape_init_array,
+ reshape_init_array_1, reshape_init_vector, reshape_init_class):
+ Adjust.
+ * typeck2.c (digest_init_r): Take a complain parameter and
+ pass it to convert_for_initialization.
+ (digest_init, digest_init_flags, process_init_constructor_array,
+ process_init_constructor_record, process_init_constructor_union,
+ process_init_constructor, digest_init_r): Adjust.
+ * init.c (expand_default_init, build_new_1): Likewise.
+ * typeck.c (cp_build_modify_expr): Likewise.
+ * decl2.c (grokfield): Likewise.
+ * call.c (convert_like_real, convert_default_arg): Likewise.
+ * semantics.c (finish_compound_literal): Pass complain to
+ reshape_init and digest_init.
+ * cp-tree.h: Adjust declarations.
+
2011-05-07 Fabien ChĂȘne <fabien@gcc.gnu.org>
-
+
PR c++/48859
* init.c (diagnose_uninitialized_cst_or_ref_member_1): stop the
recursion if there is user defined constructor.
expr = build2 (COMPLEX_EXPR, totype, real, imag);
return fold_if_not_in_template (expr);
}
- return get_target_expr (digest_init (totype, expr));
+ return get_target_expr (digest_init (totype, expr, complain));
default:
break;
arg = break_out_target_exprs (arg);
if (TREE_CODE (arg) == CONSTRUCTOR)
{
- arg = digest_init (type, arg);
+ arg = digest_init (type, arg, tf_warning_or_error);
arg = convert_for_initialization (0, type, arg, LOOKUP_IMPLICIT,
ICR_DEFAULT_ARGUMENT, fn, parmnum,
tf_warning_or_error);
extern bool cp_missing_noreturn_ok_p (tree);
extern void initialize_artificial_var (tree, VEC(constructor_elt,gc) *);
extern tree check_var_type (tree, tree);
-extern tree reshape_init (tree, tree);
+extern tree reshape_init (tree, tree, tsubst_flags_t);
extern tree next_initializable_field (tree);
extern bool defer_mark_used_calls;
extern tree store_init_value (tree, tree, int);
extern void check_narrowing (tree, tree);
-extern tree digest_init (tree, tree);
+extern tree digest_init (tree, tree, tsubst_flags_t);
extern tree digest_init_flags (tree, tree, int);
extern tree build_scoped_ref (tree, tree, tree *);
extern tree build_x_arrow (tree);
constructor_elt *end;
} reshape_iter;
-static tree reshape_init_r (tree, reshape_iter *, bool);
+static tree reshape_init_r (tree, reshape_iter *, bool, tsubst_flags_t);
/* FIELD is a FIELD_DECL or NULL. In the former case, the value
returned is the next FIELD_DECL (possibly FIELD itself) that can be
the iterator within the constructor. */
static tree
-reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d)
+reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d,
+ tsubst_flags_t complain)
{
tree new_init;
bool sized_array_p = (max_index != NULL_TREE);
tree elt_init;
check_array_designated_initializer (d->cur);
- elt_init = reshape_init_r (elt_type, d, /*first_initializer_p=*/false);
+ elt_init = reshape_init_r (elt_type, d, /*first_initializer_p=*/false,
+ complain);
if (elt_init == error_mark_node)
return error_mark_node;
CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_init),
Parameters are the same of reshape_init_r. */
static tree
-reshape_init_array (tree type, reshape_iter *d)
+reshape_init_array (tree type, reshape_iter *d, tsubst_flags_t complain)
{
tree max_index = NULL_TREE;
if (TYPE_DOMAIN (type))
max_index = array_type_nelts (type);
- return reshape_init_array_1 (TREE_TYPE (type), max_index, d);
+ return reshape_init_array_1 (TREE_TYPE (type), max_index, d, complain);
}
/* Subroutine of reshape_init_r, processes the initializers for vectors.
Parameters are the same of reshape_init_r. */
static tree
-reshape_init_vector (tree type, reshape_iter *d)
+reshape_init_vector (tree type, reshape_iter *d, tsubst_flags_t complain)
{
tree max_index = NULL_TREE;
tree value = d->cur->value;
if (!same_type_p (TREE_TYPE (value), type))
{
- error ("invalid type %qT as initializer for a vector of type %qT",
- TREE_TYPE (d->cur->value), type);
+ if (complain & tf_error)
+ error ("invalid type %qT as initializer for a vector of type %qT",
+ TREE_TYPE (d->cur->value), type);
value = error_mark_node;
}
++d->cur;
if (TREE_CODE (type) == VECTOR_TYPE)
max_index = size_int (TYPE_VECTOR_SUBPARTS (type) - 1);
- return reshape_init_array_1 (TREE_TYPE (type), max_index, d);
+ return reshape_init_array_1 (TREE_TYPE (type), max_index, d, complain);
}
/* Subroutine of reshape_init_r, processes the initializers for classes
or union. Parameters are the same of reshape_init_r. */
static tree
-reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p)
+reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p,
+ tsubst_flags_t complain)
{
tree field;
tree new_init;
initializer-list {}. */
if (!first_initializer_p)
{
- error ("initializer for %qT must be brace-enclosed", type);
+ if (complain & tf_error)
+ error ("initializer for %qT must be brace-enclosed", type);
return error_mark_node;
}
return new_init;
if (!field || TREE_CODE (field) != FIELD_DECL)
{
- error ("%qT has no non-static data member named %qD", type,
- d->cur->index);
+ if (complain & tf_error)
+ error ("%qT has no non-static data member named %qD", type,
+ d->cur->index);
return error_mark_node;
}
}
break;
field_init = reshape_init_r (TREE_TYPE (field), d,
- /*first_initializer_p=*/false);
+ /*first_initializer_p=*/false, complain);
if (field_init == error_mark_node)
return error_mark_node;
outermost CONSTRUCTOR node. */
static tree
-reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p)
+reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p,
+ tsubst_flags_t complain)
{
tree init = d->cur->value;
if (BRACE_ENCLOSED_INITIALIZER_P (init))
{
if (CONSTRUCTOR_NELTS (init) > 2)
- error ("too many initializers for %qT", type);
+ {
+ if (complain & tf_error)
+ error ("too many initializers for %qT", type);
+ else
+ return error_mark_node;
+ }
}
else if (first_initializer_p && d->cur != d->end)
{
{
if (SCALAR_TYPE_P (type))
{
- error ("braces around scalar initializer for type %qT", type);
+ if (complain & tf_error)
+ error ("braces around scalar initializer for type %qT", type);
init = error_mark_node;
}
else
{
++d->cur;
gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init));
- return reshape_init (type, init);
+ return reshape_init (type, init, complain);
}
}
/* Dispatch to specialized routines. */
if (CLASS_TYPE_P (type))
- return reshape_init_class (type, d, first_initializer_p);
+ return reshape_init_class (type, d, first_initializer_p, complain);
else if (TREE_CODE (type) == ARRAY_TYPE)
- return reshape_init_array (type, d);
+ return reshape_init_array (type, d, complain);
else if (TREE_CODE (type) == VECTOR_TYPE)
- return reshape_init_vector (type, d);
+ return reshape_init_vector (type, d, complain);
else
gcc_unreachable();
}
revised CONSTRUCTOR node is returned. */
tree
-reshape_init (tree type, tree init)
+reshape_init (tree type, tree init, tsubst_flags_t complain)
{
VEC(constructor_elt, gc) *v;
reshape_iter d;
d.cur = VEC_index (constructor_elt, v, 0);
d.end = d.cur + VEC_length (constructor_elt, v);
- new_init = reshape_init_r (type, &d, true);
+ new_init = reshape_init_r (type, &d, true, complain);
if (new_init == error_mark_node)
return error_mark_node;
/* Make sure all the element of the constructor were used. Otherwise,
issue an error about exceeding initializers. */
if (d.cur != d.end)
- error ("too many initializers for %qT", type);
+ {
+ if (complain & tf_error)
+ error ("too many initializers for %qT", type);
+ else
+ return error_mark_node;
+ }
return new_init;
}
init = error_mark_node;
}
else
- init = reshape_init (type, init);
+ init = reshape_init (type, init, tf_warning_or_error);
}
/* If DECL has an array type without a specific bound, deduce the
else if (!processing_template_decl)
{
if (TREE_CODE (init) == CONSTRUCTOR)
- init = digest_init (TREE_TYPE (value), init);
+ init = digest_init (TREE_TYPE (value), init, tf_warning_or_error);
init = maybe_constant_init (init);
if (init != error_mark_node && !TREE_CONSTANT (init))
{
/* A brace-enclosed initializer for an aggregate. In C++0x this can
happen for direct-initialization, too. */
- init = digest_init (type, init);
+ init = digest_init (type, init, complain);
init = build2 (INIT_EXPR, TREE_TYPE (exp), exp, init);
TREE_SIDE_EFFECTS (init) = 1;
finish_expr_stmt (init);
"verify length of initializer-list");
}
arraytype = build_cplus_array_type (type, domain);
- vecinit = digest_init (arraytype, vecinit);
+ vecinit = digest_init (arraytype, vecinit, complain);
}
else if (*init)
{
if (TREE_CODE (type) == ARRAY_TYPE
&& check_array_initializer (NULL_TREE, type, compound_literal))
return error_mark_node;
- compound_literal = reshape_init (type, compound_literal);
+ compound_literal = reshape_init (type, compound_literal, complain);
if (TREE_CODE (type) == ARRAY_TYPE
&& TYPE_DOMAIN (type) == NULL_TREE)
{
if (type == error_mark_node)
return error_mark_node;
}
- compound_literal = digest_init (type, compound_literal);
+ compound_literal = digest_init (type, compound_literal, complain);
/* Put static/constant array temporaries in static variables, but always
represent class temporaries with TARGET_EXPR so we elide copies. */
if ((!at_function_scope_p () || CP_TYPE_CONST_P (type))
}
if (check_array_initializer (lhs, lhstype, newrhs))
return error_mark_node;
- newrhs = digest_init (lhstype, newrhs);
+ newrhs = digest_init (lhstype, newrhs, complain);
}
else if (!same_or_base_type_p (TYPE_MAIN_VARIANT (lhstype),
#include "diagnostic-core.h"
static tree
-process_init_constructor (tree type, tree init);
+process_init_constructor (tree type, tree init, tsubst_flags_t complain);
/* Print an error message stemming from an attempt to use
}
if (!ok)
- permerror (input_location, "narrowing conversion of %qE from %qT to %qT inside { }",
- init, ftype, type);
+ permerror (input_location, "narrowing conversion of %qE from %qT "
+ "to %qT inside { }", init, ftype, type);
}
/* Process the initializer INIT for a variable of type TYPE, emitting
NESTED is true iff we are being called for an element of a CONSTRUCTOR. */
static tree
-digest_init_r (tree type, tree init, bool nested, int flags)
+digest_init_r (tree type, tree init, bool nested, int flags,
+ tsubst_flags_t complain)
{
enum tree_code code = TREE_CODE (type);
{
if (char_type != char_type_node)
{
- error ("char-array initialized from wide string");
+ if (complain & tf_error)
+ error ("char-array initialized from wide string");
return error_mark_node;
}
}
{
if (char_type == char_type_node)
{
- error ("int-array initialized from non-wide string");
+ if (complain & tf_error)
+ error ("int-array initialized from non-wide string");
return error_mark_node;
}
else if (char_type != typ1)
{
- error ("int-array initialized from incompatible wide string");
+ if (complain & tf_error)
+ error ("int-array initialized from incompatible "
+ "wide string");
return error_mark_node;
}
}
counted in the length of the constant, but in C++ this would
be invalid. */
if (size < TREE_STRING_LENGTH (init))
- permerror (input_location, "initializer-string for array of chars is too long");
+ permerror (input_location, "initializer-string for array "
+ "of chars is too long");
}
return init;
}
check_narrowing (type, init);
init = convert_for_initialization (0, type, init, flags,
ICR_INIT, NULL_TREE, 0,
- tf_warning_or_error);
+ complain);
exp = &init;
/* Skip any conversions since we'll be outputting the underlying
if (BRACE_ENCLOSED_INITIALIZER_P (init)
&& !TYPE_NON_AGGREGATE_CLASS (type))
- return process_init_constructor (type, init);
+ return process_init_constructor (type, init, complain);
else
{
if (COMPOUND_LITERAL_P (init) && TREE_CODE (type) == ARRAY_TYPE)
{
- error ("cannot initialize aggregate of type %qT with "
- "a compound literal", type);
+ if (complain & tf_error)
+ error ("cannot initialize aggregate of type %qT with "
+ "a compound literal", type);
return error_mark_node;
}
(type, TREE_TYPE (init))))
return init;
- error ("array must be initialized with a brace-enclosed"
- " initializer");
+ if (complain & tf_error)
+ error ("array must be initialized with a brace-enclosed"
+ " initializer");
return error_mark_node;
}
return convert_for_initialization (NULL_TREE, type, init,
flags,
ICR_INIT, NULL_TREE, 0,
- tf_warning_or_error);
+ complain);
}
}
tree
-digest_init (tree type, tree init)
+digest_init (tree type, tree init, tsubst_flags_t complain)
{
- return digest_init_r (type, init, false, LOOKUP_IMPLICIT);
+ return digest_init_r (type, init, false, LOOKUP_IMPLICIT, complain);
}
tree
digest_init_flags (tree type, tree init, int flags)
{
- return digest_init_r (type, init, false, flags);
+ return digest_init_r (type, init, false, flags, tf_warning_or_error);
}
\f
/* Set of flags used within process_init_constructor to describe the
which describe the initializers. */
static int
-process_init_constructor_array (tree type, tree init)
+process_init_constructor_array (tree type, tree init,
+ tsubst_flags_t complain)
{
unsigned HOST_WIDE_INT i, len = 0;
int flags = 0;
/* There must not be more initializers than needed. */
if (!unbounded && VEC_length (constructor_elt, v) > len)
- error ("too many initializers for %qT", type);
+ {
+ if (complain & tf_error)
+ error ("too many initializers for %qT", type);
+ else
+ return PICFLAG_ERRONEOUS;
+ }
FOR_EACH_VEC_ELT (constructor_elt, v, i, ce)
{
else
ce->index = size_int (i);
gcc_assert (ce->value);
- ce->value = digest_init_r (TREE_TYPE (type), ce->value, true, LOOKUP_IMPLICIT);
+ ce->value = digest_init_r (TREE_TYPE (type), ce->value, true,
+ LOOKUP_IMPLICIT, complain);
if (ce->value != error_mark_node)
gcc_assert (same_type_ignoring_top_level_qualifiers_p
one up; if it's an array, recurse. */
if (MAYBE_CLASS_TYPE_P (TREE_TYPE (type)))
next = build_functional_cast (TREE_TYPE (type), NULL_TREE,
- tf_warning_or_error);
+ complain);
else
next = build_constructor (init_list_type_node, NULL);
- next = digest_init (TREE_TYPE (type), next);
+ next = digest_init (TREE_TYPE (type), next, complain);
}
else if (!zero_init_p (TREE_TYPE (type)))
next = build_zero_init (TREE_TYPE (type),
the initializers. */
static int
-process_init_constructor_record (tree type, tree init)
+process_init_constructor_record (tree type, tree init,
+ tsubst_flags_t complain)
{
VEC(constructor_elt,gc) *v = NULL;
int flags = 0;
}
gcc_assert (ce->value);
- next = digest_init_r (type, ce->value, true, LOOKUP_IMPLICIT);
+ next = digest_init_r (type, ce->value, true,
+ LOOKUP_IMPLICIT, complain);
++idx;
}
else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field)))
if (MAYBE_CLASS_TYPE_P (TREE_TYPE (field)))
{
next = finish_compound_literal (TREE_TYPE (field), next,
- tf_warning_or_error);
+ complain);
/* direct-initialize the target. No temporary is going
to be involved. */
if (TREE_CODE (next) == TARGET_EXPR)
TARGET_EXPR_DIRECT_INIT_P (next) = true;
}
- next = digest_init_r (TREE_TYPE (field), next, true, LOOKUP_IMPLICIT);
+ next = digest_init_r (TREE_TYPE (field), next, true,
+ LOOKUP_IMPLICIT, complain);
/* Warn when some struct elements are implicitly initialized. */
warning (OPT_Wmissing_field_initializers,
else
{
if (TREE_READONLY (field))
- error ("uninitialized const member %qD", field);
+ {
+ if (complain & tf_error)
+ error ("uninitialized const member %qD", field);
+ else
+ return PICFLAG_ERRONEOUS;
+ }
else if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (TREE_TYPE (field)))
- error ("member %qD with uninitialized const fields", field);
+ {
+ if (complain & tf_error)
+ error ("member %qD with uninitialized const fields", field);
+ else
+ return PICFLAG_ERRONEOUS;
+ }
else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE)
- error ("member %qD is uninitialized reference", field);
+ {
+ if (complain & tf_error)
+ error ("member %qD is uninitialized reference", field);
+ else
+ return PICFLAG_ERRONEOUS;
+ }
/* Warn when some struct elements are implicitly initialized
to zero. */
}
if (idx < VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init)))
- error ("too many initializers for %qT", type);
-
+ {
+ if (complain & tf_error)
+ error ("too many initializers for %qT", type);
+ else
+ return PICFLAG_ERRONEOUS;
+ }
+
CONSTRUCTOR_ELTS (init) = v;
return flags;
}
which describe the initializer. */
static int
-process_init_constructor_union (tree type, tree init)
+process_init_constructor_union (tree type, tree init,
+ tsubst_flags_t complain)
{
constructor_elt *ce;
int len;
len = VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init));
if (len > 1)
{
+ if (!(complain & tf_error))
+ return PICFLAG_ERRONEOUS;
error ("too many initializers for %qT", type);
VEC_block_remove (constructor_elt, CONSTRUCTOR_ELTS (init), 1, len-1);
}
break;
if (!field)
{
- error ("no field %qD found in union being initialized", field);
+ if (complain & tf_error)
+ error ("no field %qD found in union being initialized",
+ field);
ce->value = error_mark_node;
}
ce->index = field;
{
gcc_assert (TREE_CODE (ce->index) == INTEGER_CST
|| TREE_CODE (ce->index) == RANGE_EXPR);
- error ("index value instead of field name in union initializer");
+ if (complain & tf_error)
+ error ("index value instead of field name in union initializer");
ce->value = error_mark_node;
}
}
field = TREE_CHAIN (field);
if (field == NULL_TREE)
{
- error ("too many initializers for %qT", type);
+ if (complain & tf_error)
+ error ("too many initializers for %qT", type);
ce->value = error_mark_node;
}
ce->index = field;
}
if (ce->value && ce->value != error_mark_node)
- ce->value = digest_init_r (TREE_TYPE (ce->index), ce->value, true, LOOKUP_IMPLICIT);
+ ce->value = digest_init_r (TREE_TYPE (ce->index), ce->value,
+ true, LOOKUP_IMPLICIT, complain);
return picflag_from_initializer (ce->value);
}
of error. */
static tree
-process_init_constructor (tree type, tree init)
+process_init_constructor (tree type, tree init, tsubst_flags_t complain)
{
int flags;
gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init));
if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == VECTOR_TYPE)
- flags = process_init_constructor_array (type, init);
+ flags = process_init_constructor_array (type, init, complain);
else if (TREE_CODE (type) == RECORD_TYPE)
- flags = process_init_constructor_record (type, init);
+ flags = process_init_constructor_record (type, init, complain);
else if (TREE_CODE (type) == UNION_TYPE)
- flags = process_init_constructor_union (type, init);
+ flags = process_init_constructor_union (type, init, complain);
else
gcc_unreachable ();
+2011-05-09 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/48737
+ PR c++/48744
+ * g++.dg/template/sfinae28.C: New.
+ * g++.dg/template/sfinae29.C: Likewise.
+
2011-05-09 Jason Merrill <jason@redhat.com>
* g++.dg/template/nontype23.C: New.
--- /dev/null
+// PR c++/48737
+// { dg-options "-std=c++0x" }
+
+template<class T>
+T&& create();
+
+template<class T, class... Args>
+decltype(T{create<Args>()...}, char()) f(int);
+
+template<class, class...>
+char (&f(...))[2];
+
+static_assert(sizeof(f<int[1], int, int>(0)) != 1, "Error");
--- /dev/null
+// PR c++/48744
+// { dg-options "-std=c++0x" }
+
+template<class T>
+struct add_rval_ref {
+ typedef T&& type;
+};
+
+template<>
+struct add_rval_ref<void> {
+ typedef void type;
+};
+
+template<class T>
+typename add_rval_ref<T>::type create();
+
+template<class T, class Arg>
+decltype(T{create<Arg>()}, char()) f(int);
+
+template<class, class>
+char (&f(...))[2];
+
+static_assert(sizeof(f<int, void>(0)) != 1, "Error");