Mercurial > hg > CbC > CbC_gcc
diff gcc/cp/typeck.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
line wrap: on
line diff
--- a/gcc/cp/typeck.c Thu Oct 25 07:37:49 2018 +0900 +++ b/gcc/cp/typeck.c Thu Feb 13 11:34:05 2020 +0900 @@ -1,5 +1,5 @@ /* Build expressions with type checking for C++ compiler. - Copyright (C) 1987-2018 Free Software Foundation, Inc. + Copyright (C) 1987-2020 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. @@ -35,11 +35,11 @@ #include "convert.h" #include "c-family/c-objc.h" #include "c-family/c-ubsan.h" -#include "params.h" #include "gcc-rich-location.h" #include "stringpool.h" #include "attribs.h" #include "asan.h" +#include "gimplify.h" static tree cp_build_addr_expr_strict (tree, tsubst_flags_t); static tree cp_build_function_call (tree, tree, tsubst_flags_t); @@ -51,15 +51,14 @@ tsubst_flags_t); static tree rationalize_conditional_expr (enum tree_code, tree, tsubst_flags_t); -static int comp_ptr_ttypes_real (tree, tree, int); +static bool comp_ptr_ttypes_real (tree, tree, int); static bool comp_except_types (tree, tree, bool); -static bool comp_array_types (const_tree, const_tree, bool); +static bool comp_array_types (const_tree, const_tree, compare_bounds_t, bool); static tree pointer_diff (location_t, tree, tree, tree, tsubst_flags_t, tree *); static tree get_delta_difference (tree, tree, bool, bool, tsubst_flags_t); static void casts_away_constness_r (tree *, tree *, tsubst_flags_t); static bool casts_away_constness (tree, tree, tsubst_flags_t); -static bool maybe_warn_about_returning_address_of_local (tree); -static tree lookup_destructor (tree, tree, tree, tsubst_flags_t); +static bool maybe_warn_about_returning_address_of_local (tree, location_t = UNKNOWN_LOCATION); static void error_args_num (location_t, tree, bool); static int convert_arguments (tree, vec<tree, va_gc> **, tree, int, tsubst_flags_t); @@ -449,25 +448,26 @@ } static void -composite_pointer_error (diagnostic_t kind, tree t1, tree t2, +composite_pointer_error (const op_location_t &location, + diagnostic_t kind, tree t1, tree t2, composite_pointer_operation operation) { switch (operation) { case CPO_COMPARISON: - emit_diagnostic (kind, input_location, 0, + emit_diagnostic (kind, location, 0, "comparison between " "distinct pointer types %qT and %qT lacks a cast", t1, t2); break; case CPO_CONVERSION: - emit_diagnostic (kind, input_location, 0, + emit_diagnostic (kind, location, 0, "conversion between " "distinct pointer types %qT and %qT lacks a cast", t1, t2); break; case CPO_CONDITIONAL_EXPR: - emit_diagnostic (kind, input_location, 0, + emit_diagnostic (kind, location, 0, "conditional expression between " "distinct pointer types %qT and %qT lacks a cast", t1, t2); @@ -481,7 +481,8 @@ case. See that function for documentation of the parameters. */ static tree -composite_pointer_type_r (tree t1, tree t2, +composite_pointer_type_r (const op_location_t &location, + tree t1, tree t2, composite_pointer_operation operation, tsubst_flags_t complain) { @@ -514,15 +515,16 @@ else if ((TYPE_PTR_P (pointee1) && TYPE_PTR_P (pointee2)) || (TYPE_PTRMEM_P (pointee1) && TYPE_PTRMEM_P (pointee2))) { - result_type = composite_pointer_type_r (pointee1, pointee2, operation, - complain); + result_type = composite_pointer_type_r (location, pointee1, pointee2, + operation, complain); if (result_type == error_mark_node) return error_mark_node; } else { if (complain & tf_error) - composite_pointer_error (DK_PERMERROR, t1, t2, operation); + composite_pointer_error (location, DK_PERMERROR, + t1, t2, operation); else return error_mark_node; result_type = void_type_node; @@ -538,7 +540,8 @@ TYPE_PTRMEM_CLASS_TYPE (t2))) { if (complain & tf_error) - composite_pointer_error (DK_PERMERROR, t1, t2, operation); + composite_pointer_error (location, DK_PERMERROR, + t1, t2, operation); else return error_mark_node; } @@ -562,7 +565,8 @@ pointers-to-members as per [expr.eq]. */ tree -composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2, +composite_pointer_type (const op_location_t &location, + tree t1, tree t2, tree arg1, tree arg2, composite_pointer_operation operation, tsubst_flags_t complain) { @@ -604,17 +608,17 @@ switch (operation) { case CPO_COMPARISON: - pedwarn (input_location, OPT_Wpedantic, + pedwarn (location, OPT_Wpedantic, "ISO C++ forbids comparison between pointer " "of type %<void *%> and pointer-to-function"); break; case CPO_CONVERSION: - pedwarn (input_location, OPT_Wpedantic, + pedwarn (location, OPT_Wpedantic, "ISO C++ forbids conversion between pointer " "of type %<void *%> and pointer-to-function"); break; case CPO_CONDITIONAL_EXPR: - pedwarn (input_location, OPT_Wpedantic, + pedwarn (location, OPT_Wpedantic, "ISO C++ forbids conditional expression between " "pointer of type %<void *%> and " "pointer-to-function"); @@ -671,7 +675,7 @@ else { if (complain & tf_error) - composite_pointer_error (DK_ERROR, t1, t2, operation); + composite_pointer_error (location, DK_ERROR, t1, t2, operation); return error_mark_node; } } @@ -694,19 +698,19 @@ switch (operation) { case CPO_COMPARISON: - error ("comparison between distinct " - "pointer-to-member types %qT and %qT lacks a cast", - t1, t2); + error_at (location, "comparison between distinct " + "pointer-to-member types %qT and %qT lacks a cast", + t1, t2); break; case CPO_CONVERSION: - error ("conversion between distinct " - "pointer-to-member types %qT and %qT lacks a cast", - t1, t2); + error_at (location, "conversion between distinct " + "pointer-to-member types %qT and %qT lacks a cast", + t1, t2); break; case CPO_CONDITIONAL_EXPR: - error ("conditional expression between distinct " - "pointer-to-member types %qT and %qT lacks a cast", - t1, t2); + error_at (location, "conditional expression between distinct " + "pointer-to-member types %qT and %qT lacks a cast", + t1, t2); break; default: gcc_unreachable (); @@ -715,7 +719,7 @@ } } - return composite_pointer_type_r (t1, t2, operation, complain); + return composite_pointer_type_r (location, t1, t2, operation, complain); } /* Return the merged type of two types. @@ -950,7 +954,8 @@ || (TYPE_PTRDATAMEM_P (t1) && TYPE_PTRDATAMEM_P (t2)) || (TYPE_PTRMEMFUNC_P (t1) && TYPE_PTRMEMFUNC_P (t2))); - return composite_pointer_type (t1, t2, error_mark_node, error_mark_node, + return composite_pointer_type (input_location, t1, t2, + error_mark_node, error_mark_node, CPO_CONVERSION, tf_warning_or_error); } @@ -1083,11 +1088,15 @@ return exact == ce_derived || base == NULL_TREE || length == list_length (t1); } -/* Compare the array types T1 and T2. ALLOW_REDECLARATION is true if - [] can match [size]. */ +/* Compare the array types T1 and T2. CB says how we should behave when + comparing array bounds: bounds_none doesn't allow dimensionless arrays, + bounds_either says than any array can be [], bounds_first means that + onlt T1 can be an array with unknown bounds. STRICT is true if + qualifiers must match when comparing the types of the array elements. */ static bool -comp_array_types (const_tree t1, const_tree t2, bool allow_redeclaration) +comp_array_types (const_tree t1, const_tree t2, compare_bounds_t cb, + bool strict) { tree d1; tree d2; @@ -1097,7 +1106,9 @@ return true; /* The type of the array elements must be the same. */ - if (!same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))) + if (strict + ? !same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)) + : !similar_type_p (TREE_TYPE (t1), TREE_TYPE (t2))) return false; d1 = TYPE_DOMAIN (t1); @@ -1118,8 +1129,10 @@ declarations for an array object can specify array types that differ by the presence or absence of a major array bound (_dcl.array_). */ - if (!d1 || !d2) - return allow_redeclaration; + if (!d1 && d2) + return cb >= bounds_either; + else if (d1 && !d2) + return cb == bounds_either; /* Check that the dimensions are the same. */ @@ -1261,8 +1274,7 @@ return false; /* Need to check this before TYPE_MAIN_VARIANT. FIXME function qualifiers should really change the main variant. */ - if (TREE_CODE (t1) == FUNCTION_TYPE - || TREE_CODE (t1) == METHOD_TYPE) + if (FUNC_OR_METHOD_TYPE_P (t1)) { if (type_memfn_rqual (t1) != type_memfn_rqual (t2)) return false; @@ -1368,7 +1380,9 @@ case ARRAY_TYPE: /* Target types must match incl. qualifiers. */ - if (!comp_array_types (t1, t2, !!(strict & COMPARE_REDECLARATION))) + if (!comp_array_types (t1, t2, ((strict & COMPARE_REDECLARATION) + ? bounds_either : bounds_none), + /*strict=*/true)) return false; break; @@ -1411,7 +1425,8 @@ break; case VECTOR_TYPE: - if (maybe_ne (TYPE_VECTOR_SUBPARTS (t1), TYPE_VECTOR_SUBPARTS (t2)) + if (gnu_vector_type_p (t1) != gnu_vector_type_p (t2) + || maybe_ne (TYPE_VECTOR_SUBPARTS (t1), TYPE_VECTOR_SUBPARTS (t2)) || !same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))) return false; break; @@ -1442,6 +1457,20 @@ return false; } + /* Don't treat an alias template specialization with dependent + arguments as equivalent to its underlying type when used as a + template argument; we need them to be distinct so that we + substitute into the specialization arguments at instantiation + time. And aliases can't be equivalent without being ==, so + we don't need to look any deeper. */ + if (comparing_specializations) + { + tree dep1 = dependent_alias_template_spec_p (t1, nt_transparent); + tree dep2 = dependent_alias_template_spec_p (t2, nt_transparent); + if ((dep1 || dep2) && dep1 != dep2) + return false; + } + /* If we get here, we know that from a target independent POV the types are the same. Make sure the target attributes are also the same. */ @@ -1454,6 +1483,10 @@ bool comptypes (tree t1, tree t2, int strict) { + if (strict == COMPARE_STRICT && comparing_specializations + && (t1 != TYPE_CANONICAL (t1) || t2 != TYPE_CANONICAL (t2))) + /* If comparing_specializations, treat dependent aliases as distinct. */ + strict = COMPARE_STRUCTURAL; if (strict == COMPARE_STRICT) { if (t1 == t2) @@ -1467,7 +1500,7 @@ perform a deep check. */ return structural_comptypes (t1, t2, strict); - if (flag_checking && USE_CANONICAL_TYPES) + if (flag_checking && param_use_canonical_types) { bool result = structural_comptypes (t1, t2, strict); @@ -1488,7 +1521,7 @@ return result; } - if (!flag_checking && USE_CANONICAL_TYPES) + if (!flag_checking && param_use_canonical_types) return TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2); else return structural_comptypes (t1, t2, strict); @@ -1507,12 +1540,41 @@ { if (type1 == error_mark_node || type2 == error_mark_node) return false; + if (type1 == type2) + return true; type1 = cp_build_qualified_type (type1, TYPE_UNQUALIFIED); type2 = cp_build_qualified_type (type2, TYPE_UNQUALIFIED); return same_type_p (type1, type2); } +/* Returns nonzero iff TYPE1 and TYPE2 are similar, as per [conv.qual]. */ + +bool +similar_type_p (tree type1, tree type2) +{ + if (type1 == error_mark_node || type2 == error_mark_node) + return false; + + /* Informally, two types are similar if, ignoring top-level cv-qualification: + * they are the same type; or + * they are both pointers, and the pointed-to types are similar; or + * they are both pointers to member of the same class, and the types of + the pointed-to members are similar; or + * they are both arrays of the same size or both arrays of unknown bound, + and the array element types are similar. */ + + if (same_type_ignoring_top_level_qualifiers_p (type1, type2)) + return true; + + if ((TYPE_PTR_P (type1) && TYPE_PTR_P (type2)) + || (TYPE_PTRDATAMEM_P (type1) && TYPE_PTRDATAMEM_P (type2)) + || (TREE_CODE (type1) == ARRAY_TYPE && TREE_CODE (type2) == ARRAY_TYPE)) + return comp_ptr_ttypes_const (type1, type2, bounds_either); + + return false; +} + /* Returns 1 if TYPE1 is at least as qualified as TYPE2. */ bool @@ -1601,8 +1663,8 @@ SIZEOF_EXPR. */ tree -cxx_sizeof_or_alignof_type (tree type, enum tree_code op, bool std_alignof, - bool complain) +cxx_sizeof_or_alignof_type (location_t loc, tree type, enum tree_code op, + bool std_alignof, bool complain) { gcc_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR); if (type == error_mark_node) @@ -1613,7 +1675,7 @@ { if (complain) { - pedwarn (input_location, OPT_Wpointer_arith, + pedwarn (loc, OPT_Wpointer_arith, "invalid application of %qs to a member function", OVL_OP_INFO (false, op)->name); return size_one_node; @@ -1640,10 +1702,11 @@ TREE_READONLY (value) = 1; if (op == ALIGNOF_EXPR && std_alignof) ALIGNOF_EXPR_STD_P (value) = true; + SET_EXPR_LOCATION (value, loc); return value; } - return c_sizeof_or_alignof_type (input_location, complete_type (type), + return c_sizeof_or_alignof_type (loc, complete_type (type), op == SIZEOF_EXPR, std_alignof, complain); } @@ -1662,26 +1725,31 @@ else if (!COMPLETE_TYPE_P (type)) return size_zero_node; else - return cxx_sizeof_or_alignof_type (type, SIZEOF_EXPR, false, false); + return cxx_sizeof_or_alignof_type (input_location, type, + SIZEOF_EXPR, false, false); } /* Process a sizeof expression where the operand is an expression. */ static tree -cxx_sizeof_expr (tree e, tsubst_flags_t complain) +cxx_sizeof_expr (location_t loc, tree e, tsubst_flags_t complain) { if (e == error_mark_node) return error_mark_node; - if (processing_template_decl) + if (instantiation_dependent_uneval_expression_p (e)) { e = build_min (SIZEOF_EXPR, size_type_node, e); TREE_SIDE_EFFECTS (e) = 0; TREE_READONLY (e) = 1; + SET_EXPR_LOCATION (e, loc); return e; } + location_t e_loc = cp_expr_loc_or_loc (e, loc); + 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) @@ -1694,8 +1762,9 @@ && (complain & tf_warning)) { auto_diagnostic_group d; - if (warning (OPT_Wsizeof_array_argument, "%<sizeof%> on array function " - "parameter %qE will return size of %qT", e, TREE_TYPE (e))) + if (warning_at (e_loc, OPT_Wsizeof_array_argument, + "%<sizeof%> on array function parameter %qE " + "will return size of %qT", e, TREE_TYPE (e))) inform (DECL_SOURCE_LOCATION (e), "declared here"); } @@ -1704,7 +1773,8 @@ if (bitfield_p (e)) { if (complain & tf_error) - error ("invalid application of %<sizeof%> to a bit-field"); + error_at (e_loc, + "invalid application of %<sizeof%> to a bit-field"); else return error_mark_node; e = char_type_node; @@ -1712,8 +1782,8 @@ else if (is_overloaded_fn (e)) { if (complain & tf_error) - permerror (input_location, "ISO C++ forbids applying %<sizeof%> to an expression of " - "function type"); + permerror (e_loc, "ISO C++ forbids applying %<sizeof%> to " + "an expression of function type"); else return error_mark_node; e = char_type_node; @@ -1721,7 +1791,7 @@ else if (type_unknown_p (e)) { if (complain & tf_error) - cxx_incomplete_type_error (e, TREE_TYPE (e)); + cxx_incomplete_type_error (e_loc, e, TREE_TYPE (e)); else return error_mark_node; e = char_type_node; @@ -1729,7 +1799,8 @@ else e = TREE_TYPE (e); - return cxx_sizeof_or_alignof_type (e, SIZEOF_EXPR, false, complain & tf_error); + return cxx_sizeof_or_alignof_type (loc, e, SIZEOF_EXPR, false, + complain & tf_error); } /* Implement the __alignof keyword: Return the minimum required @@ -1738,7 +1809,7 @@ "aligned" __attribute__ specification). */ static tree -cxx_alignof_expr (tree e, tsubst_flags_t complain) +cxx_alignof_expr (location_t loc, tree e, tsubst_flags_t complain) { tree t; @@ -1750,18 +1821,30 @@ e = build_min (ALIGNOF_EXPR, size_type_node, e); TREE_SIDE_EFFECTS (e) = 0; TREE_READONLY (e) = 1; + SET_EXPR_LOCATION (e, loc); return e; } + location_t e_loc = cp_expr_loc_or_loc (e, loc); + STRIP_ANY_LOCATION_WRAPPER (e); + e = mark_type_use (e); - if (VAR_P (e)) + if (!verify_type_context (loc, TCTX_ALIGNOF, TREE_TYPE (e), + !(complain & tf_error))) + { + if (!(complain & tf_error)) + return error_mark_node; + t = size_one_node; + } + else if (VAR_P (e)) t = size_int (DECL_ALIGN_UNIT (e)); else if (bitfield_p (e)) { if (complain & tf_error) - error ("invalid application of %<__alignof%> to a bit-field"); + error_at (e_loc, + "invalid application of %<__alignof%> to a bit-field"); else return error_mark_node; t = size_one_node; @@ -1772,8 +1855,8 @@ else if (is_overloaded_fn (e)) { if (complain & tf_error) - permerror (input_location, "ISO C++ forbids applying %<__alignof%> to an expression of " - "function type"); + permerror (e_loc, "ISO C++ forbids applying %<__alignof%> to " + "an expression of function type"); else return error_mark_node; if (TREE_CODE (e) == FUNCTION_DECL) @@ -1784,28 +1867,30 @@ else if (type_unknown_p (e)) { if (complain & tf_error) - cxx_incomplete_type_error (e, TREE_TYPE (e)); + cxx_incomplete_type_error (e_loc, e, TREE_TYPE (e)); else return error_mark_node; t = size_one_node; } else - return cxx_sizeof_or_alignof_type (TREE_TYPE (e), ALIGNOF_EXPR, false, + return cxx_sizeof_or_alignof_type (loc, TREE_TYPE (e), + ALIGNOF_EXPR, false, complain & tf_error); - return fold_convert (size_type_node, t); + return fold_convert_loc (loc, size_type_node, t); } /* Process a sizeof or alignof expression E with code OP where the operand is an expression. */ tree -cxx_sizeof_or_alignof_expr (tree e, enum tree_code op, bool complain) +cxx_sizeof_or_alignof_expr (location_t loc, tree e, enum tree_code op, + bool complain) { if (op == SIZEOF_EXPR) - return cxx_sizeof_expr (e, complain? tf_warning_or_error : tf_none); + return cxx_sizeof_expr (loc, e, complain? tf_warning_or_error : tf_none); else - return cxx_alignof_expr (e, complain? tf_warning_or_error : tf_none); + return cxx_alignof_expr (loc, e, complain? tf_warning_or_error : tf_none); } /* Build a representation of an expression 'alignas(E).' Return the @@ -1829,7 +1914,8 @@ alignas(type-id ), it shall have the same effect as alignas(alignof(type-id )). */ - return cxx_sizeof_or_alignof_type (e, ALIGNOF_EXPR, true, false); + return cxx_sizeof_or_alignof_type (input_location, + e, ALIGNOF_EXPR, true, false); /* If we reach this point, it means the alignas expression if of the form "alignas(assignment-expression)", so we should follow @@ -1944,11 +2030,11 @@ (CONST_CAST_TREE (exp))); return NULL_TREE; - CASE_CONVERT: - if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (exp, 0))) - == TYPE_MAIN_VARIANT (TREE_TYPE (exp))) + case VIEW_CONVERT_EXPR: + if (location_wrapper_p (exp)) return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0)); - /* Fallthrough. */ + else + return NULL_TREE; default: return NULL_TREE; @@ -1993,19 +2079,13 @@ { tree type; enum tree_code code; - location_t loc = cp_expr_loc_or_loc (exp, input_location); + location_t loc = cp_expr_loc_or_input_loc (exp); type = TREE_TYPE (exp); if (type == error_mark_node) return error_mark_node; - exp = resolve_nondeduced_context (exp, complain); - if (type_unknown_p (exp)) - { - if (complain & tf_error) - cxx_incomplete_type_error (exp, TREE_TYPE (exp)); - return error_mark_node; - } + exp = resolve_nondeduced_context_or_error (exp, complain); code = TREE_CODE (type); @@ -2168,13 +2248,23 @@ if (error_operand_p (expr)) return error_mark_node; + type = TREE_TYPE (expr); + /* [conv.prom] - If the bitfield has an enumerated type, it is treated as any - other value of that type for promotion purposes. */ - type = is_bitfield_expr_with_lowered_type (expr); - if (!type || TREE_CODE (type) != ENUMERAL_TYPE) - type = TREE_TYPE (expr); + A prvalue for an integral bit-field (11.3.9) can be converted to a prvalue + of type int if int can represent all the values of the bit-field; + otherwise, it can be converted to unsigned int if unsigned int can + represent all the values of the bit-field. If the bit-field is larger yet, + no integral promotion applies to it. If the bit-field has an enumerated + type, it is treated as any other value of that type for promotion + purposes. */ + tree bitfield_type = is_bitfield_expr_with_lowered_type (expr); + if (bitfield_type + && (TREE_CODE (bitfield_type) == ENUMERAL_TYPE + || TYPE_PRECISION (type) > TYPE_PRECISION (integer_type_node))) + type = bitfield_type; + gcc_assert (INTEGRAL_OR_ENUMERATION_TYPE_P (type)); /* Scoped enums don't promote. */ if (SCOPED_ENUM_P (type)) @@ -2182,6 +2272,9 @@ promoted_type = type_promotes_to (type); if (type != promoted_type) expr = cp_convert (promoted_type, expr, complain); + else if (bitfield_type && bitfield_type != type) + /* Prevent decay_conversion from converting to bitfield_type. */ + expr = build_nop (type, expr); return expr; } @@ -2206,6 +2299,7 @@ t = TREE_TYPE (totype); if (!same_type_p (t, char_type_node) + && !same_type_p (t, char8_type_node) && !same_type_p (t, char16_type_node) && !same_type_p (t, char32_type_node) && !same_type_p (t, wchar_type_node)) @@ -2259,7 +2353,7 @@ rationalize_conditional_expr (enum tree_code code, tree t, tsubst_flags_t complain) { - location_t loc = cp_expr_loc_or_loc (t, input_location); + location_t loc = cp_expr_loc_or_input_loc (t); /* For MIN_EXPR or MAX_EXPR, fold-const.c has arranged things so that the first operand is always the one to be used if both operands @@ -2286,13 +2380,15 @@ complain); } + tree op1 = TREE_OPERAND (t, 1); + if (TREE_CODE (op1) != THROW_EXPR) + op1 = cp_build_unary_op (code, op1, false, complain); + tree op2 = TREE_OPERAND (t, 2); + if (TREE_CODE (op2) != THROW_EXPR) + op2 = cp_build_unary_op (code, op2, false, complain); + return - build_conditional_expr (loc, TREE_OPERAND (t, 0), - cp_build_unary_op (code, TREE_OPERAND (t, 1), false, - complain), - cp_build_unary_op (code, TREE_OPERAND (t, 2), false, - complain), - complain); + build_conditional_expr (loc, TREE_OPERAND (t, 0), op1, op2, complain); } /* Given the TYPE of an anonymous union field inside T, return the @@ -2422,7 +2518,13 @@ { tree temp = unary_complex_lvalue (ADDR_EXPR, object); if (temp) - object = cp_build_fold_indirect_ref (temp); + { + temp = cp_build_fold_indirect_ref (temp); + if (xvalue_p (object) && !xvalue_p (temp)) + /* Preserve xvalue kind. */ + temp = move (temp); + object = temp; + } } /* In [expr.ref], there is an explicit list of the valid choices for @@ -2432,6 +2534,12 @@ /* A static data member. */ result = member; mark_exp_read (object); + + if (tree wrap = maybe_get_tls_wrapper_call (result)) + /* Replace an evaluated use of the thread_local variable with + a call to its wrapper. */ + result = wrap; + /* If OBJECT has side-effects, they are supposed to occur. */ if (TREE_SIDE_EFFECTS (object)) result = build2 (COMPOUND_EXPR, TREE_TYPE (result), object, result); @@ -2456,6 +2564,15 @@ tree binfo; base_kind kind; + /* We didn't complain above about a currently open class, but now we + must: we don't know how to refer to a base member before layout is + complete. But still don't complain in a template. */ + if (!cp_unevaluated_operand + && !dependent_type_p (object_type) + && !complete_type_or_maybe_complain (object_type, object, + complain)) + return error_mark_node; + binfo = lookup_base (access_path ? access_path : object_type, member_scope, ba_unique, &kind, complain); if (binfo == error_mark_node) @@ -2551,7 +2668,8 @@ type = unknown_type_node; /* Note that we do not convert OBJECT to the BASELINK_BINFO base. That will happen when the function is called. */ - result = build3 (COMPONENT_REF, type, object, member, NULL_TREE); + result = build3_loc (input_location, COMPONENT_REF, type, object, member, + NULL_TREE); } else if (TREE_CODE (member) == CONST_DECL) { @@ -2587,7 +2705,7 @@ /* Return the destructor denoted by OBJECT.SCOPE::DTOR_NAME, or, if SCOPE is NULL, by OBJECT.DTOR_NAME, where DTOR_NAME is ~type. */ -static tree +tree lookup_destructor (tree object, tree scope, tree dtor_name, tsubst_flags_t complain) { @@ -2884,7 +3002,12 @@ expression is dependent. */ || (TREE_CODE (name) == SCOPE_REF && TYPE_P (TREE_OPERAND (name, 0)) - && dependent_scope_p (TREE_OPERAND (name, 0)))) + && dependent_scope_p (TREE_OPERAND (name, 0))) + /* If NAME is operator T where "T" is dependent, we can't + lookup until we instantiate the T. */ + || (TREE_CODE (name) == IDENTIFIER_NODE + && IDENTIFIER_CONV_OP_P (name) + && dependent_type_p (TREE_TYPE (name)))) { dependent: return build_min_nt_loc (UNKNOWN_LOCATION, COMPONENT_REF, @@ -3174,7 +3297,7 @@ rval = build_new_op (loc, INDIRECT_REF, LOOKUP_NORMAL, expr, NULL_TREE, NULL_TREE, &overload, complain); if (!rval) - rval = cp_build_indirect_ref (expr, errorstring, complain); + rval = cp_build_indirect_ref (loc, expr, errorstring, complain); if (processing_template_decl && rval != error_mark_node) { @@ -3192,7 +3315,7 @@ constructs. If DO_FOLD is true, fold away INDIRECT_REF of ADDR_EXPR. */ static tree -cp_build_indirect_ref_1 (tree ptr, ref_operator errorstring, +cp_build_indirect_ref_1 (location_t loc, tree ptr, ref_operator errorstring, tsubst_flags_t complain, bool do_fold) { tree pointer, type; @@ -3241,7 +3364,7 @@ /* A pointer to incomplete type (other than cv void) can be dereferenced [expr.unary.op]/1 */ if (complain & tf_error) - error ("%qT is not a pointer-to-object type", type); + error_at (loc, "%qT is not a pointer-to-object type", type); return error_mark_node; } else if (do_fold && TREE_CODE (pointer) == ADDR_EXPR @@ -3272,23 +3395,25 @@ switch (errorstring) { case RO_ARRAY_INDEXING: - error ("invalid use of array indexing on pointer to member"); + error_at (loc, + "invalid use of array indexing on pointer to member"); break; case RO_UNARY_STAR: - error ("invalid use of unary %<*%> on pointer to member"); + error_at (loc, "invalid use of unary %<*%> on pointer to member"); break; case RO_IMPLICIT_CONVERSION: - error ("invalid use of implicit conversion on pointer to member"); + error_at (loc, "invalid use of implicit conversion on pointer " + "to member"); break; case RO_ARROW_STAR: - error ("left hand operand of %<->*%> must be a pointer to class, " - "but is a pointer to member of type %qT", type); + error_at (loc, "left hand operand of %<->*%> must be a pointer to " + "class, but is a pointer to member of type %qT", type); break; default: gcc_unreachable (); } else if (pointer != error_mark_node) - invalid_indirection_error (input_location, type, errorstring); + invalid_indirection_error (loc, type, errorstring); return error_mark_node; } @@ -3296,10 +3421,10 @@ /* Entry point used by c-common, which expects folding. */ tree -build_indirect_ref (location_t /*loc*/, - tree ptr, ref_operator errorstring) -{ - return cp_build_indirect_ref_1 (ptr, errorstring, tf_warning_or_error, true); +build_indirect_ref (location_t loc, tree ptr, ref_operator errorstring) +{ + return cp_build_indirect_ref_1 (loc, ptr, errorstring, + tf_warning_or_error, true); } /* Entry point used by internal indirection needs that don't correspond to any @@ -3308,17 +3433,18 @@ tree cp_build_fold_indirect_ref (tree pointer) { - return cp_build_indirect_ref_1 (pointer, RO_NULL, tf_warning_or_error, true); + return cp_build_indirect_ref_1 (input_location, pointer, RO_NULL, + tf_warning_or_error, true); } /* Entry point used by indirection needs that correspond to some syntactic construct. */ tree -cp_build_indirect_ref (tree ptr, ref_operator errorstring, +cp_build_indirect_ref (location_t loc, tree ptr, ref_operator errorstring, tsubst_flags_t complain) { - return cp_build_indirect_ref_1 (ptr, errorstring, complain, false); + return cp_build_indirect_ref_1 (loc, ptr, errorstring, complain, false); } /* This handles expressions of the form "a[i]", which denotes @@ -3404,6 +3530,8 @@ 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. @@ -3463,6 +3591,10 @@ { tree ar = cp_default_conversion (array, complain); tree ind = cp_default_conversion (idx, complain); + tree first = NULL_TREE; + + if (flag_strong_eval_order == 2 && TREE_SIDE_EFFECTS (ind)) + ar = first = save_expr (ar); /* Put the integer in IND to simplify error checking. */ if (TREE_CODE (TREE_TYPE (ar)) == INTEGER_TYPE) @@ -3486,11 +3618,10 @@ warn_array_subscript_with_type_char (loc, idx); - ret = cp_build_indirect_ref (cp_build_binary_op (input_location, - PLUS_EXPR, ar, ind, - complain), - RO_ARRAY_INDEXING, - complain); + ret = cp_build_binary_op (input_location, PLUS_EXPR, ar, ind, complain); + if (first) + ret = build2_loc (loc, COMPOUND_EXPR, TREE_TYPE (ret), first, ret); + ret = cp_build_indirect_ref (loc, ret, RO_ARRAY_INDEXING, complain); protected_set_expr_location (ret, loc); if (non_lvalue) ret = non_lvalue_loc (loc, ret); @@ -3686,11 +3817,11 @@ tree build_function_call_vec (location_t /*loc*/, vec<location_t> /*arg_loc*/, tree function, vec<tree, va_gc> *params, - vec<tree, va_gc> * /*origtypes*/) + vec<tree, va_gc> * /*origtypes*/, tree orig_function) { vec<tree, va_gc> *orig_params = params; tree ret = cp_build_function_call_vec (function, ¶ms, - tf_warning_or_error); + tf_warning_or_error, orig_function); /* cp_build_function_call_vec can reallocate PARAMS by adding default arguments. That should never happen here. Verify @@ -3705,14 +3836,12 @@ static tree cp_build_function_call (tree function, tree params, tsubst_flags_t complain) { - vec<tree, va_gc> *vec; tree ret; - vec = make_tree_vector (); + releasing_vec vec; for (; params != NULL_TREE; params = TREE_CHAIN (params)) vec_safe_push (vec, TREE_VALUE (params)); ret = cp_build_function_call_vec (function, &vec, complain); - release_tree_vector (vec); return ret; } @@ -3721,27 +3850,27 @@ tree cp_build_function_call_nary (tree function, tsubst_flags_t complain, ...) { - vec<tree, va_gc> *vec; va_list args; tree ret, t; - vec = make_tree_vector (); + releasing_vec vec; va_start (args, complain); for (t = va_arg (args, tree); t != NULL_TREE; t = va_arg (args, tree)) vec_safe_push (vec, t); va_end (args); ret = cp_build_function_call_vec (function, &vec, complain); - release_tree_vector (vec); return ret; } -/* Build a function call using a vector of arguments. PARAMS may be - NULL if there are no parameters. This changes the contents of - PARAMS. */ +/* Build a function call using a vector of arguments. + If FUNCTION is the result of resolving an overloaded target built-in, + ORIG_FNDECL is the original function decl, otherwise it is null. + PARAMS may be NULL if there are no parameters. This changes the + contents of PARAMS. */ tree cp_build_function_call_vec (tree function, vec<tree, va_gc> **params, - tsubst_flags_t complain) + tsubst_flags_t complain, tree orig_fndecl) { tree fntype, fndecl; int is_method; @@ -3765,27 +3894,7 @@ if (TREE_CODE (function) == FUNCTION_DECL) { - /* If the function is a non-template member function - or a non-template friend, then we need to check the - constraints. - - Note that if overload resolution failed with a single - candidate this function will be used to explicitly diagnose - the failure for the single call expression. The check is - technically redundant since we also would have failed in - add_function_candidate. */ - if (flag_concepts - && (complain & tf_error) - && !constraints_satisfied_p (function)) - { - auto_diagnostic_group d; - error ("cannot call function %qD", function); - location_t loc = DECL_SOURCE_LOCATION (function); - diagnose_constraints (loc, function, NULL_TREE); - return error_mark_node; - } - - if (!mark_used (function, complain) && !(complain & tf_error)) + if (!mark_used (function, complain)) return error_mark_node; fndecl = function; @@ -3866,7 +3975,7 @@ bool warned_p = check_function_arguments (input_location, fndecl, fntype, nargs, argarray, NULL); - ret = build_cxx_call (function, nargs, argarray, complain); + ret = build_cxx_call (function, nargs, argarray, complain, orig_fndecl); if (warned_p) { @@ -3985,8 +4094,7 @@ if (type == 0 || !TYPE_REF_P (type)) { if (TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE - || TREE_CODE (TREE_TYPE (val)) == FUNCTION_TYPE - || TREE_CODE (TREE_TYPE (val)) == METHOD_TYPE) + || FUNC_OR_METHOD_TYPE_P (TREE_TYPE (val))) val = decay_conversion (val, complain); } @@ -4002,11 +4110,19 @@ { if (complain & tf_error) { + location_t loc = EXPR_LOC_OR_LOC (val, input_location); if (fndecl) - error ("parameter %P of %qD has incomplete type %qT", - i, fndecl, type); + { + auto_diagnostic_group d; + error_at (loc, + "parameter %P of %qD has incomplete type %qT", + i, fndecl, type); + inform (get_fndecl_argument_location (fndecl, i), + " declared here"); + } else - error ("parameter %P has incomplete type %qT", i, type); + error_at (loc, "parameter %P has incomplete type %qT", i, + type); } parmval = error_mark_node; } @@ -4050,7 +4166,7 @@ provide default arguments in a language conformant manner. */ if (fndecl && TREE_PURPOSE (typetail) - && TREE_CODE (TREE_PURPOSE (typetail)) != DEFAULT_ARG) + && TREE_CODE (TREE_PURPOSE (typetail)) != DEFERRED_PARSE) { for (; typetail != void_list_node; ++i) { @@ -4097,7 +4213,7 @@ ARG2_CODE as ERROR_MARK. */ tree -build_x_binary_op (location_t loc, enum tree_code code, tree arg1, +build_x_binary_op (const op_location_t &loc, enum tree_code code, tree arg1, enum tree_code arg1_code, tree arg2, enum tree_code arg2_code, tree *overload_p, tsubst_flags_t complain) @@ -4114,7 +4230,11 @@ { if (type_dependent_expression_p (arg1) || type_dependent_expression_p (arg2)) - return build_min_nt_loc (loc, code, arg1, arg2); + { + expr = build_min_nt_loc (loc, code, arg1, arg2); + maybe_save_operator_binding (expr); + return expr; + } arg1 = build_non_dependent_expr (arg1); arg2 = build_non_dependent_expr (arg2); } @@ -4229,7 +4349,7 @@ { tree zero_vec = build_zero_cst (type); tree minus_one_vec = build_minus_one_cst (type); - tree cmp_type = build_same_sized_truth_vector_type(type); + tree cmp_type = truth_type_for (type); tree cmp = build2 (code, cmp_type, arg0, arg1); return build3 (VEC_COND_EXPR, type, cmp, minus_one_vec, zero_vec); } @@ -4245,7 +4365,7 @@ || TREE_NO_WARNING (op)) return; - tree cop = fold_non_dependent_expr (op, complain); + tree cop = fold_for_warn (op); if (TREE_CODE (cop) == ADDR_EXPR && decl_with_nonnull_addr_p (TREE_OPERAND (cop, 0)) @@ -4286,7 +4406,7 @@ multiple inheritance, and deal with pointer to member functions. */ tree -cp_build_binary_op (location_t location, +cp_build_binary_op (const op_location_t &location, enum tree_code code, tree orig_op0, tree orig_op1, tsubst_flags_t complain) { @@ -4332,16 +4452,16 @@ Also implies COMMON. */ int short_compare = 0; + /* Nonzero if this is a right-shift operation, which can be computed on the + original short and then promoted if the operand is a promoted short. */ + int short_shift = 0; + /* Nonzero means set RESULT_TYPE to the common type of the args. */ int common = 0; /* True if both operands have arithmetic type. */ bool arithmetic_types_p; - /* Apply default conversions. */ - op0 = orig_op0; - op1 = orig_op1; - /* Remember whether we're doing / or %. */ bool doing_div_or_mod = false; @@ -4351,6 +4471,10 @@ /* Tree holding instrumentation expression. */ tree instrument_expr = NULL_TREE; + /* Apply default conversions. */ + op0 = resolve_nondeduced_context (orig_op0, complain); + op1 = resolve_nondeduced_context (orig_op1, complain); + if (code == TRUTH_AND_EXPR || code == TRUTH_ANDIF_EXPR || code == TRUTH_OR_EXPR || code == TRUTH_ORIF_EXPR || code == TRUTH_XOR_EXPR) @@ -4379,7 +4503,8 @@ if (t != error_mark_node) { if (complain & tf_error) - permerror (input_location, "assuming cast to type %qT from overloaded function", + permerror (location, + "assuming cast to type %qT from overloaded function", TREE_TYPE (t)); op0 = t; } @@ -4390,7 +4515,8 @@ if (t != error_mark_node) { if (complain & tf_error) - permerror (input_location, "assuming cast to type %qT from overloaded function", + permerror (location, + "assuming cast to type %qT from overloaded function", TREE_TYPE (t)); op1 = t; } @@ -4433,7 +4559,7 @@ && !TYPE_PTR_OR_PTRMEM_P (type1))) && (complain & tf_warning)) { - source_location loc = + location_t loc = expansion_point_location_if_in_system_header (input_location); warning_at (loc, OPT_Wpointer_arith, "NULL used in arithmetic"); @@ -4441,7 +4567,8 @@ /* In case when one of the operands of the binary operation is a vector and another is a scalar -- convert scalar to vector. */ - if ((code0 == VECTOR_TYPE) != (code1 == VECTOR_TYPE)) + if ((gnu_vector_type_p (type0) && code1 != VECTOR_TYPE) + || (gnu_vector_type_p (type1) && code0 != VECTOR_TYPE)) { enum stv_conv convert_flag = scalar_to_vector (location, code, op0, op1, complain & tf_error); @@ -4542,20 +4669,23 @@ 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"); + } } } @@ -4565,9 +4695,8 @@ || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)) { enum tree_code tcode0 = code0, tcode1 = code1; - tree cop1 = fold_non_dependent_expr (op1, complain); doing_div_or_mod = true; - warn_for_div_by_zero (location, cop1); + warn_for_div_by_zero (location, fold_for_warn (op1)); if (tcode0 == COMPLEX_TYPE || tcode0 == VECTOR_TYPE) tcode0 = TREE_CODE (TREE_TYPE (TREE_TYPE (op0))); @@ -4577,15 +4706,18 @@ 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; } @@ -4603,11 +4735,8 @@ case TRUNC_MOD_EXPR: case FLOOR_MOD_EXPR: - { - tree cop1 = fold_non_dependent_expr (op1, complain); - doing_div_or_mod = true; - warn_for_div_by_zero (location, cop1); - } + doing_div_or_mod = true; + warn_for_div_by_zero (location, fold_for_warn (op1)); if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE @@ -4619,10 +4748,11 @@ 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; @@ -4631,7 +4761,7 @@ case TRUTH_ORIF_EXPR: case TRUTH_AND_EXPR: case TRUTH_OR_EXPR: - if (!VECTOR_TYPE_P (type0) && VECTOR_TYPE_P (type1)) + if (!VECTOR_TYPE_P (type0) && gnu_vector_type_p (type1)) { if (!COMPARISON_CLASS_P (op1)) op1 = cp_build_binary_op (EXPR_LOCATION (op1), NE_EXPR, op1, @@ -4649,7 +4779,8 @@ else gcc_unreachable (); } - if (VECTOR_TYPE_P (type0)) + if (gnu_vector_type_p (type0) + && (!VECTOR_TYPE_P (type1) || gnu_vector_type_p (type1))) { if (!COMPARISON_CLASS_P (op0)) op0 = cp_build_binary_op (EXPR_LOCATION (op0), NE_EXPR, op0, @@ -4682,13 +4813,15 @@ Also set SHORT_SHIFT if shifting rightward. */ case RSHIFT_EXPR: - if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE - && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE) + if (gnu_vector_type_p (type0) + && code1 == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE) { result_type = type0; converted = 1; } - else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE + else if (gnu_vector_type_p (type0) + && gnu_vector_type_p (type1) && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE && known_eq (TYPE_VECTOR_SUBPARTS (type0), @@ -4699,7 +4832,7 @@ } else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { - tree const_op1 = fold_non_dependent_expr (op1, complain); + tree const_op1 = fold_for_warn (op1); if (TREE_CODE (const_op1) != INTEGER_CST) const_op1 = op1; result_type = type0; @@ -4710,16 +4843,19 @@ { if ((complain & tf_warning) && c_inhibit_evaluation_warnings == 0) - warning (OPT_Wshift_count_negative, - "right shift count is negative"); + warning_at (location, OPT_Wshift_count_negative, + "right shift count is negative"); } else { + if (!integer_zerop (const_op1)) + short_shift = 1; + if (compare_tree_int (const_op1, TYPE_PRECISION (type0)) >= 0 && (complain & tf_warning) && c_inhibit_evaluation_warnings == 0) - warning (OPT_Wshift_count_overflow, - "right shift count >= width of type"); + warning_at (location, OPT_Wshift_count_overflow, + "right shift count >= width of type"); } } /* Avoid converting op1 to result_type later. */ @@ -4728,13 +4864,15 @@ break; case LSHIFT_EXPR: - if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE + if (gnu_vector_type_p (type0) + && code1 == INTEGER_TYPE && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE) { result_type = type0; converted = 1; } - else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE + else if (gnu_vector_type_p (type0) + && gnu_vector_type_p (type1) && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE && known_eq (TYPE_VECTOR_SUBPARTS (type0), @@ -4745,10 +4883,10 @@ } else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { - tree const_op0 = fold_non_dependent_expr (op0, complain); + tree const_op0 = fold_for_warn (op0); if (TREE_CODE (const_op0) != INTEGER_CST) const_op0 = op0; - tree const_op1 = fold_non_dependent_expr (op1, complain); + tree const_op1 = fold_for_warn (op1); if (TREE_CODE (const_op1) != INTEGER_CST) const_op1 = op1; result_type = type0; @@ -4757,24 +4895,24 @@ && tree_int_cst_sgn (const_op0) < 0 && (complain & tf_warning) && c_inhibit_evaluation_warnings == 0) - warning (OPT_Wshift_negative_value, - "left shift of negative value"); + warning_at (location, OPT_Wshift_negative_value, + "left shift of negative value"); if (TREE_CODE (const_op1) == INTEGER_CST) { if (tree_int_cst_lt (const_op1, integer_zero_node)) { if ((complain & tf_warning) && c_inhibit_evaluation_warnings == 0) - warning (OPT_Wshift_count_negative, - "left shift count is negative"); + warning_at (location, OPT_Wshift_count_negative, + "left shift count is negative"); } else if (compare_tree_int (const_op1, TYPE_PRECISION (type0)) >= 0) { if ((complain & tf_warning) && c_inhibit_evaluation_warnings == 0) - warning (OPT_Wshift_count_overflow, - "left shift count >= width of type"); + warning_at (location, OPT_Wshift_count_overflow, + "left shift count >= width of type"); } else if (TREE_CODE (const_op0) == INTEGER_CST && (complain & tf_warning)) @@ -4785,51 +4923,28 @@ } break; - case RROTATE_EXPR: - case LROTATE_EXPR: - if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) - { - result_type = type0; - if (TREE_CODE (op1) == INTEGER_CST) - { - if (tree_int_cst_lt (op1, integer_zero_node)) - { - if (complain & tf_warning) - warning (0, (code == LROTATE_EXPR) - ? G_("left rotate count is negative") - : G_("right rotate count is negative")); - } - else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0) - { - if (complain & tf_warning) - warning (0, (code == LROTATE_EXPR) - ? G_("left rotate count >= width of type") - : G_("right rotate count >= width of type")); - } - } - /* Convert the shift-count to an integer, regardless of - size of value being shifted. */ - if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) - op1 = cp_convert (integer_type_node, op1, complain); - } - break; - case EQ_EXPR: case NE_EXPR: - if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE) + if (gnu_vector_type_p (type0) && gnu_vector_type_p (type1)) goto vector_compare; if ((complain & tf_warning) && c_inhibit_evaluation_warnings == 0 && (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 + warning_at (location, OPT_Wfloat_equal, + "comparing floating-point with %<==%> " + "or %<!=%> is unsafe"); + 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_at (location, OPT_Waddress, + "comparison with string literal results in " + "unspecified behavior"); + } build_type = boolean_type_node; if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE @@ -4844,7 +4959,8 @@ && TYPE_PTR_P (type1) && integer_zerop (op1))) { if (TYPE_PTR_P (type1)) - result_type = composite_pointer_type (type0, type1, op0, op1, + result_type = composite_pointer_type (location, + type0, type1, op0, op1, CPO_COMPARISON, complain); else result_type = type0; @@ -4852,11 +4968,11 @@ if (char_type_p (TREE_TYPE (orig_op1))) { auto_diagnostic_group d; - if (warning (OPT_Wpointer_compare, - "comparison between pointer and zero character " - "constant")) - inform (input_location, - "did you mean to dereference the pointer?"); + if (warning_at (location, OPT_Wpointer_compare, + "comparison between pointer and zero character " + "constant")) + inform (location, + "did you mean to dereference the pointer?"); } warn_for_null_address (location, op0, complain); } @@ -4867,7 +4983,8 @@ && TYPE_PTR_P (type0) && integer_zerop (op0))) { if (TYPE_PTR_P (type0)) - result_type = composite_pointer_type (type0, type1, op0, op1, + result_type = composite_pointer_type (location, + type0, type1, op0, op1, CPO_COMPARISON, complain); else result_type = type1; @@ -4875,17 +4992,18 @@ if (char_type_p (TREE_TYPE (orig_op0))) { auto_diagnostic_group d; - if (warning (OPT_Wpointer_compare, + if (warning_at (location, OPT_Wpointer_compare, "comparison between pointer and zero character " "constant")) - inform (input_location, + inform (location, "did you mean to dereference the pointer?"); } warn_for_null_address (location, op1, complain); } else if ((code0 == POINTER_TYPE && code1 == POINTER_TYPE) || (TYPE_PTRDATAMEM_P (type0) && TYPE_PTRDATAMEM_P (type1))) - result_type = composite_pointer_type (type0, type1, op0, op1, + result_type = composite_pointer_type (location, + type0, type1, op0, op1, CPO_COMPARISON, complain); else if (null_ptr_cst_p (orig_op0) && null_ptr_cst_p (orig_op1)) /* One of the operands must be of nullptr_t type. */ @@ -4893,8 +5011,9 @@ else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) { result_type = type0; - if (complain & tf_error) - permerror (input_location, "ISO C++ forbids comparison between pointer and integer"); + if (complain & tf_error) + permerror (location, "ISO C++ forbids comparison between " + "pointer and integer"); else return error_mark_node; } @@ -4902,7 +5021,8 @@ { result_type = type1; if (complain & tf_error) - permerror (input_location, "ISO C++ forbids comparison between pointer and integer"); + permerror (location, "ISO C++ forbids comparison between " + "pointer and integer"); else return error_mark_node; } @@ -4914,7 +5034,7 @@ tree pfn0, delta0, e1, e2; if (TREE_SIDE_EFFECTS (op0)) - op0 = save_expr (op0); + op0 = cp_save_expr (op0); pfn0 = pfn_from_ptrmemfunc (op0); delta0 = delta_from_ptrmemfunc (op0); @@ -4962,7 +5082,7 @@ tree delta0; tree delta1; - type = composite_pointer_type (type0, type1, op0, op1, + type = composite_pointer_type (location, type0, type1, op0, op1, CPO_COMPARISON, complain); if (!same_type_p (TREE_TYPE (op0), type)) @@ -5076,7 +5196,8 @@ && (code1 == INTEGER_TYPE || code1 == REAL_TYPE)) shorten = 1; else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) - result_type = composite_pointer_type (type0, type1, op0, op1, + result_type = composite_pointer_type (location, + type0, type1, op0, op1, CPO_COMPARISON, complain); break; @@ -5084,15 +5205,17 @@ case GE_EXPR: case LT_EXPR: case GT_EXPR: + case SPACESHIP_EXPR: if (TREE_CODE (orig_op0) == STRING_CST || TREE_CODE (orig_op1) == STRING_CST) { if (complain & tf_warning) - warning (OPT_Waddress, "comparison with string literal results " - "in unspecified behavior"); - } - - if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE) + warning_at (location, OPT_Waddress, + "comparison with string literal results " + "in unspecified behavior"); + } + + if (gnu_vector_type_p (type0) && gnu_vector_type_p (type1)) { vector_compare: tree intt; @@ -5137,6 +5260,13 @@ "types %qT and %qT", type0, type1); } + if (resultcode == SPACESHIP_EXPR) + { + if (complain & tf_error) + sorry_at (location, "three-way comparison of vectors"); + return error_mark_node; + } + /* Always construct signed integer vector type. */ intt = c_common_type_for_size (GET_MODE_BITSIZE (SCALAR_TYPE_MODE (TREE_TYPE (type0))), 0); @@ -5149,7 +5279,6 @@ } result_type = build_opaque_vector_type (intt, TYPE_VECTOR_SUBPARTS (type0)); - converted = 1; return build_vec_cmp (resultcode, result_type, op0, op1); } build_type = boolean_type_node; @@ -5159,21 +5288,22 @@ || code1 == ENUMERAL_TYPE)) short_compare = 1; else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) - result_type = composite_pointer_type (type0, type1, op0, op1, + result_type = composite_pointer_type (location, + type0, type1, op0, op1, CPO_COMPARISON, complain); else if (code0 == POINTER_TYPE && null_ptr_cst_p (orig_op1)) { result_type = type0; if (extra_warnings && (complain & tf_warning)) - warning (OPT_Wextra, - "ordered comparison of pointer with integer zero"); + warning_at (location, OPT_Wextra, + "ordered comparison of pointer with integer zero"); } else if (code1 == POINTER_TYPE && null_ptr_cst_p (orig_op0)) { result_type = type1; if (extra_warnings && (complain & tf_warning)) - warning (OPT_Wextra, - "ordered comparison of pointer with integer zero"); + warning_at (location, OPT_Wextra, + "ordered comparison of pointer with integer zero"); } else if (null_ptr_cst_p (orig_op0) && null_ptr_cst_p (orig_op1)) /* One of the operands must be of nullptr_t type. */ @@ -5182,20 +5312,23 @@ { result_type = type0; if (complain & tf_error) - permerror (input_location, "ISO C++ forbids comparison between pointer and integer"); - else + permerror (location, "ISO C++ forbids comparison between " + "pointer and integer"); + else return error_mark_node; } else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE) { result_type = type1; if (complain & tf_error) - permerror (input_location, "ISO C++ forbids comparison between pointer and integer"); - else + permerror (location, "ISO C++ forbids comparison between " + "pointer and integer"); + else return error_mark_node; } if ((code0 == POINTER_TYPE || code1 == POINTER_TYPE) + && !processing_template_decl && sanitize_flags_p (SANITIZE_POINTER_COMPARE)) { op0 = save_expr (op0); @@ -5218,7 +5351,7 @@ if (code0 != REAL_TYPE || code1 != REAL_TYPE) { if (complain & tf_error) - error ("unordered comparison on non-floating point argument"); + error ("unordered comparison on non-floating-point argument"); return error_mark_node; } common = 1; @@ -5237,7 +5370,7 @@ { arithmetic_types_p = 0; /* Vector arithmetic is only allowed when both sides are vectors. */ - if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE) + if (gnu_vector_type_p (type0) && gnu_vector_type_p (type1)) { if (!tree_int_cst_equal (TYPE_SIZE (type0), TYPE_SIZE (type1)) || !vector_types_compatible_elements_p (type0, type1)) @@ -5269,12 +5402,74 @@ location); } + if (code == SPACESHIP_EXPR) + { + iloc_sentinel s (location); + + tree orig_type0 = TREE_TYPE (orig_op0); + tree_code orig_code0 = TREE_CODE (orig_type0); + tree orig_type1 = TREE_TYPE (orig_op1); + tree_code orig_code1 = TREE_CODE (orig_type1); + if (!result_type) + /* Nope. */; + else if ((orig_code0 == BOOLEAN_TYPE) != (orig_code1 == BOOLEAN_TYPE)) + /* "If one of the operands is of type bool and the other is not, the + program is ill-formed." */ + result_type = NULL_TREE; + else if (code0 == POINTER_TYPE && orig_code0 != POINTER_TYPE + && code1 == POINTER_TYPE && orig_code1 != POINTER_TYPE) + /* We only do array/function-to-pointer conversion if "at least one of + the operands is of pointer type". */ + result_type = NULL_TREE; + else if (TYPE_PTRFN_P (result_type) || NULLPTR_TYPE_P (result_type)) + /* <=> no longer supports equality relations. */ + result_type = NULL_TREE; + else if (orig_code0 == ENUMERAL_TYPE && orig_code1 == ENUMERAL_TYPE + && !(same_type_ignoring_top_level_qualifiers_p + (orig_type0, orig_type1))) + /* "If both operands have arithmetic types, or one operand has integral + type and the other operand has unscoped enumeration type, the usual + arithmetic conversions are applied to the operands." So we don't do + arithmetic conversions if the operands both have enumeral type. */ + result_type = NULL_TREE; + + if (result_type) + { + build_type = spaceship_type (result_type, complain); + if (build_type == error_mark_node) + return error_mark_node; + } + + if (result_type && arithmetic_types_p) + { + /* If a narrowing conversion is required, other than from an integral + type to a floating point type, the program is ill-formed. */ + bool ok = true; + if (TREE_CODE (result_type) == REAL_TYPE + && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (orig_op0))) + /* OK */; + else if (!check_narrowing (result_type, orig_op0, complain)) + ok = false; + if (TREE_CODE (result_type) == REAL_TYPE + && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (orig_op1))) + /* OK */; + else if (!check_narrowing (result_type, orig_op1, complain)) + ok = false; + if (!ok && !(complain & tf_error)) + return error_mark_node; + } + } + if (!result_type) { if (complain & tf_error) - error_at (location, - "invalid operands of types %qT and %qT to binary %qO", - TREE_TYPE (orig_op0), TREE_TYPE (orig_op1), code); + { + binary_op_rich_location richloc (location, + orig_op0, orig_op1, true); + error_at (&richloc, + "invalid operands of types %qT and %qT to binary %qO", + TREE_TYPE (orig_op0), TREE_TYPE (orig_op1), code); + } return error_mark_node; } @@ -5398,6 +5593,39 @@ shorten == -1); } + /* Shifts can be shortened if shifting right. */ + + if (short_shift) + { + int unsigned_arg; + tree arg0 = get_narrower (op0, &unsigned_arg); + tree const_op1 = cp_fold_rvalue (op1); + + final_type = result_type; + + if (arg0 == op0 && final_type == TREE_TYPE (op0)) + unsigned_arg = TYPE_UNSIGNED (TREE_TYPE (op0)); + + if (TYPE_PRECISION (TREE_TYPE (arg0)) < TYPE_PRECISION (result_type) + && tree_int_cst_sgn (const_op1) > 0 + /* We can shorten only if the shift count is less than the + number of bits in the smaller type size. */ + && compare_tree_int (const_op1, + TYPE_PRECISION (TREE_TYPE (arg0))) < 0 + /* We cannot drop an unsigned shift after sign-extension. */ + && (!TYPE_UNSIGNED (final_type) || unsigned_arg)) + { + /* Do an unsigned shift if the operand was zero-extended. */ + result_type + = c_common_signed_or_unsigned_type (unsigned_arg, + TREE_TYPE (arg0)); + /* Convert value-to-be-shifted to that type. */ + if (TREE_TYPE (op0) != result_type) + op0 = convert (result_type, op0); + converted = 1; + } + } + /* Comparison operations are shortened too but differently. They identify themselves by setting short_compare = 1. */ @@ -5424,14 +5652,7 @@ && !enum_cast_to_int (orig_op0) && !enum_cast_to_int (orig_op1)) { - tree oop0 = maybe_constant_value (orig_op0); - tree oop1 = maybe_constant_value (orig_op1); - - if (TREE_CODE (oop0) != INTEGER_CST) - oop0 = cp_fully_fold (orig_op0); - if (TREE_CODE (oop1) != INTEGER_CST) - oop1 = cp_fully_fold (orig_op1); - warn_for_sign_compare (location, oop0, oop1, op0, op1, + warn_for_sign_compare (location, orig_op0, orig_op1, op0, op1, result_type, resultcode); } } @@ -5443,9 +5664,9 @@ if (! converted) { warning_sentinel w (warn_sign_conversion, short_compare); - if (TREE_TYPE (op0) != result_type) + if (!same_type_p (TREE_TYPE (op0), result_type)) op0 = cp_convert_and_check (result_type, op0, complain); - if (TREE_TYPE (op1) != result_type) + if (!same_type_p (TREE_TYPE (op1), result_type)) op1 = cp_convert_and_check (result_type, op1, complain); if (op0 == error_mark_node || op1 == error_mark_node) @@ -5455,6 +5676,17 @@ if (build_type == NULL_TREE) build_type = result_type; + if (doing_shift + && flag_strong_eval_order == 2 + && TREE_SIDE_EFFECTS (op1) + && !processing_template_decl) + { + /* In C++17, in both op0 << op1 and op0 >> op1 op0 is sequenced before + op1, so if op1 has side-effects, use SAVE_EXPR around op0. */ + op0 = cp_save_expr (op0); + instrument_expr = op0; + } + if (sanitize_flags_p ((SANITIZE_SHIFT | SANITIZE_DIVIDE | SANITIZE_FLOAT_DIVIDE)) && current_function_decl != NULL_TREE @@ -5466,6 +5698,7 @@ op1 = cp_save_expr (op1); op0 = fold_non_dependent_expr (op0, complain); op1 = fold_non_dependent_expr (op1, complain); + tree instrument_expr1 = NULL_TREE; if (doing_div_or_mod && sanitize_flags_p (SANITIZE_DIVIDE | SANITIZE_FLOAT_DIVIDE)) { @@ -5478,10 +5711,15 @@ cop0 = cp_convert (orig_type, op0, complain); if (TREE_TYPE (cop1) != orig_type) cop1 = cp_convert (orig_type, op1, complain); - instrument_expr = ubsan_instrument_division (location, cop0, cop1); + instrument_expr1 = ubsan_instrument_division (location, cop0, cop1); } else if (doing_shift && sanitize_flags_p (SANITIZE_SHIFT)) - instrument_expr = ubsan_instrument_shift (location, code, op0, op1); + instrument_expr1 = ubsan_instrument_shift (location, code, op0, op1); + if (instrument_expr != NULL) + instrument_expr = add_stmt_to_compound (instrument_expr, + instrument_expr1); + else + instrument_expr = instrument_expr1; } result = build2_loc (location, resultcode, build_type, op0, op1); @@ -5600,6 +5838,13 @@ else return error_mark_node; } + else if (!verify_type_context (loc, TCTX_POINTER_ARITH, + TREE_TYPE (TREE_TYPE (op0)), + !(complain & tf_error)) + || !verify_type_context (loc, TCTX_POINTER_ARITH, + TREE_TYPE (TREE_TYPE (op1)), + !(complain & tf_error))) + return error_mark_node; /* Determine integer type result of the subtraction. This will usually be the same as the result type (ptrdiff_t), but may need to be a wider @@ -5609,7 +5854,8 @@ else inttype = restype; - if (sanitize_flags_p (SANITIZE_POINTER_SUBTRACT)) + if (!processing_template_decl + && sanitize_flags_p (SANITIZE_POINTER_SUBTRACT)) { op0 = save_expr (op0); op1 = save_expr (op1); @@ -5681,7 +5927,11 @@ if (processing_template_decl) { if (type_dependent_expression_p (xarg)) - return build_min_nt_loc (loc, code, xarg.get_value (), NULL_TREE); + { + tree e = build_min_nt_loc (loc, code, xarg.get_value (), NULL_TREE); + maybe_save_operator_binding (e); + return e; + } xarg = build_non_dependent_expr (xarg); } @@ -5714,10 +5964,10 @@ if (DECL_CONSTRUCTOR_P (fn) || DECL_DESTRUCTOR_P (fn)) { if (complain & tf_error) - error (DECL_CONSTRUCTOR_P (fn) - ? G_("taking address of constructor %qD") - : G_("taking address of destructor %qD"), - fn); + error_at (loc, DECL_CONSTRUCTOR_P (fn) + ? G_("taking address of constructor %qD") + : G_("taking address of destructor %qD"), + fn); return error_mark_node; } } @@ -5732,19 +5982,19 @@ { if (complain & tf_error) { - error ("invalid use of %qE to form a " - "pointer-to-member-function", xarg.get_value ()); + error_at (loc, "invalid use of %qE to form a " + "pointer-to-member-function", xarg.get_value ()); if (TREE_CODE (xarg) != OFFSET_REF) - inform (input_location, " a qualified-id is required"); + inform (loc, " a qualified-id is required"); } return error_mark_node; } else { if (complain & tf_error) - error ("parentheses around %qE cannot be used to form a" - " pointer-to-member-function", - xarg.get_value ()); + error_at (loc, "parentheses around %qE cannot be used to " + "form a pointer-to-member-function", + xarg.get_value ()); else return error_mark_node; PTRMEM_OK_P (xarg) = 1; @@ -5812,34 +6062,42 @@ -1. */ tree -cp_truthvalue_conversion (tree expr) +cp_truthvalue_conversion (tree expr, tsubst_flags_t complain) { tree type = TREE_TYPE (expr); + location_t loc = cp_expr_loc_or_input_loc (expr); if (TYPE_PTR_OR_PTRMEM_P (type) /* Avoid ICE on invalid use of non-static member function. */ || TREE_CODE (expr) == FUNCTION_DECL) - return build_binary_op (input_location, NE_EXPR, expr, nullptr_node, true); + return cp_build_binary_op (loc, NE_EXPR, expr, nullptr_node, complain); else - return c_common_truthvalue_conversion (input_location, expr); -} - -/* Just like cp_truthvalue_conversion, but we want a CLEANUP_POINT_EXPR. */ + return c_common_truthvalue_conversion (loc, expr); +} + +/* Returns EXPR contextually converted to bool. */ + +tree +contextual_conv_bool (tree expr, tsubst_flags_t complain) +{ + return perform_implicit_conversion_flags (boolean_type_node, expr, + complain, LOOKUP_NORMAL); +} + +/* Just like cp_truthvalue_conversion, but we want a CLEANUP_POINT_EXPR. This + is a low-level function; most callers should use maybe_convert_cond. */ tree condition_conversion (tree expr) { - tree t; - /* Anything that might happen in a template should go through - maybe_convert_cond. */ - gcc_assert (!processing_template_decl); - t = perform_implicit_conversion_flags (boolean_type_node, expr, - tf_warning_or_error, LOOKUP_NORMAL); - t = fold_build_cleanup_point_expr (boolean_type_node, t); + tree t = contextual_conv_bool (expr, tf_warning_or_error); + if (!processing_template_decl) + t = fold_build_cleanup_point_expr (boolean_type_node, t); return t; } /* Returns the address of T. This function will fold away - ADDR_EXPR of INDIRECT_REF. */ + ADDR_EXPR of INDIRECT_REF. This is only for low-level usage; + most places should use cp_build_addr_expr instead. */ tree build_address (tree t) @@ -5885,6 +6143,7 @@ return error_mark_node; argtype = lvalue_type (arg); + location_t loc = cp_expr_loc_or_input_loc (arg); gcc_assert (!(identifier_p (arg) && IDENTIFIER_ANY_OP_P (arg))); @@ -5918,12 +6177,14 @@ else if (current_class_type && TREE_OPERAND (arg, 0) == current_class_ref) /* An expression like &memfn. */ - permerror (input_location, "ISO C++ forbids taking the address of an unqualified" + permerror (loc, + "ISO C++ forbids taking the address of an unqualified" " or parenthesized non-static member function to form" " a pointer to member function. Say %<&%T::%D%>", base, name); else - permerror (input_location, "ISO C++ forbids taking the address of a bound member" + permerror (loc, + "ISO C++ forbids taking the address of a bound member" " function to form a pointer to member function." " Say %<&%T::%D%>", base, name); @@ -5944,14 +6205,13 @@ /* Anything not already handled and not a true memory reference is an error. */ - if (TREE_CODE (argtype) != FUNCTION_TYPE - && TREE_CODE (argtype) != METHOD_TYPE) + if (!FUNC_OR_METHOD_TYPE_P (argtype)) { cp_lvalue_kind kind = lvalue_kind (arg); if (kind == clk_none) { if (complain & tf_error) - lvalue_error (input_location, lv_addressof); + lvalue_error (loc, lv_addressof); return error_mark_node; } if (strict_lvalue && (kind & (clk_rvalueref|clk_class))) @@ -5959,7 +6219,7 @@ if (!(complain & tf_error)) return error_mark_node; /* Make this a permerror because we used to accept it. */ - permerror (input_location, "taking address of rvalue"); + permerror (loc, "taking address of rvalue"); } } @@ -5969,13 +6229,13 @@ arg = build1 (CONVERT_EXPR, type, arg); return arg; } - else if (pedantic && DECL_MAIN_P (arg)) + else if (pedantic && DECL_MAIN_P (tree_strip_any_location_wrapper (arg))) { /* ARM $3.4 */ /* Apparently a lot of autoconf scripts for C++ packages do this, so only complain if -Wpedantic. */ if (complain & (flag_pedantic_errors ? tf_error : tf_warning)) - pedwarn (input_location, OPT_Wpedantic, + pedwarn (loc, OPT_Wpedantic, "ISO C++ forbids taking address of function %<::main%>"); else if (flag_pedantic_errors) return error_mark_node; @@ -6033,7 +6293,8 @@ if (TYPE_REF_P (TREE_TYPE (t))) { if (complain & tf_error) - error ("cannot create pointer to reference member %qD", t); + error_at (loc, + "cannot create pointer to reference member %qD", t); return error_mark_node; } @@ -6053,7 +6314,7 @@ if (bitfield_p (arg)) { if (complain & tf_error) - error ("attempt to take address of bit-field"); + error_at (loc, "attempt to take address of bit-field"); return error_mark_node; } @@ -6061,8 +6322,19 @@ 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 + && DECL_IMMEDIATE_FUNCTION_P (stripped_arg) + && (current_function_decl == NULL_TREE + || !DECL_IMMEDIATE_FUNCTION_P (current_function_decl))) + { + if (complain & tf_error) + error_at (loc, "taking address of an immediate function %qD", + stripped_arg); + return error_mark_node; + } + 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) @@ -6135,7 +6407,7 @@ { /* No default_conversion here. It causes trouble for ADDR_EXPR. */ tree arg = xarg; - location_t location = cp_expr_loc_or_loc (arg, input_location); + location_t location = cp_expr_loc_or_input_loc (arg); tree argtype = 0; const char *errstring = NULL; tree val; @@ -6144,11 +6416,13 @@ if (!arg || error_operand_p (arg)) return error_mark_node; + arg = resolve_nondeduced_context (arg, complain); + if ((invalid_op_diag = targetm.invalid_unary_op ((code == UNARY_PLUS_EXPR ? CONVERT_EXPR : code), - TREE_TYPE (xarg)))) + TREE_TYPE (arg)))) { if (complain & tf_error) error (invalid_op_diag); @@ -6171,7 +6445,7 @@ : _("wrong type argument to unary plus")); else { - if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg))) + if (!noconvert && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (arg))) arg = cp_perform_integral_promotions (arg, complain); /* Make sure the result is not an lvalue: a unary plus or minus @@ -6196,13 +6470,13 @@ | WANT_VECTOR_OR_COMPLEX, arg, true))) errstring = _("wrong type argument to bit-complement"); - else if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg))) + else if (!noconvert && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (arg))) { /* Warn if the expression has boolean value. */ if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE && (complain & tf_warning) && warning_at (location, OPT_Wbool_operation, - "%<~%> on an expression of type bool")) + "%<~%> on an expression of type %<bool%>")) inform (location, "did you mean to use logical not (%<!%>)?"); arg = cp_perform_integral_promotions (arg, complain); } @@ -6234,12 +6508,12 @@ break; case TRUTH_NOT_EXPR: - if (VECTOR_TYPE_P (TREE_TYPE (arg))) + if (gnu_vector_type_p (TREE_TYPE (arg))) return cp_build_binary_op (input_location, EQ_EXPR, arg, build_zero_cst (TREE_TYPE (arg)), complain); arg = perform_implicit_conversion (boolean_type_node, arg, complain); - val = invert_truthvalue_loc (input_location, arg); + val = invert_truthvalue_loc (location, arg); if (arg != error_mark_node) return val; errstring = _("in argument to unary !"); @@ -6324,7 +6598,8 @@ if (TREE_CODE (argtype) == ENUMERAL_TYPE) { if (complain & tf_error) - permerror (input_location, (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) + permerror (location, (code == PREINCREMENT_EXPR + || code == POSTINCREMENT_EXPR) ? G_("ISO C++ forbids incrementing an enum") : G_("ISO C++ forbids decrementing an enum")); else @@ -6340,26 +6615,34 @@ if (!COMPLETE_OR_VOID_TYPE_P (type)) { if (complain & tf_error) - error (((code == PREINCREMENT_EXPR - || code == POSTINCREMENT_EXPR)) - ? G_("cannot increment a pointer to incomplete type %qT") - : G_("cannot decrement a pointer to incomplete type %qT"), - TREE_TYPE (argtype)); + error_at (location, ((code == PREINCREMENT_EXPR + || code == POSTINCREMENT_EXPR)) + ? G_("cannot increment a pointer to incomplete " + "type %qT") + : G_("cannot decrement a pointer to incomplete " + "type %qT"), + TREE_TYPE (argtype)); else return error_mark_node; } else if (!TYPE_PTROB_P (argtype)) { if (complain & tf_error) - pedwarn (input_location, OPT_Wpointer_arith, + pedwarn (location, OPT_Wpointer_arith, (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) - ? G_("ISO C++ forbids incrementing a pointer of type %qT") - : G_("ISO C++ forbids decrementing a pointer of type %qT"), + ? G_("ISO C++ forbids incrementing a pointer " + "of type %qT") + : G_("ISO C++ forbids decrementing a pointer " + "of type %qT"), argtype); else return error_mark_node; } + else if (!verify_type_context (location, TCTX_POINTER_ARITH, + TREE_TYPE (argtype), + !(complain & tf_error))) + return error_mark_node; inc = cxx_sizeof_nowarn (TREE_TYPE (argtype)); } @@ -6384,14 +6667,26 @@ complain)) return error_mark_node; + /* [depr.volatile.type] "Postfix ++ and -- expressions and + prefix ++ and -- expressions of volatile-qualified arithmetic + and pointer types are deprecated." */ + if (TREE_THIS_VOLATILE (arg) || CP_TYPE_VOLATILE_P (TREE_TYPE (arg))) + warning_at (location, OPT_Wvolatile, + "%qs expression of %<volatile%>-qualified type is " + "deprecated", + ((code == PREINCREMENT_EXPR + || code == POSTINCREMENT_EXPR) + ? "++" : "--")); + /* Forbid using -- or ++ in C++17 on `bool'. */ if (TREE_CODE (declared_type) == BOOLEAN_TYPE) { if (code == POSTDECREMENT_EXPR || code == PREDECREMENT_EXPR) { if (complain & tf_error) - error ("use of an operand of type %qT in %<operator--%> " - "is forbidden", boolean_type_node); + error_at (location, + "use of an operand of type %qT in %<operator--%> " + "is forbidden", boolean_type_node); return error_mark_node; } else @@ -6399,16 +6694,18 @@ if (cxx_dialect >= cxx17) { if (complain & tf_error) - error ("use of an operand of type %qT in " - "%<operator++%> is forbidden in C++17", - boolean_type_node); + error_at (location, + "use of an operand of type %qT in " + "%<operator++%> is forbidden in C++17", + boolean_type_node); return error_mark_node; } /* Otherwise, [depr.incr.bool] says this is deprecated. */ - else if (!in_system_header_at (input_location)) - warning (OPT_Wdeprecated, "use of an operand of type %qT " - "in %<operator++%> is deprecated", - boolean_type_node); + else + warning_at (location, OPT_Wdeprecated, + "use of an operand of type %qT " + "in %<operator++%> is deprecated", + boolean_type_node); } val = boolean_increment (code, arg); } @@ -6439,7 +6736,7 @@ } if (complain & tf_error) - error ("%s", errstring); + error_at (location, "%s", errstring); return error_mark_node; } @@ -6521,8 +6818,7 @@ return arg; } - if (TREE_CODE (TREE_TYPE (arg)) == FUNCTION_TYPE - || TREE_CODE (TREE_TYPE (arg)) == METHOD_TYPE + if (FUNC_OR_METHOD_TYPE_P (TREE_TYPE (arg)) || TREE_CODE (arg) == OFFSET_REF) return NULL_TREE; @@ -6688,7 +6984,7 @@ && !CONSTRUCTOR_IS_DIRECT_INIT (expr)) { if (complain & tf_error) - pedwarn (cp_expr_loc_or_loc (expr, input_location), 0, + pedwarn (cp_expr_loc_or_input_loc (expr), 0, "list-initializer for non-class type must not " "be parenthesized"); else @@ -6832,7 +7128,8 @@ if (type_unknown_p (rhs)) { if (complain & tf_error) - error ("no context to resolve type of %qE", rhs); + error_at (cp_expr_loc_or_input_loc (rhs), + "no context to resolve type of %qE", rhs); return error_mark_node; } @@ -6849,8 +7146,9 @@ */ static bool -check_for_casting_away_constness (tree src_type, tree dest_type, - enum tree_code cast, tsubst_flags_t complain) +check_for_casting_away_constness (location_t loc, tree src_type, + tree dest_type, enum tree_code cast, + tsubst_flags_t complain) { /* C-style casts are allowed to cast away constness. With WARN_CAST_QUAL, we still want to issue a warning. */ @@ -6864,21 +7162,23 @@ { case CAST_EXPR: if (complain & tf_warning) - warning (OPT_Wcast_qual, - "cast from type %qT to type %qT casts away qualifiers", - src_type, dest_type); + warning_at (loc, OPT_Wcast_qual, + "cast from type %qT to type %qT casts away qualifiers", + src_type, dest_type); return false; - + case STATIC_CAST_EXPR: if (complain & tf_error) - error ("static_cast from type %qT to type %qT casts away qualifiers", - src_type, dest_type); + error_at (loc, "%<static_cast%> from type %qT to type %qT casts " + "away qualifiers", + src_type, dest_type); return true; - + case REINTERPRET_CAST_EXPR: if (complain & tf_error) - error ("reinterpret_cast from type %qT to type %qT casts away qualifiers", - src_type, dest_type); + error_at (loc, "%<reinterpret_cast%> from type %qT to type %qT " + "casts away qualifiers", + src_type, dest_type); return true; default: @@ -6888,7 +7188,8 @@ /* Warns if the cast from expression EXPR to type TYPE is useless. */ void -maybe_warn_about_useless_cast (tree type, tree expr, tsubst_flags_t complain) +maybe_warn_about_useless_cast (location_t loc, tree type, tree expr, + tsubst_flags_t complain) { if (warn_useless_cast && complain & tf_warning) @@ -6898,22 +7199,22 @@ ? xvalue_p (expr) : lvalue_p (expr)) && same_type_p (TREE_TYPE (expr), TREE_TYPE (type))) || same_type_p (TREE_TYPE (expr), type)) - warning (OPT_Wuseless_cast, "useless cast to type %q#T", type); + warning_at (loc, OPT_Wuseless_cast, + "useless cast to type %q#T", type); } } /* Warns if the cast ignores cv-qualifiers on TYPE. */ -void -maybe_warn_about_cast_ignoring_quals (tree type, tsubst_flags_t complain) +static void +maybe_warn_about_cast_ignoring_quals (location_t loc, tree type, + tsubst_flags_t complain) { if (warn_ignored_qualifiers && complain & tf_warning && !CLASS_TYPE_P (type) && (cp_type_quals (type) & (TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE))) - { - warning (OPT_Wignored_qualifiers, "type qualifiers ignored on cast " - "result type"); - } + warning_at (loc, OPT_Wignored_qualifiers, + "type qualifiers ignored on cast result type"); } /* Convert EXPR (an expression with pointer-to-member type) to TYPE @@ -6972,7 +7273,7 @@ indicate whether or not the cast was valid. */ static tree -build_static_cast_1 (tree type, tree expr, bool c_cast_p, +build_static_cast_1 (location_t loc, tree type, tree expr, bool c_cast_p, bool *valid_p, tsubst_flags_t complain) { tree intype; @@ -7036,12 +7337,12 @@ base = lookup_base (TREE_TYPE (type), intype, c_cast_p ? ba_unique : ba_check, NULL, complain); - expr = build_address (expr); + expr = cp_build_addr_expr (expr, complain); if (sanitize_flags_p (SANITIZE_VPTR)) { tree ubsan_check - = cp_ubsan_maybe_instrument_downcast (input_location, type, + = cp_ubsan_maybe_instrument_downcast (loc, type, intype, expr); if (ubsan_check) expr = ubsan_check; @@ -7164,8 +7465,8 @@ conversion does not cast away constness (_expr.const.cast_), and the following additional rules for specific cases: */ /* For reference, the conversions not excluded are: integral - promotions, floating point promotion, integral conversions, - floating point conversions, floating-integral conversions, + promotions, floating-point promotion, integral conversions, + floating-point conversions, floating-integral conversions, pointer conversions, and pointer to member conversions. */ /* DR 128 @@ -7199,7 +7500,8 @@ return expr; if (!c_cast_p - && check_for_casting_away_constness (intype, type, STATIC_CAST_EXPR, + && check_for_casting_away_constness (loc, intype, type, + STATIC_CAST_EXPR, complain)) return error_mark_node; base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype), @@ -7211,7 +7513,7 @@ if (sanitize_flags_p (SANITIZE_VPTR)) { tree ubsan_check - = cp_ubsan_maybe_instrument_downcast (input_location, type, + = cp_ubsan_maybe_instrument_downcast (loc, type, intype, expr); if (ubsan_check) expr = ubsan_check; @@ -7248,7 +7550,7 @@ if (can_convert (t1, t2, complain) || can_convert (t2, t1, complain)) { if (!c_cast_p - && check_for_casting_away_constness (intype, type, + && check_for_casting_away_constness (loc, intype, type, STATIC_CAST_EXPR, complain)) return error_mark_node; @@ -7270,7 +7572,8 @@ && TYPE_PTROB_P (type)) { if (!c_cast_p - && check_for_casting_away_constness (intype, type, STATIC_CAST_EXPR, + && check_for_casting_away_constness (loc, intype, type, + STATIC_CAST_EXPR, complain)) return error_mark_node; if (processing_template_decl) @@ -7285,7 +7588,8 @@ /* Return an expression representing static_cast<TYPE>(EXPR). */ tree -build_static_cast (tree type, tree oexpr, tsubst_flags_t complain) +build_static_cast (location_t loc, tree type, tree oexpr, + tsubst_flags_t complain) { tree expr = oexpr; tree result; @@ -7302,7 +7606,9 @@ expr = build_min (STATIC_CAST_EXPR, type, oexpr); /* We don't know if it will or will not have side effects. */ TREE_SIDE_EFFECTS (expr) = 1; - return convert_from_reference (expr); + result = convert_from_reference (expr); + protected_set_expr_location (result, loc); + return result; } else if (processing_template_decl) expr = build_non_dependent_expr (expr); @@ -7314,23 +7620,37 @@ && TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0))) expr = TREE_OPERAND (expr, 0); - result = build_static_cast_1 (type, expr, /*c_cast_p=*/false, &valid_p, - complain); + result = build_static_cast_1 (loc, type, expr, /*c_cast_p=*/false, + &valid_p, complain); if (valid_p) { if (result != error_mark_node) { - maybe_warn_about_useless_cast (type, expr, complain); - maybe_warn_about_cast_ignoring_quals (type, complain); + maybe_warn_about_useless_cast (loc, type, expr, complain); + maybe_warn_about_cast_ignoring_quals (loc, type, complain); } if (processing_template_decl) goto tmpl; + protected_set_expr_location (result, loc); return result; } if (complain & tf_error) - error ("invalid static_cast from type %qT to type %qT", - TREE_TYPE (expr), type); + { + error_at (loc, "invalid %<static_cast%> from type %qT to type %qT", + TREE_TYPE (expr), type); + if ((TYPE_PTR_P (type) || TYPE_REF_P (type)) + && CLASS_TYPE_P (TREE_TYPE (type)) + && !COMPLETE_TYPE_P (TREE_TYPE (type))) + inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (TREE_TYPE (type))), + "class type %qT is incomplete", TREE_TYPE (type)); + tree expr_type = TREE_TYPE (expr); + if (TYPE_PTR_P (expr_type)) + expr_type = TREE_TYPE (expr_type); + if (CLASS_TYPE_P (expr_type) && !COMPLETE_TYPE_P (expr_type)) + inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (expr_type)), + "class type %qT is incomplete", expr_type); + } return error_mark_node; } @@ -7392,8 +7712,9 @@ indicate whether or not reinterpret_cast was valid. */ static tree -build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p, - bool *valid_p, tsubst_flags_t complain) +build_reinterpret_cast_1 (location_t loc, tree type, tree expr, + bool c_cast_p, bool *valid_p, + tsubst_flags_t complain) { tree intype; @@ -7420,7 +7741,7 @@ reinterpret_cast. */ if (TYPE_REF_P (type)) { - if (TYPE_REF_IS_RVALUE (type)) + if (TYPE_REF_IS_RVALUE (type) && !VOID_TYPE_P (intype)) { if (!obvalue_p (expr)) /* Perform the temporary materialization conversion. */ @@ -7429,9 +7750,9 @@ else if (!lvalue_p (expr)) { if (complain & tf_error) - error ("invalid cast of an rvalue expression of type " - "%qT to type %qT", - intype, type); + error_at (loc, "invalid cast of an rvalue expression of type " + "%qT to type %qT", + intype, type); return error_mark_node; } @@ -7442,8 +7763,8 @@ && (complain & tf_warning) && (comptypes (TREE_TYPE (intype), TREE_TYPE (type), COMPARE_BASE | COMPARE_DERIVED))) - warning (0, "casting %qT to %qT does not dereference pointer", - intype, type); + warning_at (loc, 0, "casting %qT to %qT does not dereference pointer", + intype, type); expr = cp_build_addr_expr (expr, complain); @@ -7452,7 +7773,7 @@ if (expr != error_mark_node) expr = build_reinterpret_cast_1 - (build_pointer_type (TREE_TYPE (type)), expr, c_cast_p, + (loc, build_pointer_type (TREE_TYPE (type)), expr, c_cast_p, valid_p, complain); if (expr != error_mark_node) /* cp_build_indirect_ref isn't right for rvalue refs. */ @@ -7499,7 +7820,7 @@ if (TYPE_PRECISION (type) < TYPE_PRECISION (intype)) { if (complain & tf_error) - permerror (input_location, "cast from %qH to %qI loses precision", + permerror (loc, "cast from %qH to %qI loses precision", intype, type); else return error_mark_node; @@ -7523,9 +7844,9 @@ if ((complain & tf_warning) && !cxx_safe_function_type_cast_p (TREE_TYPE (type), TREE_TYPE (intype))) - warning (OPT_Wcast_function_type, - "cast between incompatible function types" - " from %qH to %qI", intype, type); + warning_at (loc, OPT_Wcast_function_type, + "cast between incompatible function types" + " from %qH to %qI", intype, type); return build_nop_reinterpret (type, expr); } else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)) @@ -7534,16 +7855,16 @@ && !cxx_safe_function_type_cast_p (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE_RAW (type)), TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE_RAW (intype)))) - warning (OPT_Wcast_function_type, - "cast between incompatible pointer to member types" - " from %qH to %qI", intype, type); + warning_at (loc, OPT_Wcast_function_type, + "cast between incompatible pointer to member types" + " from %qH to %qI", intype, type); return build_nop_reinterpret (type, expr); } else if ((TYPE_PTRDATAMEM_P (type) && TYPE_PTRDATAMEM_P (intype)) || (TYPE_PTROBV_P (type) && TYPE_PTROBV_P (intype))) { if (!c_cast_p - && check_for_casting_away_constness (intype, type, + && check_for_casting_away_constness (loc, intype, type, REINTERPRET_CAST_EXPR, complain)) return error_mark_node; @@ -7556,8 +7877,9 @@ && COMPLETE_TYPE_P (TREE_TYPE (intype)) && min_align_of_type (TREE_TYPE (type)) > min_align_of_type (TREE_TYPE (intype))) - warning (OPT_Wcast_align, "cast from %qH to %qI " - "increases required alignment of target type", intype, type); + warning_at (loc, OPT_Wcast_align, "cast from %qH to %qI " + "increases required alignment of target type", + intype, type); if (warn_strict_aliasing <= 2) /* strict_aliasing_warning STRIP_NOPs its expr. */ @@ -7571,14 +7893,14 @@ if (complain & tf_warning) /* C++11 5.2.10 p8 says that "Converting a function pointer to an object pointer type or vice versa is conditionally-supported." */ - warning (OPT_Wconditionally_supported, - "casting between pointer-to-function and pointer-to-object " - "is conditionally-supported"); + warning_at (loc, OPT_Wconditionally_supported, + "casting between pointer-to-function and " + "pointer-to-object is conditionally-supported"); return build_nop_reinterpret (type, expr); } - else if (VECTOR_TYPE_P (type)) - return convert_to_vector (type, expr); - else if (VECTOR_TYPE_P (intype) + else if (gnu_vector_type_p (type)) + return convert_to_vector (type, rvalue (expr)); + else if (gnu_vector_type_p (intype) && INTEGRAL_OR_ENUMERATION_TYPE_P (type)) return convert_to_integer_nofold (type, expr); else @@ -7586,7 +7908,8 @@ if (valid_p) *valid_p = false; if (complain & tf_error) - error ("invalid cast from type %qT to type %qT", intype, type); + error_at (loc, "invalid cast from type %qT to type %qT", + intype, type); return error_mark_node; } @@ -7598,7 +7921,8 @@ } tree -build_reinterpret_cast (tree type, tree expr, tsubst_flags_t complain) +build_reinterpret_cast (location_t loc, tree type, tree expr, + tsubst_flags_t complain) { tree r; @@ -7613,16 +7937,19 @@ && type_dependent_expression_p (expr)) /* There might turn out to be side effects inside expr. */ TREE_SIDE_EFFECTS (t) = 1; - return convert_from_reference (t); - } - - r = build_reinterpret_cast_1 (type, expr, /*c_cast_p=*/false, + r = convert_from_reference (t); + protected_set_expr_location (r, loc); + return r; + } + + r = build_reinterpret_cast_1 (loc, type, expr, /*c_cast_p=*/false, /*valid_p=*/NULL, complain); if (r != error_mark_node) { - maybe_warn_about_useless_cast (type, expr, complain); - maybe_warn_about_cast_ignoring_quals (type, complain); - } + maybe_warn_about_useless_cast (loc, type, expr, complain); + maybe_warn_about_cast_ignoring_quals (loc, type, complain); + } + protected_set_expr_location (r, loc); return r; } @@ -7634,8 +7961,8 @@ whether or not the conversion succeeded. */ static tree -build_const_cast_1 (tree dst_type, tree expr, tsubst_flags_t complain, - bool *valid_p) +build_const_cast_1 (location_t loc, tree dst_type, tree expr, + tsubst_flags_t complain, bool *valid_p) { tree src_type; tree reference_type; @@ -7654,18 +7981,19 @@ if (!INDIRECT_TYPE_P (dst_type) && !TYPE_PTRDATAMEM_P (dst_type)) { if (complain & tf_error) - error ("invalid use of const_cast with type %qT, " - "which is not a pointer, " - "reference, nor a pointer-to-data-member type", dst_type); + error_at (loc, "invalid use of %<const_cast%> with type %qT, " + "which is not a pointer, reference, " + "nor a pointer-to-data-member type", dst_type); return error_mark_node; } if (TREE_CODE (TREE_TYPE (dst_type)) == FUNCTION_TYPE) { if (complain & tf_error) - error ("invalid use of const_cast with type %qT, which is a pointer " - "or reference to a function type", dst_type); - return error_mark_node; + error_at (loc, "invalid use of %<const_cast%> with type %qT, " + "which is a pointer or reference to a function type", + dst_type); + return error_mark_node; } /* A prvalue of non-class type is cv-unqualified. */ @@ -7704,9 +8032,10 @@ else { if (complain & tf_error) - error ("invalid const_cast of an rvalue of type %qT to type %qT", - src_type, dst_type); - return error_mark_node; + error_at (loc, "invalid %<const_cast%> of an rvalue of type %qT " + "to type %qT", + src_type, dst_type); + return error_mark_node; } dst_type = build_pointer_type (TREE_TYPE (dst_type)); src_type = build_pointer_type (src_type); @@ -7724,23 +8053,23 @@ if (TYPE_PTR_P (src_type) || TYPE_PTRDATAMEM_P (src_type)) { - if (comp_ptr_ttypes_const (dst_type, src_type)) + if (comp_ptr_ttypes_const (dst_type, src_type, bounds_none)) { if (valid_p) { *valid_p = true; /* This cast is actually a C-style cast. Issue a warning if the user is making a potentially unsafe cast. */ - check_for_casting_away_constness (src_type, dst_type, + check_for_casting_away_constness (loc, src_type, dst_type, CAST_EXPR, complain); /* ??? comp_ptr_ttypes_const ignores TYPE_ALIGN. */ if ((STRICT_ALIGNMENT || warn_cast_align == 2) && (complain & tf_warning) && min_align_of_type (TREE_TYPE (dst_type)) > min_align_of_type (TREE_TYPE (src_type))) - warning (OPT_Wcast_align, "cast from %qH to %qI " - "increases required alignment of target type", - src_type, dst_type); + warning_at (loc, OPT_Wcast_align, "cast from %qH to %qI " + "increases required alignment of target type", + src_type, dst_type); } if (reference_type) { @@ -7768,18 +8097,19 @@ else if (valid_p && !at_least_as_qualified_p (TREE_TYPE (dst_type), TREE_TYPE (src_type))) - check_for_casting_away_constness (src_type, dst_type, CAST_EXPR, - complain); + check_for_casting_away_constness (loc, src_type, dst_type, + CAST_EXPR, complain); } if (complain & tf_error) - error ("invalid const_cast from type %qT to type %qT", - src_type, dst_type); + error_at (loc, "invalid %<const_cast%> from type %qT to type %qT", + src_type, dst_type); return error_mark_node; } tree -build_const_cast (tree type, tree expr, tsubst_flags_t complain) +build_const_cast (location_t loc, tree type, tree expr, + tsubst_flags_t complain) { tree r; @@ -7794,24 +8124,27 @@ && type_dependent_expression_p (expr)) /* There might turn out to be side effects inside expr. */ TREE_SIDE_EFFECTS (t) = 1; - return convert_from_reference (t); - } - - r = build_const_cast_1 (type, expr, complain, /*valid_p=*/NULL); + r = convert_from_reference (t); + protected_set_expr_location (r, loc); + return r; + } + + r = build_const_cast_1 (loc, type, expr, complain, /*valid_p=*/NULL); if (r != error_mark_node) { - maybe_warn_about_useless_cast (type, expr, complain); - maybe_warn_about_cast_ignoring_quals (type, complain); - } + maybe_warn_about_useless_cast (loc, type, expr, complain); + maybe_warn_about_cast_ignoring_quals (loc, type, complain); + } + protected_set_expr_location (r, loc); return r; } /* Like cp_build_c_cast, but for the c-common bits. */ tree -build_c_cast (location_t /*loc*/, tree type, tree expr) -{ - return cp_build_c_cast (type, expr, tf_warning_or_error); +build_c_cast (location_t loc, tree type, tree expr) +{ + return cp_build_c_cast (loc, type, expr, tf_warning_or_error); } /* Like the "build_c_cast" used for c-common, but using cp_expr to @@ -7821,7 +8154,7 @@ cp_expr build_c_cast (location_t loc, tree type, cp_expr expr) { - cp_expr result = cp_build_c_cast (type, expr, tf_warning_or_error); + cp_expr result = cp_build_c_cast (loc, type, expr, tf_warning_or_error); result.set_location (loc); return result; } @@ -7830,7 +8163,8 @@ TYPE of expression EXPR. */ tree -cp_build_c_cast (tree type, tree expr, tsubst_flags_t complain) +cp_build_c_cast (location_t loc, tree type, tree expr, + tsubst_flags_t complain) { tree value = expr; tree result; @@ -7869,7 +8203,8 @@ if (TYPE_PTR_P (TREE_TYPE (expr))) { if (complain & tf_error) - permerror (input_location, "ISO C++ forbids casting to an array type %qT", type); + permerror (loc, "ISO C++ forbids casting to an array type %qT", + type); else return error_mark_node; type = build_pointer_type (TREE_TYPE (type)); @@ -7877,16 +8212,16 @@ else { if (complain & tf_error) - error ("ISO C++ forbids casting to an array type %qT", type); + error_at (loc, "ISO C++ forbids casting to an array type %qT", + type); return error_mark_node; } } - if (TREE_CODE (type) == FUNCTION_TYPE - || TREE_CODE (type) == METHOD_TYPE) + if (FUNC_OR_METHOD_TYPE_P (type)) { if (complain & tf_error) - error ("invalid cast to function type %qT", type); + error_at (loc, "invalid cast to function type %qT", type); return error_mark_node; } @@ -7896,28 +8231,28 @@ && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (value)) /* Don't warn about converting any constant. */ && !TREE_CONSTANT (value)) - warning_at (input_location, OPT_Wint_to_pointer_cast, + warning_at (loc, OPT_Wint_to_pointer_cast, "cast to pointer from integer of different size"); /* A C-style cast can be a const_cast. */ - result = build_const_cast_1 (type, value, complain & tf_warning, + result = build_const_cast_1 (loc, type, value, complain & tf_warning, &valid_p); if (valid_p) { if (result != error_mark_node) { - maybe_warn_about_useless_cast (type, value, complain); - maybe_warn_about_cast_ignoring_quals (type, complain); + maybe_warn_about_useless_cast (loc, type, value, complain); + maybe_warn_about_cast_ignoring_quals (loc, type, complain); } return result; } /* Or a static cast. */ - result = build_static_cast_1 (type, value, /*c_cast_p=*/true, + result = build_static_cast_1 (loc, type, value, /*c_cast_p=*/true, &valid_p, complain); /* Or a reinterpret_cast. */ if (!valid_p) - result = build_reinterpret_cast_1 (type, value, /*c_cast_p=*/true, + result = build_reinterpret_cast_1 (loc, type, value, /*c_cast_p=*/true, &valid_p, complain); /* The static_cast or reinterpret_cast may be followed by a const_cast. */ @@ -7928,8 +8263,8 @@ { tree result_type; - maybe_warn_about_useless_cast (type, value, complain); - maybe_warn_about_cast_ignoring_quals (type, complain); + maybe_warn_about_useless_cast (loc, type, value, complain); + maybe_warn_about_cast_ignoring_quals (loc, type, complain); /* Non-class rvalues always have cv-unqualified type. */ if (!CLASS_TYPE_P (type)) @@ -7944,7 +8279,7 @@ to succeed. */ if (!same_type_p (non_reference (type), non_reference (result_type))) { - result = build_const_cast_1 (type, result, false, &valid_p); + result = build_const_cast_1 (loc, type, result, false, &valid_p); gcc_assert (valid_p); } return result; @@ -8058,12 +8393,11 @@ /* Produce (a ? (b = rhs) : (c = rhs)) except that the RHS goes through a save-expr so the code to compute it is only emitted once. */ - tree cond; - if (VOID_TYPE_P (TREE_TYPE (rhs))) { if (complain & tf_error) - error ("void value not ignored as it ought to be"); + error_at (cp_expr_loc_or_loc (rhs, loc), + "void value not ignored as it ought to be"); return error_mark_node; } @@ -8074,13 +8408,23 @@ if (!lvalue_or_else (lhs, lv_assign, complain)) return error_mark_node; - cond = build_conditional_expr - (input_location, TREE_OPERAND (lhs, 0), - cp_build_modify_expr (loc, TREE_OPERAND (lhs, 1), - modifycode, rhs, complain), - cp_build_modify_expr (loc, TREE_OPERAND (lhs, 2), - modifycode, rhs, complain), - complain); + tree op1 = TREE_OPERAND (lhs, 1); + if (TREE_CODE (op1) != THROW_EXPR) + op1 = cp_build_modify_expr (loc, op1, modifycode, rhs, complain); + /* When sanitizing undefined behavior, even when rhs doesn't need + stabilization at this point, the sanitization might add extra + SAVE_EXPRs in there and so make sure there is no tree sharing + in the rhs, otherwise those SAVE_EXPRs will have initialization + only in one of the two branches. */ + if (sanitize_flags_p (SANITIZE_UNDEFINED + | SANITIZE_UNDEFINED_NONDEFAULT)) + rhs = unshare_expr (rhs); + tree op2 = TREE_OPERAND (lhs, 2); + if (TREE_CODE (op2) != THROW_EXPR) + op2 = cp_build_modify_expr (loc, op2, modifycode, rhs, complain); + tree cond = build_conditional_expr (input_location, + TREE_OPERAND (lhs, 0), op1, op2, + complain); if (cond == error_mark_node) return cond; @@ -8130,11 +8474,10 @@ /* Do the default thing. */; else { - vec<tree, va_gc> *rhs_vec = make_tree_vector_single (rhs); + releasing_vec rhs_vec = make_tree_vector_single (rhs); result = build_special_member_call (lhs, complete_ctor_identifier, &rhs_vec, lhstype, LOOKUP_NORMAL, complain); - release_tree_vector (rhs_vec); if (result == NULL_TREE) return error_mark_node; goto ret; @@ -8181,6 +8524,15 @@ && MAYBE_CLASS_TYPE_P (TREE_TYPE (lhstype))) || MAYBE_CLASS_TYPE_P (lhstype))); + /* An expression of the form E1 op= E2. [expr.ass] says: + "Such expressions are deprecated if E1 has volatile-qualified + type." We warn here rather than in cp_genericize_r because + for compound assignments we are supposed to warn even if the + assignment is a discarded-value expression. */ + if (TREE_THIS_VOLATILE (lhs) || CP_TYPE_VOLATILE_P (lhstype)) + warning_at (loc, OPT_Wvolatile, + "compound assignment with %<volatile%>-qualified left " + "operand is deprecated"); /* Preevaluate the RHS to make sure its evaluation is complete before the lvalue-to-rvalue conversion of the LHS: @@ -8199,8 +8551,8 @@ if (newrhs == error_mark_node) { if (complain & tf_error) - error (" in evaluation of %<%Q(%#T, %#T)%>", modifycode, - TREE_TYPE (lhs), TREE_TYPE (rhs)); + inform (loc, " in evaluation of %<%Q(%#T, %#T)%>", + modifycode, TREE_TYPE (lhs), TREE_TYPE (rhs)); return error_mark_node; } @@ -8230,8 +8582,7 @@ && (TREE_READONLY (lhs) || CP_TYPE_CONST_P (lhstype) /* Functions are not modifiable, even though they are lvalues. */ - || TREE_CODE (TREE_TYPE (lhs)) == FUNCTION_TYPE - || TREE_CODE (TREE_TYPE (lhs)) == METHOD_TYPE + || FUNC_OR_METHOD_TYPE_P (TREE_TYPE (lhs)) /* If it's an aggregate and any field is const, then it is effectively const. */ || (CLASS_TYPE_P (lhstype) @@ -8259,7 +8610,8 @@ if (modifycode != INIT_EXPR) { if (complain & tf_error) - error ("assigning to an array from an initializer list"); + error_at (loc, + "assigning to an array from an initializer list"); return error_mark_node; } if (check_array_initializer (lhs, lhstype, newrhs)) @@ -8272,7 +8624,8 @@ /* 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) { @@ -8285,8 +8638,8 @@ TYPE_MAIN_VARIANT (TREE_TYPE (newrhs)))) { if (complain & tf_error) - error ("incompatible types in assignment of %qT to %qT", - TREE_TYPE (rhs), lhstype); + error_at (loc, "incompatible types in assignment of %qT to %qT", + TREE_TYPE (rhs), lhstype); return error_mark_node; } @@ -8299,9 +8652,9 @@ if (complain & tf_error) { if (modifycode == INIT_EXPR) - error ("array used as initializer"); + error_at (loc, "array used as initializer"); else - error ("invalid array assignment"); + error_at (loc, "invalid array assignment"); } return error_mark_node; } @@ -8353,8 +8706,8 @@ goto ret; } - result = build2 (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR, - lhstype, lhs, newrhs); + result = build2_loc (loc, modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR, + lhstype, lhs, newrhs); TREE_SIDE_EFFECTS (result) = 1; if (!plain_assign) @@ -8435,7 +8788,7 @@ if (!(complain & tf_error)) return error_mark_node; - error (" in pointer to member function conversion"); + inform (input_location, " in pointer to member function conversion"); return size_zero_node; } else if (binfo) @@ -8496,7 +8849,7 @@ return error_mark_node; error_not_base_type (from, to); - error (" in pointer to member conversion"); + inform (input_location, " in pointer to member conversion"); result = size_zero_node; } else @@ -8515,7 +8868,7 @@ return error_mark_node; error_not_base_type (from, to); - error (" in pointer to member conversion"); + inform (input_location, " in pointer to member conversion"); result = size_zero_node; } } @@ -8618,7 +8971,7 @@ if (same_type_p (to_type, pfn_type)) return pfn; else if (integer_zerop (n) && TREE_CODE (pfn) != CONSTRUCTOR) - return build_reinterpret_cast (to_type, pfn, + return build_reinterpret_cast (input_location, to_type, pfn, complain); } @@ -8652,7 +9005,7 @@ /* Handle null pointer to member function conversions. */ if (null_ptr_cst_p (pfn)) { - pfn = cp_build_c_cast (type, pfn, complain); + pfn = cp_build_c_cast (input_location, type, pfn, complain); return build_ptrmemfunc1 (to_type, integer_zero_node, pfn); @@ -8790,8 +9143,12 @@ tree rhstype; enum tree_code coder; - /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ - if (TREE_CODE (rhs) == NON_LVALUE_EXPR) + location_t rhs_loc = EXPR_LOC_OR_LOC (rhs, input_location); + bool has_loc = EXPR_LOCATION (rhs) != UNKNOWN_LOCATION; + /* 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 @@ -8803,7 +9160,7 @@ { warning_sentinel w (warn_useless_cast); warning_sentinel w2 (warn_ignored_qualifiers); - rhs = cp_build_c_cast (type, elt, complain); + rhs = cp_build_c_cast (rhs_loc, type, elt, complain); } else rhs = error_mark_node; @@ -8828,7 +9185,7 @@ if (coder == VOID_TYPE) { if (complain & tf_error) - error ("void value not ignored as it ought to be"); + error_at (rhs_loc, "void value not ignored as it ought to be"); return error_mark_node; } @@ -8896,39 +9253,47 @@ parmnum, complain, flags); } else if (fndecl) - complain_about_bad_argument (cp_expr_location (rhs), + complain_about_bad_argument (rhs_loc, rhstype, type, fndecl, parmnum); else - switch (errtype) - { + { + range_label_for_type_mismatch label (rhstype, type); + gcc_rich_location richloc (rhs_loc, has_loc ? &label : NULL); + switch (errtype) + { case ICR_DEFAULT_ARGUMENT: - error ("cannot convert %qH to %qI in default argument", - rhstype, type); + error_at (&richloc, + "cannot convert %qH to %qI in default argument", + rhstype, type); break; case ICR_ARGPASS: - error ("cannot convert %qH to %qI in argument passing", - rhstype, type); + error_at (&richloc, + "cannot convert %qH to %qI in argument passing", + rhstype, type); break; case ICR_CONVERTING: - error ("cannot convert %qH to %qI", - rhstype, type); + error_at (&richloc, "cannot convert %qH to %qI", + rhstype, type); break; case ICR_INIT: - error ("cannot convert %qH to %qI in initialization", - rhstype, type); + error_at (&richloc, + "cannot convert %qH to %qI in initialization", + rhstype, type); break; case ICR_RETURN: - error ("cannot convert %qH to %qI in return", - rhstype, type); + error_at (&richloc, "cannot convert %qH to %qI in return", + rhstype, type); break; case ICR_ASSIGN: - error ("cannot convert %qH to %qI in assignment", - rhstype, type); + error_at (&richloc, + "cannot convert %qH to %qI in assignment", + rhstype, type); break; default: gcc_unreachable(); } + } if (TYPE_PTR_P (rhstype) && TYPE_PTR_P (type) && CLASS_TYPE_P (TREE_TYPE (rhstype)) @@ -8993,14 +9358,14 @@ && TREE_CODE (rhs) == MODIFY_EXPR && !TREE_NO_WARNING (rhs) && TREE_CODE (TREE_TYPE (rhs)) != BOOLEAN_TYPE - && (complain & tf_warning)) - { - location_t loc = cp_expr_loc_or_loc (rhs, input_location); - - warning_at (loc, OPT_Wparentheses, - "suggest parentheses around assignment used as truth value"); - TREE_NO_WARNING (rhs) = 1; - } + && (complain & tf_warning) + && warning_at (rhs_loc, OPT_Wparentheses, + "suggest parentheses around assignment used as " + "truth value")) + TREE_NO_WARNING (rhs) = 1; + + if (complain & tf_warning) + warn_for_address_or_pointer_of_packed_member (type, rhs); return perform_implicit_conversion_flags (strip_top_quals (type), rhs, complain, flags); @@ -9063,6 +9428,7 @@ if (codel == REFERENCE_TYPE) { + auto_diagnostic_group d; /* This should eventually happen in convert_arguments. */ int savew = 0, savee = 0; @@ -9072,9 +9438,8 @@ if (fndecl && (warningcount + werrorcount > savew || errorcount > savee)) - inform (DECL_SOURCE_LOCATION (fndecl), + inform (get_fndecl_argument_location (fndecl, parmnum), "in passing argument %P of %qD", parmnum, fndecl); - return rhs; } @@ -9083,8 +9448,6 @@ if (exp == error_mark_node) return error_mark_node; - rhstype = non_reference (rhstype); - type = complete_type (type); if (DIRECT_INIT_EXPR_P (type, rhs)) @@ -9103,11 +9466,12 @@ temporary give an appropriate warning and return true. */ static bool -maybe_warn_about_returning_address_of_local (tree retval) +maybe_warn_about_returning_address_of_local (tree retval, location_t loc) { tree valtype = TREE_TYPE (DECL_RESULT (current_function_decl)); tree whats_returned = fold_for_warn (retval); - location_t loc = cp_expr_loc_or_loc (retval, input_location); + if (!loc) + loc = cp_expr_loc_or_input_loc (retval); for (;;) { @@ -9141,7 +9505,7 @@ || is_std_forward_p (whats_returned))) { tree arg = CALL_EXPR_ARG (whats_returned, 0); - return maybe_warn_about_returning_address_of_local (arg); + return maybe_warn_about_returning_address_of_local (arg, loc); } if (TREE_CODE (whats_returned) != ADDR_EXPR) @@ -9160,11 +9524,13 @@ "returning reference to temporary"); else if (is_std_init_list (valtype)) warning_at (loc, OPT_Winit_list_lifetime, - "returning temporary initializer_list does not extend " + "returning temporary %<initializer_list%> does not extend " "the lifetime of the underlying array"); return true; } + STRIP_ANY_LOCATION_WRAPPER (whats_returned); + if (DECL_P (whats_returned) && DECL_NAME (whats_returned) && DECL_FUNCTION_SCOPE_P (whats_returned) @@ -9184,8 +9550,10 @@ tree base = DECL_DECOMP_BASE (whats_returned); if (TYPE_REF_P (TREE_TYPE (base))) { - tree init = DECL_INITIAL (base); - return maybe_warn_about_returning_address_of_local (init); + if (tree init = DECL_INITIAL (base)) + return maybe_warn_about_returning_address_of_local (init, loc); + else + return false; } } bool w = false; @@ -9196,14 +9564,15 @@ whats_returned); else if (is_std_init_list (valtype)) w = warning_at (loc, OPT_Winit_list_lifetime, - "returning local initializer_list variable %qD " + "returning local %<initializer_list%> variable %qD " "does not extend the lifetime of the underlying array", whats_returned); - else if (TREE_CODE (whats_returned) == LABEL_DECL) + else if (POINTER_TYPE_P (valtype) + && TREE_CODE (whats_returned) == LABEL_DECL) w = warning_at (loc, OPT_Wreturn_local_addr, "address of label %qD returned", whats_returned); - else + else if (POINTER_TYPE_P (valtype)) w = warning_at (loc, OPT_Wreturn_local_addr, "address of local variable %qD returned", whats_returned); @@ -9218,11 +9587,22 @@ /* Returns true if DECL is in the std namespace. */ -static bool +bool decl_in_std_namespace_p (tree decl) { - return (decl != NULL_TREE - && DECL_NAMESPACE_STD_P (decl_namespace_context (decl))); + while (decl) + { + decl = decl_namespace_context (decl); + if (DECL_NAMESPACE_STD_P (decl)) + return true; + /* Allow inline namespaces inside of std namespace, e.g. with + --enable-symvers=gnu-versioned-namespace std::forward would be + actually std::_8::forward. */ + if (!DECL_NAMESPACE_INLINE_P (decl)) + return false; + decl = CP_DECL_CONTEXT (decl); + } + return false; } /* Returns true if FN, a CALL_EXPR, is a call to std::forward. */ @@ -9266,6 +9646,10 @@ static bool can_do_nrvo_p (tree retval, tree functype) { + if (functype == error_mark_node) + return false; + if (retval) + STRIP_ANY_LOCATION_WRAPPER (retval); tree result = DECL_RESULT (current_function_decl); return (retval != NULL_TREE && !processing_template_decl @@ -9292,6 +9676,7 @@ 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)) @@ -9309,7 +9694,7 @@ if (!(warn_pessimizing_move || warn_redundant_move)) return; - location_t loc = cp_expr_loc_or_loc (retval, input_location); + location_t loc = cp_expr_loc_or_input_loc (retval); /* C++98 doesn't know move. */ if (cxx_dialect < cxx11) @@ -9324,7 +9709,7 @@ if (!CLASS_TYPE_P (functype)) return; - /* We're looking for *std::move<T&> (&arg). */ + /* We're looking for *std::move<T&> ((T &) &arg). */ if (REFERENCE_REF_P (retval) && TREE_CODE (TREE_OPERAND (retval, 0)) == CALL_EXPR) { @@ -9332,9 +9717,12 @@ if (is_std_move_p (fn)) { tree arg = CALL_EXPR_ARG (fn, 0); - STRIP_NOPS (arg); - if (TREE_CODE (arg) == ADDR_EXPR) - arg = TREE_OPERAND (arg, 0); + if (TREE_CODE (arg) != NOP_EXPR) + return; + arg = TREE_OPERAND (arg, 0); + if (TREE_CODE (arg) != ADDR_EXPR) + return; + arg = TREE_OPERAND (arg, 0); arg = convert_from_reference (arg); /* Warn if we could do copy elision were it not for the move. */ if (can_do_nrvo_p (arg, functype)) @@ -9347,12 +9735,27 @@ } /* Warn if the move is redundant. It is redundant when we would do maybe-rvalue overload resolution even without std::move. */ - else if (treat_lvalue_as_rvalue_p (arg, /*parm_ok*/true)) + else if (warn_redundant_move + && treat_lvalue_as_rvalue_p (arg, /*parm_ok*/true)) { - auto_diagnostic_group d; - if (warning_at (loc, OPT_Wredundant_move, - "redundant move in return statement")) - inform (loc, "remove %<std::move%> call"); + /* Make sure that the overload resolution would actually succeed + if we removed the std::move call. */ + tree t = convert_for_initialization (NULL_TREE, functype, + move (arg), + (LOOKUP_NORMAL + | LOOKUP_ONLYCONVERTING + | LOOKUP_PREFER_RVALUE), + ICR_RETURN, NULL_TREE, 0, + tf_none); + /* If this worked, implicit rvalue would work, so the call to + std::move is redundant. */ + if (t != error_mark_node) + { + auto_diagnostic_group d; + if (warning_at (loc, OPT_Wredundant_move, + "redundant move in return statement")) + inform (loc, "remove %<std::move%> call"); + } } } } @@ -9375,6 +9778,7 @@ the declared type is incomplete. */ tree functype; int fn_returns_value_p; + location_t loc = cp_expr_loc_or_input_loc (retval); *no_warning = false; @@ -9388,7 +9792,7 @@ if (DECL_DESTRUCTOR_P (current_function_decl)) { if (retval) - error ("returning a value from a destructor"); + error_at (loc, "returning a value from a destructor"); return NULL_TREE; } else if (DECL_CONSTRUCTOR_P (current_function_decl)) @@ -9399,7 +9803,7 @@ error ("cannot return from a handler of a function-try-block of a constructor"); else if (retval) /* You can't return a value from a constructor. */ - error ("returning a value from a constructor"); + error_at (loc, "returning a value from a constructor"); return NULL_TREE; } @@ -9415,7 +9819,7 @@ /* If one of the types might be void, we can't tell whether we're returning a value. */ if ((WILDCARD_TYPE_P (TREE_TYPE (DECL_RESULT (current_function_decl))) - && !current_function_auto_return_pattern) + && !FNDECL_USED_AUTO (current_function_decl)) || (retval != NULL_TREE && (TREE_TYPE (retval) == NULL_TREE || WILDCARD_TYPE_P (TREE_TYPE (retval))))) @@ -9425,16 +9829,17 @@ functype = TREE_TYPE (TREE_TYPE (current_function_decl)); /* Deduce auto return type from a return statement. */ - if (current_function_auto_return_pattern) - { + if (FNDECL_USED_AUTO (current_function_decl)) + { + tree pattern = DECL_SAVED_AUTO_RETURN_TYPE (current_function_decl); tree auto_node; tree type; - if (!retval && !is_auto (current_function_auto_return_pattern)) + if (!retval && !is_auto (pattern)) { /* Give a helpful error message. */ error ("return-statement with no value, in function returning %qT", - current_function_auto_return_pattern); + pattern); inform (input_location, "only plain %<auto%> return type can be " "deduced to %<void%>"); type = error_mark_node; @@ -9448,23 +9853,23 @@ { if (!retval) retval = void_node; - auto_node = type_uses_auto (current_function_auto_return_pattern); - type = do_auto_deduction (current_function_auto_return_pattern, - retval, auto_node); + auto_node = type_uses_auto (pattern); + type = do_auto_deduction (pattern, retval, auto_node, + tf_warning_or_error, adc_return_type); } if (type == error_mark_node) /* Leave it. */; - else if (functype == current_function_auto_return_pattern) + else if (functype == pattern) apply_deduced_return_type (current_function_decl, type); else if (!same_type_p (type, functype)) { if (LAMBDA_FUNCTION_P (current_function_decl)) - error ("inconsistent types %qT and %qT deduced for " - "lambda return type", functype, type); + error_at (loc, "inconsistent types %qT and %qT deduced for " + "lambda return type", functype, type); else - error ("inconsistent deduction for auto return type: " - "%qT and then %qT", functype, type); + error_at (loc, "inconsistent deduction for auto return type: " + "%qT and then %qT", functype, type); } functype = type; } @@ -9497,9 +9902,8 @@ type. In that case, we have to evaluate the expression for its side-effects. */ finish_expr_stmt (retval); - else - permerror (input_location, - "return-statement with a value, in function " + else if (retval != error_mark_node) + permerror (loc, "return-statement with a value, in function " "returning %qT", valtype); current_function_returns_null = 1; @@ -9529,7 +9933,7 @@ && ! flag_check_new && retval && null_ptr_cst_p (retval)) warning (0, "%<operator new%> must not return NULL unless it is " - "declared %<throw()%> (or -fcheck-new is in effect)"); + "declared %<throw()%> (or %<-fcheck-new%> is in effect)"); /* Effective C++ rule 15. See also start_function. */ if (warn_ecpp @@ -9555,7 +9959,8 @@ } if (warn) - warning (OPT_Weffc__, "%<operator=%> should return a reference to %<*this%>"); + warning_at (loc, OPT_Weffc__, + "%<operator=%> should return a reference to %<*this%>"); } if (dependent_type_p (functype) @@ -9585,6 +9990,8 @@ 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) @@ -9647,6 +10054,11 @@ } } + /* The call in a (lambda) thunk needs no conversions. */ + if (TREE_CODE (retval) == CALL_EXPR + && CALL_FROM_THUNK_P (retval)) + converted = true; + /* First convert the value to the function's return type, then to the type of return value's location to handle the case that functype is smaller than the valtype. */ @@ -9666,7 +10078,7 @@ retval = build2 (COMPOUND_EXPR, TREE_TYPE (retval), retval, TREE_OPERAND (retval, 0)); else if (!processing_template_decl - && maybe_warn_about_returning_address_of_local (retval) + && maybe_warn_about_returning_address_of_local (retval, loc) && INDIRECT_TYPE_P (valtype)) retval = build2 (COMPOUND_EXPR, TREE_TYPE (retval), retval, build_zero_cst (TREE_TYPE (retval))); @@ -9679,6 +10091,9 @@ if (retval && retval != result) retval = build2 (INIT_EXPR, TREE_TYPE (result), result, retval); + if (tree set = maybe_set_retval_sentinel ()) + retval = build2 (COMPOUND_EXPR, void_type_node, retval, set); + return retval; } @@ -9691,7 +10106,7 @@ If CONSTP is positive, then all outer pointers have been const-qualified. */ -static int +static bool comp_ptr_ttypes_real (tree to, tree from, int constp) { bool to_more_cv_qualified = false; @@ -9700,24 +10115,25 @@ for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from)) { if (TREE_CODE (to) != TREE_CODE (from)) - return 0; + return false; if (TREE_CODE (from) == OFFSET_TYPE && !same_type_p (TYPE_OFFSET_BASETYPE (from), TYPE_OFFSET_BASETYPE (to))) - return 0; - - /* Const and volatile mean something different for function types, - so the usual checks are not appropriate. */ - if (TREE_CODE (to) != FUNCTION_TYPE && TREE_CODE (to) != METHOD_TYPE) + return false; + + /* Const and volatile mean something different for function and + array types, so the usual checks are not appropriate. We'll + check the array type elements in further iterations. */ + if (!FUNC_OR_METHOD_TYPE_P (to) && TREE_CODE (to) != ARRAY_TYPE) { if (!at_least_as_qualified_p (to, from)) - return 0; + return false; if (!at_least_as_qualified_p (from, to)) { if (constp == 0) - return 0; + return false; to_more_cv_qualified = true; } @@ -9728,7 +10144,17 @@ if (VECTOR_TYPE_P (to)) is_opaque_pointer = vector_targets_convertible_p (to, from); - if (!TYPE_PTR_P (to) && !TYPE_PTRDATAMEM_P (to)) + /* P0388R4 allows a conversion from int[N] to int[] but not the + other way round. When both arrays have bounds but they do + not match, then no conversion is possible. */ + if (TREE_CODE (to) == ARRAY_TYPE + && !comp_array_types (to, from, bounds_first, /*strict=*/false)) + return false; + + if (!TYPE_PTR_P (to) + && !TYPE_PTRDATAMEM_P (to) + /* CWG 330 says we need to look through arrays. */ + && TREE_CODE (to) != ARRAY_TYPE) return ((constp >= 0 || to_more_cv_qualified) && (is_opaque_pointer || same_type_ignoring_top_level_qualifiers_p (to, from))); @@ -9831,10 +10257,10 @@ /* Return true if TO and FROM (both of which are POINTER_TYPEs or pointer-to-member types) are the same, ignoring cv-qualification at - all levels. */ + all levels. CB says how we should behave when comparing array bounds. */ bool -comp_ptr_ttypes_const (tree to, tree from) +comp_ptr_ttypes_const (tree to, tree from, compare_bounds_t cb) { bool is_opaque_pointer = false; @@ -9851,7 +10277,14 @@ if (VECTOR_TYPE_P (to)) is_opaque_pointer = vector_targets_convertible_p (to, from); - if (!TYPE_PTR_P (to)) + if (TREE_CODE (to) == ARRAY_TYPE + /* Ignore cv-qualification, but if we see e.g. int[3] and int[4], + we must fail. */ + && !comp_array_types (to, from, cb, /*strict=*/false)) + return false; + + /* CWG 330 says we need to look through arrays. */ + if (!TYPE_PTR_P (to) && TREE_CODE (to) != ARRAY_TYPE) return (is_opaque_pointer || same_type_ignoring_top_level_qualifiers_p (to, from)); } @@ -9885,8 +10318,7 @@ cp_ref_qualifier type_memfn_rqual (const_tree type) { - gcc_assert (TREE_CODE (type) == FUNCTION_TYPE - || TREE_CODE (type) == METHOD_TYPE); + gcc_assert (FUNC_OR_METHOD_TYPE_P (type)); if (!FUNCTION_REF_QUALIFIED (type)) return REF_QUAL_NONE; @@ -10127,7 +10559,7 @@ if (kind == clk_none) { if (complain & tf_error) - lvalue_error (input_location, use); + lvalue_error (cp_expr_loc_or_input_loc (ref), use); return 0; } else if (kind & (clk_rvalueref|clk_class)) @@ -10135,7 +10567,8 @@ if (!(complain & tf_error)) return 0; /* Make this a permerror because we used to accept it. */ - permerror (input_location, "using rvalue as lvalue"); + permerror (cp_expr_loc_or_input_loc (ref), + "using rvalue as lvalue"); } return 1; } @@ -10206,6 +10639,7 @@ t = TYPE_MAIN_VARIANT (t); if ((maybe_raw_p = same_type_p (t, char_type_node)) || same_type_p (t, wchar_type_node) + || same_type_p (t, char8_type_node) || same_type_p (t, char16_type_node) || same_type_p (t, char32_type_node)) { @@ -10238,6 +10672,8 @@ max_arity = 1; else if (same_type_p (t, wchar_type_node)) max_arity = 1; + else if (same_type_p (t, char8_type_node)) + max_arity = 1; else if (same_type_p (t, char16_type_node)) max_arity = 1; else if (same_type_p (t, char32_type_node))