From 754af126c04251c045d99b808915d9fde11de8a5 Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Mon, 9 May 2011 19:24:50 +0000 Subject: [PATCH] re PR c++/48737 ([C++0x][SFINAE] Hard errors with array list-construction with too many elements) /cp 2011-05-09 Paolo Carlini 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. /testsuite 2011-05-09 Paolo Carlini PR c++/48737 PR c++/48744 * g++.dg/template/sfinae28.C: New. * g++.dg/template/sfinae29.C: Likewise. From-SVN: r173590 --- gcc/cp/ChangeLog | 24 ++++- gcc/cp/call.c | 4 +- gcc/cp/cp-tree.h | 4 +- gcc/cp/decl.c | 68 +++++++----- gcc/cp/decl2.c | 2 +- gcc/cp/init.c | 4 +- gcc/cp/semantics.c | 4 +- gcc/cp/typeck.c | 2 +- gcc/cp/typeck2.c | 128 +++++++++++++++-------- gcc/testsuite/ChangeLog | 7 ++ gcc/testsuite/g++.dg/template/sfinae28.C | 13 +++ gcc/testsuite/g++.dg/template/sfinae29.C | 23 ++++ 12 files changed, 206 insertions(+), 77 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/sfinae28.C create mode 100644 gcc/testsuite/g++.dg/template/sfinae29.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 04096deee9c..b89280dbda3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,27 @@ +2011-05-09 Paolo Carlini + + 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 - + PR c++/48859 * init.c (diagnose_uninitialized_cst_or_ref_member_1): stop the recursion if there is user defined constructor. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 3a71572b67d..095d1b0cb29 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -5670,7 +5670,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, 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; @@ -6032,7 +6032,7 @@ convert_default_arg (tree type, tree arg, tree fn, int parmnum) 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); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index a03d6a11bca..53092ffc6e7 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4903,7 +4903,7 @@ extern tree cxx_comdat_group (tree); 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; @@ -5669,7 +5669,7 @@ extern int abstract_virtuals_error_sfinae (tree, tree, tsubst_flags_t); 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); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index c255e16c6da..ab36d18552a 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -4878,7 +4878,7 @@ typedef struct reshape_iterator_t 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 @@ -4904,7 +4904,8 @@ next_initializable_field (tree field) 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); @@ -4936,7 +4937,8 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d) 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), @@ -4952,7 +4954,7 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d) 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; @@ -4961,14 +4963,14 @@ reshape_init_array (tree type, reshape_iter *d) 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; @@ -4979,8 +4981,9 @@ reshape_init_vector (tree type, reshape_iter *d) 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; @@ -4991,14 +4994,15 @@ reshape_init_vector (tree type, reshape_iter *d) 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; @@ -5018,7 +5022,8 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p) 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; @@ -5036,8 +5041,9 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p) 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; } } @@ -5047,7 +5053,7 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p) 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; @@ -5074,7 +5080,8 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p) 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; @@ -5089,7 +5096,12 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p) 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) { @@ -5116,7 +5128,8 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p) { 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 @@ -5203,7 +5216,7 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p) { ++d->cur; gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init)); - return reshape_init (type, init); + return reshape_init (type, init, complain); } } @@ -5213,11 +5226,11 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p) /* 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(); } @@ -5238,7 +5251,7 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p) 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; @@ -5257,14 +5270,19 @@ reshape_init (tree type, tree init) 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; } @@ -5417,7 +5435,7 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup) 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 diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 2e08dd730d9..91a66443bc8 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -924,7 +924,7 @@ grokfield (const cp_declarator *declarator, 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)) diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 3eb804dd56a..b71ddfc0f9f 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1435,7 +1435,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, { /* 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); @@ -2378,7 +2378,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, "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) { diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index d33f9fe16a9..0ba0370833b 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2369,7 +2369,7 @@ finish_compound_literal (tree type, tree compound_literal, 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) { @@ -2378,7 +2378,7 @@ finish_compound_literal (tree type, tree compound_literal, 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)) diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 4d0c0d7b06b..d98c62bb940 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -6715,7 +6715,7 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs, } 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), diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index aec54f9d07f..ec6b5d37850 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -39,7 +39,7 @@ along with GCC; see the file COPYING3. If not see #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 @@ -783,8 +783,8 @@ check_narrowing (tree type, tree init) } 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 @@ -797,7 +797,8 @@ check_narrowing (tree type, tree init) 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); @@ -833,7 +834,8 @@ digest_init_r (tree type, tree init, bool nested, int flags) { 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; } } @@ -841,12 +843,15 @@ digest_init_r (tree type, tree init, bool nested, int flags) { 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; } } @@ -861,7 +866,8 @@ digest_init_r (tree type, tree init, bool nested, int flags) 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; } @@ -878,7 +884,7 @@ digest_init_r (tree type, tree init, bool nested, int flags) 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 @@ -902,13 +908,14 @@ digest_init_r (tree type, tree init, bool nested, int flags) 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; } @@ -924,28 +931,29 @@ digest_init_r (tree type, tree init, bool nested, int flags) (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); } /* Set of flags used within process_init_constructor to describe the @@ -974,7 +982,8 @@ picflag_from_initializer (tree init) 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; @@ -1001,7 +1010,12 @@ process_init_constructor_array (tree type, tree init) /* 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) { @@ -1017,7 +1031,8 @@ process_init_constructor_array (tree type, tree init) 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 @@ -1041,10 +1056,10 @@ process_init_constructor_array (tree type, tree init) 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), @@ -1068,7 +1083,8 @@ process_init_constructor_array (tree type, tree init) 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; @@ -1124,7 +1140,8 @@ process_init_constructor_record (tree type, tree init) } 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))) @@ -1137,14 +1154,15 @@ process_init_constructor_record (tree type, tree init) 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, @@ -1153,11 +1171,26 @@ process_init_constructor_record (tree type, tree init) 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. */ @@ -1181,8 +1214,13 @@ process_init_constructor_record (tree type, tree init) } 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; } @@ -1192,7 +1230,8 @@ process_init_constructor_record (tree type, tree init) 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; @@ -1204,6 +1243,8 @@ process_init_constructor_union (tree type, tree init) 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); } @@ -1225,7 +1266,9 @@ process_init_constructor_union (tree type, tree init) 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; @@ -1234,7 +1277,8 @@ process_init_constructor_union (tree type, tree init) { 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; } } @@ -1247,14 +1291,16 @@ process_init_constructor_union (tree type, tree init) 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); } @@ -1274,18 +1320,18 @@ process_init_constructor_union (tree type, tree init) 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 (); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4b4bd93cd11..82478ea5c0e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2011-05-09 Paolo Carlini + + PR c++/48737 + PR c++/48744 + * g++.dg/template/sfinae28.C: New. + * g++.dg/template/sfinae29.C: Likewise. + 2011-05-09 Jason Merrill * g++.dg/template/nontype23.C: New. diff --git a/gcc/testsuite/g++.dg/template/sfinae28.C b/gcc/testsuite/g++.dg/template/sfinae28.C new file mode 100644 index 00000000000..be96983bf39 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/sfinae28.C @@ -0,0 +1,13 @@ +// PR c++/48737 +// { dg-options "-std=c++0x" } + +template +T&& create(); + +template +decltype(T{create()...}, char()) f(int); + +template +char (&f(...))[2]; + +static_assert(sizeof(f(0)) != 1, "Error"); diff --git a/gcc/testsuite/g++.dg/template/sfinae29.C b/gcc/testsuite/g++.dg/template/sfinae29.C new file mode 100644 index 00000000000..486064c3af7 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/sfinae29.C @@ -0,0 +1,23 @@ +// PR c++/48744 +// { dg-options "-std=c++0x" } + +template +struct add_rval_ref { + typedef T&& type; +}; + +template<> +struct add_rval_ref { + typedef void type; +}; + +template +typename add_rval_ref::type create(); + +template +decltype(T{create()}, char()) f(int); + +template +char (&f(...))[2]; + +static_assert(sizeof(f(0)) != 1, "Error");