diff options
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 95 | ||||
-rw-r--r-- | gcc/cp/call.c | 9 | ||||
-rw-r--r-- | gcc/cp/class.c | 8 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 17 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 22 | ||||
-rw-r--r-- | gcc/cp/decl.c | 33 | ||||
-rw-r--r-- | gcc/cp/expr.c | 2 | ||||
-rw-r--r-- | gcc/cp/init.c | 9 | ||||
-rw-r--r-- | gcc/cp/parser.c | 75 | ||||
-rw-r--r-- | gcc/cp/pt.c | 10 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 85 | ||||
-rw-r--r-- | gcc/cp/tree.c | 16 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 105 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 56 |
14 files changed, 408 insertions, 134 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b2360d5..0ebc366 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,98 @@ +2018-12-19 David Malcolm <dmalcolm@redhat.com> + + PR c++/43064 + PR c++/43486 + * call.c (build_conditional_expr_1): Strip location wrappers when + checking for CONST_DECL. + (conversion_null_warnings): Use location of "expr" if available. + * class.c (fixed_type_or_null): Handle location wrappers. + * constexpr.c (potential_constant_expression_1): Likewise. + * cvt.c (ignore_overflows): Strip location wrappers when + checking for INTEGER_CST, and re-wrap the result if present. + (ocp_convert): Call fold_for_warn before checking for INTEGER_CST. + * decl.c (reshape_init_r): Strip any location wrapper. + (undeduced_auto_decl): Likewise. + * expr.c (mark_discarded_use): Likewise for expr. + * init.c (build_aggr_init): Likewise before checking init for + DECL_P. + (warn_placement_new_too_small): Call fold_for_warn on adj before + checking for CONSTANT_CLASS_P, and on nelts. Strip any location + wrapper from op0 and on oper before checking for VAR_P. + * parser.c (cp_parser_primary_expression): Call + maybe_add_location_wrapper on numeric and string literals. + (cp_parser_postfix_expression): Strip any location wrapper when + checking for DECL_IS_BUILTIN_CONSTANT_P. + (cp_parser_unary_expression): Ensure that folding of NEGATE_EXPR + around a constant happens in the presence of location wrappers and + returns a wrapped result. + (cp_parser_has_attribute_expression): Strip any location wrapper + from "oper". + (cp_parser_binary_expression): Strip any location wrapper when + checking for DECL_P on the lhs. + (cp_parser_decltype): Strip any location wrapper from result of + cp_parser_decltype_expr. + (cp_parser_mem_initializer): Add location wrappers to the + parenthesized expression list. + (cp_parser_template_parameter_list): Don't create wrapper nodes + within a template-parameter-list. + (cp_parser_template_argument_list): Don't create wrapper nodes + within a template-argument-list. + (cp_parser_parameter_declaration): Strip location wrappers from + default arguments. + (cp_parser_gnu_attribute_list): Don't create wrapper nodes. + (cp_parser_std_attribute_spec_seq): Likewise. + (cp_parser_omp_all_clauses): Don't create wrapper nodes within + OpenMP clauses. + (cp_parser_omp_for_loop): Likewise. + (cp_parser_omp_declare_reduction_exprs): Likewise. + * pt.c (convert_nontype_argument_function): Strip location + wrappers from fn_no_ptr before checking for FUNCTION_DECL. + (tsubst_default_argument): Move note about which callsite led to + instantiation to after the check_default_argument call. + (do_auto_deduction): Likewise from init before checking for + DECL_P. + * semantics.c (force_paren_expr): Likewise from expr before + checking for DECL_P. + (finish_parenthesized_expr): Likewise from expr before + checking for STRING_CST. + (perform_koenig_lookup): Likewise from fn. + (finish_call_expr): Likewise. + (finish_id_expression): Rename to... + (finish_id_expression_1): ...this, calling + maybe_add_location_wrapper on the result. + (capture_decltype): Use lookup_name_real rather than value_member + when looking up decl within the capture-list. + * tree.c (cp_stabilize_reference): Strip any location wrapper. + (builtin_valid_in_constant_expr_p): Likewise. + (strip_typedefs_expr): Strip any location wrapper before checking + for decls or constants. + (is_overloaded_fn): Likewise. + (maybe_get_fns): Likewise. + (selftest::test_lvalue_kind): Verify lvalue_p. + * typeck.c (cxx_sizeof_expr): Strip any location wrapper. + (cxx_alignof_expr): Likewise. + (is_bitfield_expr_with_lowered_type): Handle location wrappers. + (cp_build_array_ref): Call maybe_constant_value on "idx". + (cp_build_binary_op): Strip location wrapper from first_arg before + checking for PARM_DECL. Likewise for op1 before checking for + INTEGER_CST in two places. Likewise for orig_op0 and orig_op1 + when checking for STRING_CST. + (cp_build_addr_expr_1): Likewise for arg when checking for + FUNCTION_DECL. + (cp_build_modify_expr): Likewise for newrhs when checking for + STRING_CST. + (convert_for_assignment): Don't strip location wrappers when + stripping NON_LVALUE_EXPR. + (maybe_warn_about_returning_address_of_local): Strip location + wrapper from whats_returned before checking for DECL_P. + (can_do_nrvo_p): Strip location wrapper from retval. + (treat_lvalue_as_rvalue_p): Likewise. + (check_return_expr): Likewise. + * typeck2.c (cxx_incomplete_type_diagnostic): Strip location + wrapper from value before checking for VAR_P or PARM_DECL. + (digest_init_r): Strip location wrapper from init. When + copying "init", also copy the wrapped node. + 2018-12-19 Jakub Jelinek <jakub@redhat.com> PR c++/87934 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 6328a36..ef3a02c 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -5347,9 +5347,12 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3, if (TREE_CODE (arg2_type) == ENUMERAL_TYPE && TREE_CODE (arg3_type) == ENUMERAL_TYPE) { - if (TREE_CODE (orig_arg2) == CONST_DECL - && TREE_CODE (orig_arg3) == CONST_DECL - && DECL_CONTEXT (orig_arg2) == DECL_CONTEXT (orig_arg3)) + tree stripped_orig_arg2 = tree_strip_any_location_wrapper (orig_arg2); + tree stripped_orig_arg3 = tree_strip_any_location_wrapper (orig_arg3); + if (TREE_CODE (stripped_orig_arg2) == CONST_DECL + && TREE_CODE (stripped_orig_arg3) == CONST_DECL + && (DECL_CONTEXT (stripped_orig_arg2) + == DECL_CONTEXT (stripped_orig_arg3))) /* Two enumerators from the same enumeration can have different types when the enumeration is still being defined. */; else if (complain & tf_warning) diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 36e1757..5d6e12f 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -7388,6 +7388,14 @@ fixed_type_or_null (tree instance, int *nonnull, int *cdtorp) } return NULL_TREE; + case VIEW_CONVERT_EXPR: + if (location_wrapper_p (instance)) + return RECUR (TREE_OPERAND (instance, 0)); + else + /* TODO: Recursion may be correct for some non-location-wrapper + uses of VIEW_CONVERT_EXPR. */ + return NULL_TREE; + default: return NULL_TREE; } diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 79df70e..15a30fd 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -5762,13 +5762,18 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, may change to something more specific to type-punning (DR 1312). */ { tree from = TREE_OPERAND (t, 0); - if (INDIRECT_TYPE_P (TREE_TYPE (t)) - && TREE_CODE (from) == INTEGER_CST - && !integer_zerop (from)) + if (location_wrapper_p (t)) + return (RECUR (from, want_rval)); + if (INDIRECT_TYPE_P (TREE_TYPE (t))) { - if (flags & tf_error) - error_at (loc, "reinterpret_cast from integer to pointer"); - return false; + STRIP_ANY_LOCATION_WRAPPER (from); + if (TREE_CODE (from) == INTEGER_CST + && !integer_zerop (from)) + { + if (flags & tf_error) + error_at (loc, "reinterpret_cast from integer to pointer"); + return false; + } } return (RECUR (from, TREE_CODE (t) != VIEW_CONVERT_EXPR)); } diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index eb16873..f758f2d 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -582,15 +582,20 @@ force_rvalue (tree expr, tsubst_flags_t complain) static tree ignore_overflows (tree expr, tree orig) { - if (TREE_CODE (expr) == INTEGER_CST - && TREE_CODE (orig) == INTEGER_CST - && TREE_OVERFLOW (expr) != TREE_OVERFLOW (orig)) + tree stripped_expr = tree_strip_any_location_wrapper (expr); + tree stripped_orig = tree_strip_any_location_wrapper (orig); + + if (TREE_CODE (stripped_expr) == INTEGER_CST + && TREE_CODE (stripped_orig) == INTEGER_CST + && TREE_OVERFLOW (stripped_expr) != TREE_OVERFLOW (stripped_orig)) { - gcc_assert (!TREE_OVERFLOW (orig)); + gcc_assert (!TREE_OVERFLOW (stripped_orig)); /* Ensure constant sharing. */ - expr = wide_int_to_tree (TREE_TYPE (expr), wi::to_wide (expr)); + stripped_expr = wide_int_to_tree (TREE_TYPE (stripped_expr), + wi::to_wide (stripped_expr)); } - return expr; + + return preserve_any_location_wrapper (stripped_expr, expr); } /* Fold away simple conversions, but make sure TREE_OVERFLOW is set @@ -800,10 +805,11 @@ ocp_convert (tree type, tree expr, int convtype, int flags, the original value is within the range of the enumeration values. Otherwise, the resulting enumeration value is unspecified. */ + tree val = fold_for_warn (e); if ((complain & tf_warning) - && TREE_CODE (e) == INTEGER_CST + && TREE_CODE (val) == INTEGER_CST && ENUM_UNDERLYING_TYPE (type) - && !int_fits_type_p (e, ENUM_UNDERLYING_TYPE (type))) + && !int_fits_type_p (val, ENUM_UNDERLYING_TYPE (type))) warning_at (loc, OPT_Wconversion, "the result of the conversion is unspecified because " "%qE is outside the range of type %qT", diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index d6028e3..056bf19 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -6010,14 +6010,16 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p, && has_designator_problem (d, complain)) return error_mark_node; + tree stripped_init = tree_strip_any_location_wrapper (init); + if (TREE_CODE (type) == COMPLEX_TYPE) { /* A complex type can be initialized from one or two initializers, but braces are not elided. */ d->cur++; - if (BRACE_ENCLOSED_INITIALIZER_P (init)) + if (BRACE_ENCLOSED_INITIALIZER_P (stripped_init)) { - if (CONSTRUCTOR_NELTS (init) > 2) + if (CONSTRUCTOR_NELTS (stripped_init) > 2) { if (complain & tf_error) error ("too many initializers for %qT", type); @@ -6047,16 +6049,16 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p, We need to check for BRACE_ENCLOSED_INITIALIZER_P here because of g++.old-deja/g++.mike/p7626.C: a pointer-to-member constant is a CONSTRUCTOR (with a record type). */ - if (TREE_CODE (init) == CONSTRUCTOR + if (TREE_CODE (stripped_init) == CONSTRUCTOR /* Don't complain about a capture-init. */ - && !CONSTRUCTOR_IS_DIRECT_INIT (init) - && BRACE_ENCLOSED_INITIALIZER_P (init)) /* p7626.C */ + && !CONSTRUCTOR_IS_DIRECT_INIT (stripped_init) + && BRACE_ENCLOSED_INITIALIZER_P (stripped_init)) /* p7626.C */ { if (SCALAR_TYPE_P (type)) { if (cxx_dialect < cxx11 /* Isn't value-initialization. */ - || CONSTRUCTOR_NELTS (init) > 0) + || CONSTRUCTOR_NELTS (stripped_init) > 0) { if (complain & tf_error) error ("braces around scalar initializer for type %qT", @@ -6116,20 +6118,22 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p, && char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type)))) { tree str_init = init; + tree stripped_str_init = stripped_init; /* Strip one level of braces if and only if they enclose a single element (as allowed by [dcl.init.string]). */ if (!first_initializer_p - && TREE_CODE (str_init) == CONSTRUCTOR - && CONSTRUCTOR_NELTS (str_init) == 1) + && TREE_CODE (stripped_str_init) == CONSTRUCTOR + && CONSTRUCTOR_NELTS (stripped_str_init) == 1) { - str_init = (*CONSTRUCTOR_ELTS (str_init))[0].value; + str_init = (*CONSTRUCTOR_ELTS (stripped_str_init))[0].value; + stripped_str_init = tree_strip_any_location_wrapper (str_init); } /* If it's a string literal, then it's the initializer for the array as a whole. Otherwise, continue with normal initialization for array types (one value per array element). */ - if (TREE_CODE (str_init) == STRING_CST) + if (TREE_CODE (stripped_str_init) == STRING_CST) { if (has_designator_problem (d, complain)) return error_mark_node; @@ -6144,24 +6148,24 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p, which reshape_init exists). */ if (!first_initializer_p) { - if (TREE_CODE (init) == CONSTRUCTOR) + if (TREE_CODE (stripped_init) == CONSTRUCTOR) { if (TREE_TYPE (init) && TYPE_PTRMEMFUNC_P (TREE_TYPE (init))) /* There is no need to reshape pointer-to-member function initializers, as they are always constructed correctly by the front end. */ ; - else if (COMPOUND_LITERAL_P (init)) + else if (COMPOUND_LITERAL_P (stripped_init)) /* For a nested compound literal, there is no need to reshape since brace elision is not allowed. Even if we decided to allow it, we should add a call to reshape_init in finish_compound_literal, before calling digest_init, so changing this code would still not be necessary. */ - gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (init)); + gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init)); else { ++d->cur; - gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init)); + gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (stripped_init)); return reshape_init (type, init, complain); } } @@ -16593,6 +16597,7 @@ undeduced_auto_decl (tree decl) { if (cxx_dialect < cxx11) return false; + STRIP_ANY_LOCATION_WRAPPER (decl); return ((VAR_OR_FUNCTION_DECL_P (decl) || TREE_CODE (decl) == TEMPLATE_DECL) && type_uses_auto (TREE_TYPE (decl))); diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c index 93477bc..8163866 100644 --- a/gcc/cp/expr.c +++ b/gcc/cp/expr.c @@ -263,6 +263,8 @@ mark_discarded_use (tree expr) if (expr == NULL_TREE) return expr; + STRIP_ANY_LOCATION_WRAPPER (expr); + switch (TREE_CODE (expr)) { case COND_EXPR: diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 54a1dae..5538eeb 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1756,7 +1756,8 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain) { from_array = 1; init = mark_rvalue_use (init); - if (init && DECL_P (init) + if (init + && DECL_P (tree_strip_any_location_wrapper (init)) && !(flags & LOOKUP_ONLYCONVERTING)) { /* Wrap the initializer in a CONSTRUCTOR so that build_vec_init @@ -2604,6 +2605,7 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper) Otherwise, use the size of the entire array as an optimistic estimate (this may lead to false negatives). */ tree adj = TREE_OPERAND (oper, 1); + adj = fold_for_warn (adj); if (CONSTANT_CLASS_P (adj)) adjust += wi::to_offset (convert (ssizetype, adj)); else @@ -2667,11 +2669,13 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper) tree op0 = oper; while (TREE_CODE (op0 = TREE_OPERAND (op0, 0)) == COMPONENT_REF); + STRIP_ANY_LOCATION_WRAPPER (op0); if (VAR_P (op0)) var_decl = op0; oper = TREE_OPERAND (oper, 1); } + STRIP_ANY_LOCATION_WRAPPER (oper); tree opertype = TREE_TYPE (oper); if ((addr_expr || !INDIRECT_TYPE_P (opertype)) && (VAR_P (oper) @@ -2762,6 +2766,9 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper) others. */ offset_int bytes_need; + if (nelts) + nelts = fold_for_warn (nelts); + if (CONSTANT_CLASS_P (size)) bytes_need = wi::to_offset (size); else if (nelts && CONSTANT_CLASS_P (nelts)) diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index b57e35d..c0552b5 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -5232,7 +5232,8 @@ cp_parser_primary_expression (cp_parser *parser, if (!cast_p) cp_parser_non_integral_constant_expression (parser, NIC_FLOAT); } - return cp_expr (token->u.value, token->location); + return (cp_expr (token->u.value, token->location) + .maybe_add_location_wrapper ()); case CPP_CHAR_USERDEF: case CPP_CHAR16_USERDEF: @@ -5254,9 +5255,10 @@ cp_parser_primary_expression (cp_parser *parser, /* ??? Should wide strings be allowed when parser->translate_strings_p is false (i.e. in attributes)? If not, we can kill the third argument to cp_parser_string_literal. */ - return cp_parser_string_literal (parser, - parser->translate_strings_p, - true); + return (cp_parser_string_literal (parser, + parser->translate_strings_p, + true) + .maybe_add_location_wrapper ()); case CPP_OPEN_PAREN: /* If we see `( { ' then we are looking at the beginning of @@ -7169,8 +7171,10 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, is_member_access = false; + tree stripped_expression + = tree_strip_any_location_wrapper (postfix_expression); is_builtin_constant_p - = DECL_IS_BUILTIN_CONSTANT_P (postfix_expression); + = DECL_IS_BUILTIN_CONSTANT_P (stripped_expression); if (is_builtin_constant_p) { /* The whole point of __builtin_constant_p is to allow @@ -8363,18 +8367,22 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk, case NEGATE_EXPR: /* Immediately fold negation of a constant, unless the constant is 0 (since -0 == 0) or it would overflow. */ - if (unary_operator == NEGATE_EXPR && op_ttype == CPP_NUMBER - && CONSTANT_CLASS_P (cast_expression) - && !integer_zerop (cast_expression) - && !TREE_OVERFLOW (cast_expression)) + if (unary_operator == NEGATE_EXPR && op_ttype == CPP_NUMBER) { - tree folded = fold_build1 (unary_operator, - TREE_TYPE (cast_expression), - cast_expression); - if (CONSTANT_CLASS_P (folded) && !TREE_OVERFLOW (folded)) + tree stripped_expr + = tree_strip_any_location_wrapper (cast_expression); + if (CONSTANT_CLASS_P (stripped_expr) + && !integer_zerop (stripped_expr) + && !TREE_OVERFLOW (stripped_expr)) { - expression = cp_expr (folded, loc); - break; + tree folded = fold_build1 (unary_operator, + TREE_TYPE (stripped_expr), + stripped_expr); + if (CONSTANT_CLASS_P (folded) && !TREE_OVERFLOW (folded)) + { + expression = maybe_wrap_with_location (folded, loc); + break; + } } } /* Fall through. */ @@ -8489,6 +8497,8 @@ cp_parser_has_attribute_expression (cp_parser *parser) if (!oper || oper == error_mark_node) oper = cp_parser_unary_expression (parser); + STRIP_ANY_LOCATION_WRAPPER (oper); + /* Go back to evaluating expressions. */ --cp_unevaluated_operand; --c_inhibit_evaluation_warnings; @@ -9508,7 +9518,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p, || (TREE_CODE (TREE_TYPE (TREE_OPERAND (current.lhs, 0))) != BOOLEAN_TYPE)))) /* Avoid warning for !!b == y where b is boolean. */ - && (!DECL_P (current.lhs) + && (!DECL_P (tree_strip_any_location_wrapper (current.lhs)) || TREE_TYPE (current.lhs) == NULL_TREE || TREE_CODE (TREE_TYPE (current.lhs)) != BOOLEAN_TYPE)) warn_logical_not_parentheses (current.loc, current.tree_type, @@ -14546,6 +14556,7 @@ cp_parser_decltype (cp_parser *parser) ++c_inhibit_evaluation_warnings; expr = cp_parser_decltype_expr (parser, id_expression_or_member_access_p); + STRIP_ANY_LOCATION_WRAPPER (expr); /* Go back to evaluating expressions. */ --cp_unevaluated_operand; @@ -14923,7 +14934,9 @@ cp_parser_mem_initializer (cp_parser* parser) vec = cp_parser_parenthesized_expression_list (parser, non_attr, /*cast_p=*/false, /*allow_expansion_p=*/true, - /*non_constant_p=*/NULL); + /*non_constant_p=*/NULL, + /*close_paren_loc=*/NULL, + /*wrap_locations_p=*/true); if (vec == NULL) return error_mark_node; expression_list = build_tree_list_vec (vec); @@ -15464,6 +15477,11 @@ cp_parser_template_parameter_list (cp_parser* parser) { tree parameter_list = NULL_TREE; + /* Don't create wrapper nodes within a template-parameter-list, + since we don't want to have different types based on the + spelling location of constants and decls within them. */ + auto_suppress_location_wrappers sentinel; + begin_template_parm_list (); /* The loop below parses the template parms. We first need to know @@ -16636,6 +16654,9 @@ cp_parser_template_argument_list (cp_parser* parser) bool saved_ice_p; bool saved_non_ice_p; + /* Don't create location wrapper nodes within a template-argument-list. */ + auto_suppress_location_wrappers sentinel; + saved_in_template_argument_list_p = parser->in_template_argument_list_p; parser->in_template_argument_list_p = true; /* Even if the template-id appears in an integral @@ -22313,6 +22334,9 @@ cp_parser_parameter_declaration (cp_parser *parser, else default_argument = NULL_TREE; + if (default_argument) + STRIP_ANY_LOCATION_WRAPPER (default_argument); + /* Generate a location for the parameter, ranging from the start of the initial token to the end of the final token (using input_location for the latter, set up by cp_lexer_set_source_position_from_token when @@ -25661,6 +25685,10 @@ cp_parser_gnu_attribute_list (cp_parser* parser, bool exactly_one /* = false */) tree attribute_list = NULL_TREE; bool save_translate_strings_p = parser->translate_strings_p; + /* Don't create wrapper nodes within attributes: the + handlers don't know how to handle them. */ + auto_suppress_location_wrappers sentinel; + parser->translate_strings_p = false; while (true) { @@ -26106,6 +26134,10 @@ cp_parser_std_attribute_spec_seq (cp_parser *parser) tree attr_specs = NULL_TREE; tree attr_last = NULL_TREE; + /* Don't create wrapper nodes within attributes: the + handlers don't know how to handle them. */ + auto_suppress_location_wrappers sentinel; + while (true) { tree attr_spec = cp_parser_std_attribute_spec (parser); @@ -34880,6 +34912,9 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, bool first = true; cp_token *token = NULL; + /* Don't create location wrapper nodes within OpenMP clauses. */ + auto_suppress_location_wrappers sentinel; + while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)) { pragma_omp_clause c_kind; @@ -36597,6 +36632,10 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, } loc = cp_lexer_consume_token (parser->lexer)->location; + /* Don't create location wrapper nodes within an OpenMP "for" + statement. */ + auto_suppress_location_wrappers sentinel; + matching_parens parens; if (!parens.require_open (parser)) return NULL; @@ -39168,6 +39207,8 @@ cp_parser_omp_declare_reduction_exprs (tree fndecl, cp_parser *parser) else { cp_parser_parse_tentatively (parser); + /* Don't create location wrapper nodes here. */ + auto_suppress_location_wrappers sentinel; tree fn_name = cp_parser_id_expression (parser, /*template_p=*/false, /*check_dependency_p=*/true, /*template_p=*/NULL, diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index e99de71..d4ac034 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -6196,6 +6196,7 @@ convert_nontype_argument_function (tree type, tree expr, -- the address of an object or function with external [C++11: or internal] linkage. */ + STRIP_ANY_LOCATION_WRAPPER (fn_no_ptr); if (TREE_CODE (fn_no_ptr) != FUNCTION_DECL) { if (complain & tf_error) @@ -12756,14 +12757,14 @@ tsubst_default_argument (tree fn, int parmnum, tree type, tree arg, finish_lambda_scope (); + /* Make sure the default argument is reasonable. */ + arg = check_default_argument (type, arg, complain); + if (errorcount+sorrycount > errs && (complain & tf_warning_or_error)) inform (input_location, " when instantiating default argument for call to %qD", fn); - /* Make sure the default argument is reasonable. */ - arg = check_default_argument (type, arg, complain); - pop_access_scope (fn); pop_from_top_level (); @@ -27224,7 +27225,8 @@ do_auto_deduction (tree type, tree init, tree auto_node, complain); else if (AUTO_IS_DECLTYPE (auto_node)) { - bool id = (DECL_P (init) + tree stripped_init = tree_strip_any_location_wrapper (init); + bool id = (DECL_P (stripped_init) || ((TREE_CODE (init) == COMPONENT_REF || TREE_CODE (init) == SCOPE_REF) && !REF_PARENTHESIZED_P (init))); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 09ed97d..0865076 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1742,7 +1742,8 @@ force_paren_expr (tree expr) if (cp_unevaluated_operand) return expr; - if (!DECL_P (expr) && TREE_CODE (expr) != COMPONENT_REF + if (!DECL_P (tree_strip_any_location_wrapper (expr)) + && TREE_CODE (expr) != COMPONENT_REF && TREE_CODE (expr) != SCOPE_REF) return expr; @@ -1805,8 +1806,9 @@ finish_parenthesized_expr (cp_expr expr) enclosed in parentheses. */ PTRMEM_OK_P (expr) = 0; - if (TREE_CODE (expr) == STRING_CST) - PAREN_STRING_LITERAL_P (expr) = 1; + tree stripped_expr = tree_strip_any_location_wrapper (expr); + if (TREE_CODE (stripped_expr) == STRING_CST) + PAREN_STRING_LITERAL_P (stripped_expr) = 1; expr = cp_expr (force_paren_expr (expr), expr.get_location ()); @@ -2299,19 +2301,22 @@ empty_expr_stmt_p (tree expr_stmt) return false; } -/* Perform Koenig lookup. FN is the postfix-expression representing +/* Perform Koenig lookup. FN_EXPR is the postfix-expression representing the function (or functions) to call; ARGS are the arguments to the call. Returns the functions to be considered by overload resolution. */ cp_expr -perform_koenig_lookup (cp_expr fn, vec<tree, va_gc> *args, +perform_koenig_lookup (cp_expr fn_expr, vec<tree, va_gc> *args, tsubst_flags_t complain) { tree identifier = NULL_TREE; tree functions = NULL_TREE; tree tmpl_args = NULL_TREE; bool template_id = false; - location_t loc = fn.get_location (); + location_t loc = fn_expr.get_location (); + tree fn = fn_expr.get_value (); + + STRIP_ANY_LOCATION_WRAPPER (fn); if (TREE_CODE (fn) == TEMPLATE_ID_EXPR) { @@ -2351,7 +2356,7 @@ perform_koenig_lookup (cp_expr fn, vec<tree, va_gc> *args, if (fn && template_id && fn != error_mark_node) fn = build2 (TEMPLATE_ID_EXPR, unknown_type_node, fn, tmpl_args); - return fn; + return cp_expr (fn, loc); } /* Generate an expression for `FN (ARGS)'. This may change the @@ -2382,6 +2387,8 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual, it so that we can tell this is a call to a known function. */ fn = maybe_undo_parenthesized_ref (fn); + STRIP_ANY_LOCATION_WRAPPER (fn); + orig_fn = fn; if (processing_template_decl) @@ -3523,20 +3530,20 @@ process_outer_var_ref (tree decl, tsubst_flags_t complain, bool odr_use) the use of "this" explicit. Upon return, *IDK will be filled in appropriately. */ -cp_expr -finish_id_expression (tree id_expression, - tree decl, - tree scope, - cp_id_kind *idk, - bool integral_constant_expression_p, - bool allow_non_integral_constant_expression_p, - bool *non_integral_constant_expression_p, - bool template_p, - bool done, - bool address_p, - bool template_arg_p, - const char **error_msg, - location_t location) +static cp_expr +finish_id_expression_1 (tree id_expression, + tree decl, + tree scope, + cp_id_kind *idk, + bool integral_constant_expression_p, + bool allow_non_integral_constant_expression_p, + bool *non_integral_constant_expression_p, + bool template_p, + bool done, + bool address_p, + bool template_arg_p, + const char **error_msg, + location_t location) { decl = strip_using_decl (decl); @@ -3841,6 +3848,34 @@ finish_id_expression (tree id_expression, return cp_expr (decl, location); } +/* As per finish_id_expression_1, but adding a wrapper node + around the result if needed to express LOCATION. */ + +cp_expr +finish_id_expression (tree id_expression, + tree decl, + tree scope, + cp_id_kind *idk, + bool integral_constant_expression_p, + bool allow_non_integral_constant_expression_p, + bool *non_integral_constant_expression_p, + bool template_p, + bool done, + bool address_p, + bool template_arg_p, + const char **error_msg, + location_t location) +{ + cp_expr result + = finish_id_expression_1 (id_expression, decl, scope, idk, + integral_constant_expression_p, + allow_non_integral_constant_expression_p, + non_integral_constant_expression_p, + template_p, done, address_p, template_arg_p, + error_msg, location); + return result.maybe_add_location_wrapper (); +} + /* Implement the __typeof keyword: Return the type of EXPR, suitable for use as a type-specifier. */ @@ -9766,12 +9801,12 @@ static tree capture_decltype (tree decl) { tree lam = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (current_function_decl)); - /* FIXME do lookup instead of list walk? */ - tree cap = value_member (decl, LAMBDA_EXPR_CAPTURE_LIST (lam)); + tree cap = lookup_name_real (DECL_NAME (decl), /*type*/0, /*nonclass*/1, + /*block_p=*/true, /*ns*/0, LOOKUP_HIDDEN); tree type; - if (cap) - type = TREE_TYPE (TREE_PURPOSE (cap)); + if (cap && is_capture_proxy (cap)) + type = TREE_TYPE (cap); else switch (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lam)) { diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 97074df..aac3ece 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -377,6 +377,7 @@ bitfield_p (const_tree ref) tree cp_stabilize_reference (tree ref) { + STRIP_ANY_LOCATION_WRAPPER (ref); switch (TREE_CODE (ref)) { case NON_DEPENDENT_EXPR: @@ -421,6 +422,7 @@ cp_stabilize_reference (tree ref) bool builtin_valid_in_constant_expr_p (const_tree decl) { + STRIP_ANY_LOCATION_WRAPPER (decl); if (TREE_CODE (decl) != FUNCTION_DECL) /* Not a function. */ return false; @@ -1715,6 +1717,8 @@ strip_typedefs_expr (tree t, bool *remove_attributes) if (t == NULL_TREE || t == error_mark_node) return t; + STRIP_ANY_LOCATION_WRAPPER (t); + if (DECL_P (t) || CONSTANT_CLASS_P (t)) return t; @@ -2369,6 +2373,8 @@ lookup_maybe_add (tree fns, tree lookup, bool deduping) int is_overloaded_fn (tree x) { + STRIP_ANY_LOCATION_WRAPPER (x); + /* A baselink is also considered an overloaded function. */ if (TREE_CODE (x) == OFFSET_REF || TREE_CODE (x) == COMPONENT_REF) @@ -2417,6 +2423,8 @@ really_overloaded_fn (tree x) tree maybe_get_fns (tree from) { + STRIP_ANY_LOCATION_WRAPPER (from); + /* A baselink is also considered an overloaded function. */ if (TREE_CODE (from) == OFFSET_REF || TREE_CODE (from) == COMPONENT_REF) @@ -5527,6 +5535,14 @@ test_lvalue_kind () ASSERT_EQ (clk_rvalueref, lvalue_kind (rvalue_ref_of_parm)); tree rvalue_ref_of_wrapped_parm = move (wrapped_parm); ASSERT_EQ (clk_rvalueref, lvalue_kind (rvalue_ref_of_wrapped_parm)); + + /* Verify lvalue_p. */ + ASSERT_FALSE (lvalue_p (int_cst)); + ASSERT_FALSE (lvalue_p (wrapped_int_cst)); + ASSERT_TRUE (lvalue_p (parm)); + ASSERT_TRUE (lvalue_p (wrapped_parm)); + ASSERT_FALSE (lvalue_p (rvalue_ref_of_parm)); + ASSERT_FALSE (lvalue_p (rvalue_ref_of_wrapped_parm)); } /* Run all of the selftests within this file. */ diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 47ddad1..519510d 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1682,6 +1682,8 @@ cxx_sizeof_expr (tree e, tsubst_flags_t complain) return e; } + STRIP_ANY_LOCATION_WRAPPER (e); + /* To get the size of a static data member declared as an array of unknown bound, we need to instantiate it. */ if (VAR_P (e) @@ -1754,6 +1756,8 @@ cxx_alignof_expr (tree e, tsubst_flags_t complain) return e; } + STRIP_ANY_LOCATION_WRAPPER (e); + e = mark_type_use (e); if (VAR_P (e)) @@ -1944,6 +1948,12 @@ is_bitfield_expr_with_lowered_type (const_tree exp) (CONST_CAST_TREE (exp))); return NULL_TREE; + case VIEW_CONVERT_EXPR: + if (location_wrapper_p (exp)) + return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0)); + else + return NULL_TREE; + CASE_CONVERT: if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (exp, 0))) == TYPE_MAIN_VARIANT (TREE_TYPE (exp))) @@ -3415,6 +3425,8 @@ cp_build_array_ref (location_t loc, tree array, tree idx, pointer arithmetic.) */ idx = cp_perform_integral_promotions (idx, complain); + idx = maybe_constant_value (idx); + /* An array that is indexed by a non-constant cannot be stored in a register; we must be able to do address arithmetic on its address. @@ -4561,20 +4573,23 @@ cp_build_binary_op (location_t location, type0 = TREE_TYPE (type0); if (!TYPE_P (type1)) type1 = TREE_TYPE (type1); - if (INDIRECT_TYPE_P (type0) && same_type_p (TREE_TYPE (type0), type1) - && !(TREE_CODE (first_arg) == PARM_DECL - && DECL_ARRAY_PARAMETER_P (first_arg) - && warn_sizeof_array_argument) - && (complain & tf_warning)) + if (INDIRECT_TYPE_P (type0) && same_type_p (TREE_TYPE (type0), type1)) { - auto_diagnostic_group d; - if (warning_at (location, OPT_Wsizeof_pointer_div, - "division %<sizeof (%T) / sizeof (%T)%> does " - "not compute the number of array elements", - type0, type1)) - if (DECL_P (first_arg)) - inform (DECL_SOURCE_LOCATION (first_arg), - "first %<sizeof%> operand was declared here"); + STRIP_ANY_LOCATION_WRAPPER (first_arg); + if (!(TREE_CODE (first_arg) == PARM_DECL + && DECL_ARRAY_PARAMETER_P (first_arg) + && warn_sizeof_array_argument) + && (complain & tf_warning)) + { + auto_diagnostic_group d; + if (warning_at (location, OPT_Wsizeof_pointer_div, + "division %<sizeof (%T) / sizeof (%T)%> does " + "not compute the number of array elements", + type0, type1)) + if (DECL_P (first_arg)) + inform (DECL_SOURCE_LOCATION (first_arg), + "first %<sizeof%> operand was declared here"); + } } } @@ -4596,15 +4611,18 @@ cp_build_binary_op (location_t location, if (!(tcode0 == INTEGER_TYPE && tcode1 == INTEGER_TYPE)) resultcode = RDIV_EXPR; else - /* When dividing two signed integers, we have to promote to int. - unless we divide by a constant != -1. Note that default - conversion will have been performed on the operands at this - point, so we have to dig out the original type to find out if - it was unsigned. */ - shorten = ((TREE_CODE (op0) == NOP_EXPR - && TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op0, 0)))) - || (TREE_CODE (op1) == INTEGER_CST - && ! integer_all_onesp (op1))); + { + /* When dividing two signed integers, we have to promote to int. + unless we divide by a constant != -1. Note that default + conversion will have been performed on the operands at this + point, so we have to dig out the original type to find out if + it was unsigned. */ + tree stripped_op1 = tree_strip_any_location_wrapper (op1); + shorten = ((TREE_CODE (op0) == NOP_EXPR + && TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op0, 0)))) + || (TREE_CODE (stripped_op1) == INTEGER_CST + && ! integer_all_onesp (stripped_op1))); + } common = 1; } @@ -4638,10 +4656,11 @@ cp_build_binary_op (location_t location, on some targets, since the modulo instruction is undefined if the quotient can't be represented in the computation mode. We shorten only if unsigned or if dividing by something we know != -1. */ + tree stripped_op1 = tree_strip_any_location_wrapper (op1); shorten = ((TREE_CODE (op0) == NOP_EXPR && TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op0, 0)))) - || (TREE_CODE (op1) == INTEGER_CST - && ! integer_all_onesp (op1))); + || (TREE_CODE (stripped_op1) == INTEGER_CST + && ! integer_all_onesp (stripped_op1))); common = 1; } break; @@ -4842,13 +4861,17 @@ cp_build_binary_op (location_t location, && (FLOAT_TYPE_P (type0) || FLOAT_TYPE_P (type1))) warning (OPT_Wfloat_equal, "comparing floating point with == or != is unsafe"); - if ((complain & tf_warning) - && ((TREE_CODE (orig_op0) == STRING_CST + if (complain & tf_warning) + { + tree stripped_orig_op0 = tree_strip_any_location_wrapper (orig_op0); + tree stripped_orig_op1 = tree_strip_any_location_wrapper (orig_op1); + if ((TREE_CODE (stripped_orig_op0) == STRING_CST && !integer_zerop (cp_fully_fold (op1))) - || (TREE_CODE (orig_op1) == STRING_CST - && !integer_zerop (cp_fully_fold (op0))))) - warning (OPT_Waddress, "comparison with string literal results " - "in unspecified behavior"); + || (TREE_CODE (stripped_orig_op1) == STRING_CST + && !integer_zerop (cp_fully_fold (op0)))) + warning (OPT_Waddress, "comparison with string literal results " + "in unspecified behavior"); + } build_type = boolean_type_node; if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE @@ -6080,8 +6103,9 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain) so we can just form an ADDR_EXPR with the correct type. */ if (processing_template_decl || TREE_CODE (arg) != COMPONENT_REF) { - if (TREE_CODE (arg) == FUNCTION_DECL - && !mark_used (arg, complain) && !(complain & tf_error)) + tree stripped_arg = tree_strip_any_location_wrapper (arg); + if (TREE_CODE (stripped_arg) == FUNCTION_DECL + && !mark_used (stripped_arg, complain) && !(complain & tf_error)) return error_mark_node; val = build_address (arg); if (TREE_CODE (arg) == OFFSET_REF) @@ -8304,7 +8328,8 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode, /* C++11 8.5/17: "If the destination type is an array of characters, an array of char16_t, an array of char32_t, or an array of wchar_t, and the initializer is a string literal...". */ - else if (TREE_CODE (newrhs) == STRING_CST + else if ((TREE_CODE (tree_strip_any_location_wrapper (newrhs)) + == STRING_CST) && char_type_p (TREE_TYPE (TYPE_MAIN_VARIANT (lhstype))) && modifycode == INIT_EXPR) { @@ -8823,9 +8848,10 @@ convert_for_assignment (tree type, tree rhs, enum tree_code coder; location_t rhs_loc = EXPR_LOC_OR_LOC (rhs, input_location); - - /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ - if (TREE_CODE (rhs) == NON_LVALUE_EXPR) + /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue, + but preserve location wrappers. */ + if (TREE_CODE (rhs) == NON_LVALUE_EXPR + && !location_wrapper_p (rhs)) rhs = TREE_OPERAND (rhs, 0); /* Handle [dcl.init.list] direct-list-initialization from @@ -9199,6 +9225,8 @@ maybe_warn_about_returning_address_of_local (tree retval) return true; } + STRIP_ANY_LOCATION_WRAPPER (whats_returned); + if (DECL_P (whats_returned) && DECL_NAME (whats_returned) && DECL_FUNCTION_SCOPE_P (whats_returned) @@ -9300,6 +9328,8 @@ is_std_move_p (tree fn) static bool can_do_nrvo_p (tree retval, tree functype) { + if (retval) + STRIP_ANY_LOCATION_WRAPPER (retval); tree result = DECL_RESULT (current_function_decl); return (retval != NULL_TREE && !processing_template_decl @@ -9326,6 +9356,7 @@ can_do_nrvo_p (tree retval, tree functype) bool treat_lvalue_as_rvalue_p (tree retval, bool parm_ok) { + STRIP_ANY_LOCATION_WRAPPER (retval); return ((cxx_dialect != cxx98) && ((VAR_P (retval) && !DECL_HAS_VALUE_EXPR_P (retval)) || (parm_ok && TREE_CODE (retval) == PARM_DECL)) @@ -9619,6 +9650,8 @@ check_return_expr (tree retval, bool *no_warning) this restriction, anyway. (jason 2000-11-19) See finish_function and finalize_nrv for the rest of this optimization. */ + if (retval) + STRIP_ANY_LOCATION_WRAPPER (retval); bool named_return_value_okay_p = can_do_nrvo_p (retval, functype); if (fn_returns_value_p && flag_elide_constructors) diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 64e36ef..c1fa4a9 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -460,14 +460,19 @@ cxx_incomplete_type_diagnostic (location_t loc, const_tree value, if (TREE_CODE (type) == ERROR_MARK) return; - if (value != 0 && (VAR_P (value) - || TREE_CODE (value) == PARM_DECL - || TREE_CODE (value) == FIELD_DECL)) + if (value) { - complained = emit_diagnostic (diag_kind, DECL_SOURCE_LOCATION (value), 0, - "%qD has incomplete type", value); - is_decl = true; - } + STRIP_ANY_LOCATION_WRAPPER (value); + + if (VAR_P (value) + || TREE_CODE (value) == PARM_DECL + || TREE_CODE (value) == FIELD_DECL) + { + complained = emit_diagnostic (diag_kind, DECL_SOURCE_LOCATION (value), 0, + "%qD has incomplete type", value); + is_decl = true; + } + } retry: /* We must print an error message. Be clever about what it says. */ @@ -1052,6 +1057,8 @@ digest_init_r (tree type, tree init, int nested, int flags, location_t loc = cp_expr_loc_or_loc (init, input_location); + tree stripped_init = tree_strip_any_location_wrapper (init); + /* Initialization of an array of chars from a string constant. The initializer can be optionally enclosed in braces, but reshape_init has already removed them if they were present. */ @@ -1065,7 +1072,7 @@ digest_init_r (tree type, tree init, int nested, int flags, tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type)); if (char_type_p (typ1) /*&& init */ - && TREE_CODE (init) == STRING_CST) + && TREE_CODE (stripped_init) == STRING_CST) { tree char_type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (init))); @@ -1113,6 +1120,14 @@ digest_init_r (tree type, tree init, int nested, int flags, { init = copy_node (init); TREE_TYPE (init) = type; + /* If we have a location wrapper, then also copy the wrapped + node, and update the copy's type. */ + if (location_wrapper_p (init)) + { + stripped_init = copy_node (stripped_init); + TREE_OPERAND (init, 0) = stripped_init; + TREE_TYPE (stripped_init) = type; + } } if (TYPE_DOMAIN (type) && TREE_CONSTANT (TYPE_SIZE (type))) { @@ -1123,12 +1138,13 @@ digest_init_r (tree type, tree init, int nested, int flags, because it's ok to ignore the terminating null char that is counted in the length of the constant, but in C++ this would be invalid. */ - if (size < TREE_STRING_LENGTH (init)) + if (size < TREE_STRING_LENGTH (stripped_init)) { permerror (loc, "initializer-string for array " "of chars is too long"); - init = build_string (size, TREE_STRING_POINTER (init)); + init = build_string (size, + TREE_STRING_POINTER (stripped_init)); TREE_TYPE (init) = type; } } @@ -1137,7 +1153,7 @@ digest_init_r (tree type, tree init, int nested, int flags, } /* Handle scalar types (including conversions) and references. */ - if ((code != COMPLEX_TYPE || BRACE_ENCLOSED_INITIALIZER_P (init)) + if ((code != COMPLEX_TYPE || BRACE_ENCLOSED_INITIALIZER_P (stripped_init)) && (SCALAR_TYPE_P (type) || code == REFERENCE_TYPE)) { if (nested) @@ -1162,23 +1178,23 @@ digest_init_r (tree type, tree init, int nested, int flags, the object is initialized from that element." */ if (flag_checking && cxx_dialect >= cxx11 - && BRACE_ENCLOSED_INITIALIZER_P (init) - && CONSTRUCTOR_NELTS (init) == 1 + && BRACE_ENCLOSED_INITIALIZER_P (stripped_init) + && CONSTRUCTOR_NELTS (stripped_init) == 1 && ((CLASS_TYPE_P (type) && !CLASSTYPE_NON_AGGREGATE (type)) || VECTOR_TYPE_P (type))) { - tree elt = CONSTRUCTOR_ELT (init, 0)->value; + tree elt = CONSTRUCTOR_ELT (stripped_init, 0)->value; if (reference_related_p (type, TREE_TYPE (elt))) /* We should have fixed this in reshape_init. */ gcc_unreachable (); } - if (BRACE_ENCLOSED_INITIALIZER_P (init) + if (BRACE_ENCLOSED_INITIALIZER_P (stripped_init) && !TYPE_NON_AGGREGATE_CLASS (type)) - return process_init_constructor (type, init, nested, complain); + return process_init_constructor (type, stripped_init, nested, complain); else { - if (COMPOUND_LITERAL_P (init) && code == ARRAY_TYPE) + if (COMPOUND_LITERAL_P (stripped_init) && code == ARRAY_TYPE) { if (complain & tf_error) error_at (loc, "cannot initialize aggregate of type %qT with " @@ -1188,12 +1204,12 @@ digest_init_r (tree type, tree init, int nested, int flags, } if (code == ARRAY_TYPE - && !BRACE_ENCLOSED_INITIALIZER_P (init)) + && !BRACE_ENCLOSED_INITIALIZER_P (stripped_init)) { /* Allow the result of build_array_copy and of build_value_init_noctor. */ - if ((TREE_CODE (init) == VEC_INIT_EXPR - || TREE_CODE (init) == CONSTRUCTOR) + if ((TREE_CODE (stripped_init) == VEC_INIT_EXPR + || TREE_CODE (stripped_init) == CONSTRUCTOR) && (same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (init)))) return init; |