commit d8489e38cc7e65238665e0321650f356509cb03e Author: Jason Merrill Date: Thu Apr 7 17:11:44 2011 -0400 * init.c (build_value_init_noctor): Handle REFERENCE_TYPE at top level. (perform_member_init): Not here. * typeck2.c (build_functional_cast): Limit REFERENCE_TYPE special case to templates. (abstract_virtuals_error_sfinae): Remove RESULT_DECL special case. diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 2e9eb680..005f8d6 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -388,14 +388,6 @@ build_value_init_noctor (tree type, tsubst_flags_t complain) ftype = TREE_TYPE (field); - if (TREE_CODE (ftype) == REFERENCE_TYPE) - { - if (complain & tf_error) - error ("value-initialization of reference"); - else - return error_mark_node; - } - /* We could skip vfields and fields of types with user-defined constructors, but I think that won't improve performance at all; it should be simpler in general just @@ -408,6 +400,9 @@ build_value_init_noctor (tree type, tsubst_flags_t complain) all of the subobjects. */ value = build_value_init (ftype, complain); + if (value == error_mark_node) + return error_mark_node; + if (value) CONSTRUCTOR_APPEND_ELT(v, field, value); } @@ -450,6 +445,9 @@ build_value_init_noctor (tree type, tsubst_flags_t complain) ce->value = build_value_init (TREE_TYPE (type), complain); + if (ce->value == error_mark_node) + return error_mark_node; + /* The gimplifier can't deal with a RANGE_EXPR of TARGET_EXPRs. */ gcc_assert (TREE_CODE (ce->value) != TARGET_EXPR && TREE_CODE (ce->value) != AGGR_INIT_EXPR); @@ -464,6 +462,12 @@ build_value_init_noctor (tree type, tsubst_flags_t complain) error ("value-initialization of function type %qT", type); return error_mark_node; } + else if (TREE_CODE (type) == REFERENCE_TYPE) + { + if (complain & tf_error) + error ("value-initialization of reference type %qT", type); + return error_mark_node; + } return build_zero_init (type, NULL_TREE, /*static_storage_p=*/false); } @@ -504,16 +508,9 @@ perform_member_init (tree member, tree init) } else { - if (TREE_CODE (type) == REFERENCE_TYPE) - permerror (DECL_SOURCE_LOCATION (current_function_decl), - "value-initialization of %q#D, which has reference type", - member); - else - { - init = build2 (INIT_EXPR, type, decl, - build_value_init (type, tf_warning_or_error)); - finish_expr_stmt (init); - } + init = build2 (INIT_EXPR, type, decl, + build_value_init (type, tf_warning_or_error)); + finish_expr_stmt (init); } } /* Deal with this here, as we will get confused if we try to call the diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index f2046f7..f3a0079 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -301,9 +301,6 @@ abstract_virtuals_error_sfinae (tree decl, tree type, tsubst_flags_t complain) if (!pure) return 0; - if (decl && TREE_CODE (decl) == RESULT_DECL) - return 0; - if (!(complain & tf_error)) return 1; @@ -1536,16 +1533,21 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain) else type = exp; - if (TREE_CODE (type) == REFERENCE_TYPE && !parms) - { - if (complain & tf_error) - error ("invalid value-initialization of reference type"); - return error_mark_node; - } - if (processing_template_decl) { - tree t = build_min (CAST_EXPR, type, parms); + tree t; + + /* Diagnose this even in a template. We could also try harder + to give all the usual errors when the type and args are + non-dependent... */ + if (TREE_CODE (type) == REFERENCE_TYPE && !parms) + { + if (complain & tf_error) + error ("invalid value-initialization of reference type"); + return error_mark_node; + } + + t = build_min (CAST_EXPR, type, parms); /* We don't know if it will or will not have side effects. */ TREE_SIDE_EFFECTS (t) = 1; return t;