Ping. On Thu, May 05, 2016 at 04:22:15PM +0200, Marek Polacek wrote: > On Wed, May 04, 2016 at 11:52:39AM -0400, Jason Merrill wrote: > > On Wed, May 4, 2016 at 9:00 AM, Marek Polacek <pola...@redhat.com> wrote: > > > On Tue, May 03, 2016 at 08:05:47PM -0400, Jason Merrill wrote: > > >> Looks good. > > >> > > >> But I don't see a C++ testcase; can the test go into c-c++-common? > > > > > > Sadly, no. As of now, the patch doesn't improve things for C++ (?). > > > Seems > > > we'd need to pass better locations down to pointer_int_sum / > > > size_in_bytes. > > > It cascades :(. > > > > Sure. But can you fix that, too, while you're thinking about it? > > Passing the location to cp_pointer_int_sum and pointer_diff seems > > pretty simple. > > That's true, that was pretty simple, actually. And while at it, I also > added a location parameter to cp_build_modify_expr. With that, we generate > better diagnostics even for C++, so I could move the test to c-c++-common. > And I also added another test, this time with -Wpointer-arith diagnostics, > which this patch improves as well. > > Bootstrapped/regtested on x86_64-linux, ok for trunk? > > 2016-05-05 Marek Polacek <pola...@redhat.com> > > PR c/70756 > * c-common.c (pointer_int_sum): Call size_in_bytes_loc instead of > size_in_bytes and pass LOC to it. > > * c-decl.c (build_compound_literal): Pass LOC down to > c_incomplete_type_error. > * c-tree.h (require_complete_type): Adjust declaration. > (c_incomplete_type_error): Likewise. > * c-typeck.c (require_complete_type): Add location parameter, pass it > down to c_incomplete_type_error. > (c_incomplete_type_error): Add location parameter, pass it down to > error_at. > (build_component_ref): Pass location down to c_incomplete_type_error. > (default_conversion): Pass location down to require_complete_type. > (build_array_ref): Likewise. > (build_function_call_vec): Likewise. > (convert_arguments): Likewise. > (build_unary_op): Likewise. > (build_c_cast): Likewise. > (build_modify_expr): Likewise. > (convert_for_assignment): Likewise. > (c_finish_omp_clauses): Likewise. > > * call.c (build_new_op_1): Pass LOC to cp_build_modify_expr. > * cp-tree.h (cp_build_modify_expr): Update declaration. > (cxx_incomplete_type_error, cxx_incomplete_type_diagnostic): New inline > overloads. > * cp-ubsan.c (cp_ubsan_dfs_initialize_vtbl_ptrs): Pass INPUT_LOCATION to > cp_build_modify_expr. > * decl2.c (set_guard): Likewise. > (handle_tls_init): Likewise. > * init.c (perform_member_init): Likewise. > (expand_virtual_init): Likewise. > (build_new_1): Likewise. > (build_vec_delete_1): Likewise. > (get_temp_regvar): Likewise. > (build_vec_init): Likewise. > * method.c (do_build_copy_assign): Likewise. > (assignable_expr): Likewise. > * semantics.c (finish_omp_for): Likewise. > * typeck.c (cp_build_binary_op): Pass LOCATION to pointer_diff and > cp_pointer_int_sum. > (cp_pointer_int_sum): Add location parameter. Pass it down to > pointer_int_sum. > (pointer_diff): Add location parameter. Use it. > (build_modify_expr): Pass location down to cp_build_modify_expr. > (cp_build_modify_expr): Add location parameter. Use it. > (build_x_modify_expr): Pass location down to cp_build_modify_expr. > * typeck2.c (cxx_incomplete_type_diagnostic, > cxx_incomplete_type_error): Add location parameter. > > * langhooks-def.h (lhd_incomplete_type_error): Adjust declaration. > * langhooks.c (lhd_incomplete_type_error): Add location parameter. > * langhooks.h (incomplete_type_error): Likewise. > * tree.c (size_in_bytes_loc): Renamed from size_in_bytes. Add location > parameter, pass it down to incomplete_type_error. > * tree.h (size_in_bytes): New inline overload. > (size_in_bytes_loc): Renamed from size_in_bytes. > > * c-c++-common/pr70756-2.c: New test. > * c-c++-common/pr70756.c: New test. > > diff --git gcc/c-family/c-common.c gcc/c-family/c-common.c > index 63a18c8..150bdb2 100644 > --- gcc/c-family/c-common.c > +++ gcc/c-family/c-common.c > @@ -4269,7 +4269,7 @@ pointer_int_sum (location_t loc, enum tree_code > resultcode, > size_exp = integer_one_node; > } > else > - size_exp = size_in_bytes (TREE_TYPE (result_type)); > + size_exp = size_in_bytes_loc (loc, TREE_TYPE (result_type)); > > /* We are manipulating pointer values, so we don't need to warn > about relying on undefined signed overflow. We disable the > diff --git gcc/c/c-decl.c gcc/c/c-decl.c > index 7094efc..48fa65c 100644 > --- gcc/c/c-decl.c > +++ gcc/c/c-decl.c > @@ -5112,7 +5112,7 @@ build_compound_literal (location_t loc, tree type, tree > init, bool non_const) > > if (type == error_mark_node || !COMPLETE_TYPE_P (type)) > { > - c_incomplete_type_error (NULL_TREE, type); > + c_incomplete_type_error (loc, NULL_TREE, type); > return error_mark_node; > } > > diff --git gcc/c/c-tree.h gcc/c/c-tree.h > index 07d0f65..1201f42 100644 > --- gcc/c/c-tree.h > +++ gcc/c/c-tree.h > @@ -588,13 +588,13 @@ extern tree c_last_sizeof_arg; > extern struct c_switch *c_switch_stack; > > extern tree c_objc_common_truthvalue_conversion (location_t, tree); > -extern tree require_complete_type (tree); > +extern tree require_complete_type (location_t, tree); > extern int same_translation_unit_p (const_tree, const_tree); > extern int comptypes (tree, tree); > extern int comptypes_check_different_types (tree, tree, bool *); > extern bool c_vla_type_p (const_tree); > extern bool c_mark_addressable (tree); > -extern void c_incomplete_type_error (const_tree, const_tree); > +extern void c_incomplete_type_error (location_t, const_tree, const_tree); > extern tree c_type_promotes_to (tree); > extern struct c_expr default_function_array_conversion (location_t, > struct c_expr); > diff --git gcc/c/c-typeck.c gcc/c/c-typeck.c > index 861aa12..b037f46 100644 > --- gcc/c/c-typeck.c > +++ gcc/c/c-typeck.c > @@ -183,11 +183,12 @@ struct tagged_tu_seen_cache { > static const struct tagged_tu_seen_cache * tagged_tu_seen_base; > static void free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache > *); > > -/* Do `exp = require_complete_type (exp);' to make sure exp > - does not have an incomplete type. (That includes void types.) */ > +/* Do `exp = require_complete_type (loc, exp);' to make sure exp > + does not have an incomplete type. (That includes void types.) > + LOC is the location of the use. */ > > tree > -require_complete_type (tree value) > +require_complete_type (location_t loc, tree value) > { > tree type = TREE_TYPE (value); > > @@ -198,23 +199,24 @@ require_complete_type (tree value) > if (COMPLETE_TYPE_P (type)) > return value; > > - c_incomplete_type_error (value, type); > + c_incomplete_type_error (loc, value, type); > return error_mark_node; > } > > /* Print an error message for invalid use of an incomplete type. > VALUE is the expression that was used (or 0 if that isn't known) > - and TYPE is the type that was invalid. */ > + and TYPE is the type that was invalid. LOC is the location for > + the error. */ > > void > -c_incomplete_type_error (const_tree value, const_tree type) > +c_incomplete_type_error (location_t loc, const_tree value, const_tree type) > { > /* Avoid duplicate error message. */ > if (TREE_CODE (type) == ERROR_MARK) > return; > > if (value != 0 && (VAR_P (value) || TREE_CODE (value) == PARM_DECL)) > - error ("%qD has an incomplete type %qT", value, type); > + error_at (loc, "%qD has an incomplete type %qT", value, type); > else > { > retry: > @@ -228,7 +230,7 @@ c_incomplete_type_error (const_tree value, const_tree > type) > break; > > case VOID_TYPE: > - error ("invalid use of void expression"); > + error_at (loc, "invalid use of void expression"); > return; > > case ARRAY_TYPE: > @@ -236,13 +238,13 @@ c_incomplete_type_error (const_tree value, const_tree > type) > { > if (TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL) > { > - error ("invalid use of flexible array member"); > + error_at (loc, "invalid use of flexible array member"); > return; > } > type = TREE_TYPE (type); > goto retry; > } > - error ("invalid use of array with unspecified bounds"); > + error_at (loc, "invalid use of array with unspecified bounds"); > return; > > default: > @@ -250,10 +252,10 @@ c_incomplete_type_error (const_tree value, const_tree > type) > } > > if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) > - error ("invalid use of undefined type %qT", type); > + error_at (loc, "invalid use of undefined type %qT", type); > else > /* If this type has a typedef-name, the TYPE_NAME is a TYPE_DECL. */ > - error ("invalid use of incomplete typedef %qT", type); > + error_at (loc, "invalid use of incomplete typedef %qT", type); > } > } > > @@ -2117,7 +2119,7 @@ default_conversion (tree exp) > return error_mark_node; > } > > - exp = require_complete_type (exp); > + exp = require_complete_type (EXPR_LOC_OR_LOC (exp, input_location), exp); > if (exp == error_mark_node) > return error_mark_node; > > @@ -2334,7 +2336,7 @@ build_component_ref (location_t loc, tree datum, tree > component) > { > if (!COMPLETE_TYPE_P (type)) > { > - c_incomplete_type_error (NULL_TREE, type); > + c_incomplete_type_error (loc, NULL_TREE, type); > return error_mark_node; > } > > @@ -2642,7 +2644,7 @@ build_array_ref (location_t loc, tree array, tree index) > in an inline function. > Hope it doesn't break something else. */ > | TREE_THIS_VOLATILE (array)); > - ret = require_complete_type (rval); > + ret = require_complete_type (loc, rval); > protected_set_expr_location (ret, loc); > if (non_lvalue) > ret = non_lvalue_loc (loc, ret); > @@ -3088,7 +3090,7 @@ build_function_call_vec (location_t loc, > vec<location_t> arg_loc, > "function with qualified void return type called"); > return result; > } > - return require_complete_type (result); > + return require_complete_type (loc, result); > } > > /* Like build_function_call_vec, but call also resolve_overloaded_builtin. > */ > @@ -3239,7 +3241,7 @@ convert_arguments (location_t loc, vec<location_t> > arg_loc, tree typelist, > val = c_fully_fold (val, false, NULL); > STRIP_TYPE_NOPS (val); > > - val = require_complete_type (val); > + val = require_complete_type (ploc, val); > > if (type != 0) > { > @@ -4047,7 +4049,7 @@ build_unary_op (location_t location, > arg = remove_c_maybe_const_expr (arg); > > if (code != ADDR_EXPR) > - arg = require_complete_type (arg); > + arg = require_complete_type (location, arg); > > typecode = TREE_CODE (TREE_TYPE (arg)); > if (typecode == ERROR_MARK) > @@ -5268,7 +5270,7 @@ build_c_cast (location_t loc, tree type, tree expr) > > if (!VOID_TYPE_P (type)) > { > - value = require_complete_type (value); > + value = require_complete_type (loc, value); > if (value == error_mark_node) > return error_mark_node; > } > @@ -5538,7 +5540,7 @@ build_modify_expr (location_t location, tree lhs, tree > lhs_origtype, > bool is_atomic_op; > > /* Types that aren't fully specified cannot be used in assignments. */ > - lhs = require_complete_type (lhs); > + lhs = require_complete_type (location, lhs); > > /* Avoid duplicate error messages from operands that had errors. */ > if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK) > @@ -6133,7 +6135,7 @@ convert_for_assignment (location_t location, location_t > expr_loc, tree type, > error_at (location, "void value not ignored as it ought to be"); > return error_mark_node; > } > - rhs = require_complete_type (rhs); > + rhs = require_complete_type (location, rhs); > if (rhs == error_mark_node) > return error_mark_node; > > @@ -12550,7 +12552,7 @@ c_finish_omp_clauses (tree clauses, enum > c_omp_region_type ort) > > t = OMP_CLAUSE_DECL (c); > } > - t = require_complete_type (t); > + t = require_complete_type (OMP_CLAUSE_LOCATION (c), t); > if (t == error_mark_node) > { > remove = true; > @@ -13361,7 +13363,7 @@ c_finish_omp_clauses (tree clauses, enum > c_omp_region_type ort) > > if (need_complete) > { > - t = require_complete_type (t); > + t = require_complete_type (OMP_CLAUSE_LOCATION (c), t); > if (t == error_mark_node) > remove = true; > } > diff --git gcc/cp/call.c gcc/cp/call.c > index e9ebdbc..a49bbb5 100644 > --- gcc/cp/call.c > +++ gcc/cp/call.c > @@ -5757,7 +5757,7 @@ build_new_op_1 (location_t loc, enum tree_code code, > int flags, tree arg1, > switch (code) > { > case MODIFY_EXPR: > - return cp_build_modify_expr (arg1, code2, arg2, complain); > + return cp_build_modify_expr (loc, arg1, code2, arg2, complain); > > case INDIRECT_REF: > return cp_build_indirect_ref (arg1, RO_UNARY_STAR, complain); > diff --git gcc/cp/cp-tree.h gcc/cp/cp-tree.h > index 6665355..556c256 100644 > --- gcc/cp/cp-tree.h > +++ gcc/cp/cp-tree.h > @@ -6666,7 +6666,8 @@ extern tree cp_build_c_cast (tree, > tree, tsubst_flags_t); > extern cp_expr build_x_modify_expr (location_t, tree, > enum tree_code, tree, > tsubst_flags_t); > -extern tree cp_build_modify_expr (tree, enum tree_code, tree, > +extern tree cp_build_modify_expr (location_t, tree, > + enum tree_code, tree, > tsubst_flags_t); > extern tree convert_for_initialization (tree, tree, tree, int, > impl_conv_rhs, tree, int, > @@ -6726,11 +6727,24 @@ extern tree finish_binary_fold_expr (tree, > tree, int); > > /* in typeck2.c */ > extern void require_complete_eh_spec_types (tree, tree); > -extern void cxx_incomplete_type_diagnostic (const_tree, const_tree, > diagnostic_t); > -#undef cxx_incomplete_type_error > -extern void cxx_incomplete_type_error (const_tree, > const_tree); > -#define cxx_incomplete_type_error(V,T) \ > - (cxx_incomplete_type_diagnostic ((V), (T), DK_ERROR)) > +extern void cxx_incomplete_type_diagnostic (location_t, const_tree, > + const_tree, diagnostic_t); > +inline void > +cxx_incomplete_type_diagnostic (const_tree value, const_tree type, > + diagnostic_t diag_kind) > +{ > + cxx_incomplete_type_diagnostic (EXPR_LOC_OR_LOC (value, input_location), > + value, type, diag_kind); > +} > + > +extern void cxx_incomplete_type_error (location_t, const_tree, > + const_tree); > +inline void > +cxx_incomplete_type_error (const_tree value, const_tree type) > +{ > + cxx_incomplete_type_diagnostic (value, type, DK_ERROR); > +} > + > extern void cxx_incomplete_type_inform (const_tree); > extern tree error_not_base_type (tree, tree); > extern tree binfo_or_else (tree, tree); > diff --git gcc/cp/cp-ubsan.c gcc/cp/cp-ubsan.c > index be24a5c..9c8f6e6 100644 > --- gcc/cp/cp-ubsan.c > +++ gcc/cp/cp-ubsan.c > @@ -299,8 +299,8 @@ cp_ubsan_dfs_initialize_vtbl_ptrs (tree binfo, void *data) > > /* Assign NULL to the vptr. */ > tree vtbl = build_zero_cst (TREE_TYPE (vtbl_ptr)); > - tree stmt = cp_build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl, > - tf_warning_or_error); > + tree stmt = cp_build_modify_expr (input_location, vtbl_ptr, NOP_EXPR, > + vtbl, tf_warning_or_error); > if (vptr_via_virtual_p (binfo)) > /* If this vptr comes from a virtual base of the complete object, only > clear it if we're in charge of virtual bases. */ > diff --git gcc/cp/decl2.c gcc/cp/decl2.c > index 0ea326d..22f9ede 100644 > --- gcc/cp/decl2.c > +++ gcc/cp/decl2.c > @@ -3161,7 +3161,7 @@ set_guard (tree guard) > guard_init = integer_one_node; > if (!same_type_p (TREE_TYPE (guard_init), TREE_TYPE (guard))) > guard_init = fold_convert (TREE_TYPE (guard), guard_init); > - return cp_build_modify_expr (guard, NOP_EXPR, guard_init, > + return cp_build_modify_expr (input_location, guard, NOP_EXPR, guard_init, > tf_warning_or_error); > } > > @@ -4346,7 +4346,8 @@ handle_tls_init (void) > tree cond = cp_build_unary_op (TRUTH_NOT_EXPR, guard, false, > tf_warning_or_error); > finish_if_stmt_cond (cond, if_stmt); > - finish_expr_stmt (cp_build_modify_expr (guard, NOP_EXPR, boolean_true_node, > + finish_expr_stmt (cp_build_modify_expr (loc, guard, NOP_EXPR, > + boolean_true_node, > tf_warning_or_error)); > for (; vars; vars = TREE_CHAIN (vars)) > { > diff --git gcc/cp/init.c gcc/cp/init.c > index 681ca12..8e7541f 100644 > --- gcc/cp/init.c > +++ gcc/cp/init.c > @@ -798,7 +798,8 @@ perform_member_init (tree member, tree init) > tf_warning_or_error); > > if (init) > - finish_expr_stmt (cp_build_modify_expr (decl, INIT_EXPR, init, > + finish_expr_stmt (cp_build_modify_expr (input_location, decl, > + INIT_EXPR, init, > tf_warning_or_error)); > } > > @@ -1254,8 +1255,8 @@ expand_virtual_init (tree binfo, tree decl) > > /* Assign the vtable to the vptr. */ > vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0, tf_warning_or_error); > - finish_expr_stmt (cp_build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl, > - tf_warning_or_error)); > + finish_expr_stmt (cp_build_modify_expr (input_location, vtbl_ptr, NOP_EXPR, > + vtbl, tf_warning_or_error)); > } > > /* If an exception is thrown in a constructor, those base classes already > @@ -3208,8 +3209,8 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, > tree nelts, > > ie = build_x_compound_expr_from_vec (*init, "new initializer", > complain); > - init_expr = cp_build_modify_expr (init_expr, INIT_EXPR, ie, > - complain); > + init_expr = cp_build_modify_expr (input_location, init_expr, > + INIT_EXPR, ie, complain); > } > stable = stabilize_init (init_expr, &init_preeval_expr); > } > @@ -3596,7 +3597,7 @@ build_vec_delete_1 (tree base, tree maxindex, tree type, > > tbase = create_temporary_var (ptype); > tbase_init > - = cp_build_modify_expr (tbase, NOP_EXPR, > + = cp_build_modify_expr (input_location, tbase, NOP_EXPR, > fold_build_pointer_plus_loc (input_location, > fold_convert (ptype, > base), > @@ -3613,7 +3614,7 @@ build_vec_delete_1 (tree base, tree maxindex, tree type, > fold_convert (ptype, base))); > tmp = fold_build1_loc (input_location, NEGATE_EXPR, sizetype, size_exp); > tmp = fold_build_pointer_plus (tbase, tmp); > - tmp = cp_build_modify_expr (tbase, NOP_EXPR, tmp, complain); > + tmp = cp_build_modify_expr (input_location, tbase, NOP_EXPR, tmp, > complain); > if (tmp == error_mark_node) > return error_mark_node; > body = build_compound_expr (input_location, body, tmp); > @@ -3735,8 +3736,8 @@ get_temp_regvar (tree type, tree init) > decl = create_temporary_var (type); > add_decl_expr (decl); > > - finish_expr_stmt (cp_build_modify_expr (decl, INIT_EXPR, init, > - tf_warning_or_error)); > + finish_expr_stmt (cp_build_modify_expr (input_location, decl, INIT_EXPR, > + init, tf_warning_or_error)); > > return decl; > } > @@ -4000,8 +4001,8 @@ build_vec_init (tree base, tree maxindex, tree init, > else if (MAYBE_CLASS_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE) > one_init = build_aggr_init (baseref, elt, 0, complain); > else > - one_init = cp_build_modify_expr (baseref, NOP_EXPR, > - elt, complain); > + one_init = cp_build_modify_expr (input_location, baseref, > + NOP_EXPR, elt, complain); > if (one_init == error_mark_node) > errors = true; > if (try_const) > @@ -4128,12 +4129,12 @@ build_vec_init (tree base, tree maxindex, tree init, > from = NULL_TREE; > > if (from_array == 2) > - elt_init = cp_build_modify_expr (to, NOP_EXPR, from, > - complain); > + elt_init = cp_build_modify_expr (input_location, to, NOP_EXPR, > + from, complain); > else if (type_build_ctor_call (type)) > elt_init = build_aggr_init (to, from, 0, complain); > else if (from) > - elt_init = cp_build_modify_expr (to, NOP_EXPR, from, > + elt_init = cp_build_modify_expr (input_location, to, NOP_EXPR, from, > complain); > else > gcc_unreachable (); > diff --git gcc/cp/method.c gcc/cp/method.c > index 0e501d9..310e7eb 100644 > --- gcc/cp/method.c > +++ gcc/cp/method.c > @@ -741,7 +741,7 @@ do_build_copy_assign (tree fndecl) > init = move (init); > > if (DECL_NAME (field)) > - init = cp_build_modify_expr (comp, NOP_EXPR, init, > + init = cp_build_modify_expr (input_location, comp, NOP_EXPR, init, > tf_warning_or_error); > else > init = build2 (MODIFY_EXPR, TREE_TYPE (comp), comp, init); > @@ -1023,7 +1023,7 @@ assignable_expr (tree to, tree from) > ++cp_unevaluated_operand; > to = build_stub_object (to); > from = build_stub_object (from); > - tree r = cp_build_modify_expr (to, NOP_EXPR, from, tf_none); > + tree r = cp_build_modify_expr (input_location, to, NOP_EXPR, from, > tf_none); > --cp_unevaluated_operand; > return r; > } > diff --git gcc/cp/semantics.c gcc/cp/semantics.c > index fed7e88..817ef99 100644 > --- gcc/cp/semantics.c > +++ gcc/cp/semantics.c > @@ -8073,7 +8073,7 @@ finish_omp_for (location_t locus, enum tree_code code, > tree declv, > { > if (orig_incr) > TREE_VEC_ELT (orig_incr, i) = incr; > - incr = cp_build_modify_expr (TREE_OPERAND (incr, 0), > + incr = cp_build_modify_expr (elocus, TREE_OPERAND (incr, 0), > TREE_CODE (TREE_OPERAND (incr, 1)), > TREE_OPERAND (incr, 2), > tf_warning_or_error); > @@ -8107,7 +8107,8 @@ finish_omp_for (location_t locus, enum tree_code code, > tree declv, > if (!processing_template_decl) > { > init = fold_build_cleanup_point_expr (TREE_TYPE (init), init); > - init = cp_build_modify_expr (decl, NOP_EXPR, init, > tf_warning_or_error); > + init = cp_build_modify_expr (elocus, decl, NOP_EXPR, init, > + tf_warning_or_error); > } > else > init = build2 (MODIFY_EXPR, void_type_node, decl, init); > diff --git gcc/cp/typeck.c gcc/cp/typeck.c > index 95c777d..0d8a980 100644 > --- gcc/cp/typeck.c > +++ gcc/cp/typeck.c > @@ -43,13 +43,14 @@ static tree pfn_from_ptrmemfunc (tree); > static tree delta_from_ptrmemfunc (tree); > static tree convert_for_assignment (tree, tree, impl_conv_rhs, tree, int, > tsubst_flags_t, int); > -static tree cp_pointer_int_sum (enum tree_code, tree, tree, tsubst_flags_t); > +static tree cp_pointer_int_sum (location_t, enum tree_code, tree, tree, > + 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_except_types (tree, tree, bool); > static bool comp_array_types (const_tree, const_tree, bool); > -static tree pointer_diff (tree, tree, tree, tsubst_flags_t); > +static tree pointer_diff (location_t, tree, tree, tree, tsubst_flags_t); > 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); > @@ -4236,8 +4237,8 @@ cp_build_binary_op (location_t location, > if (code0 == POINTER_TYPE && code1 == POINTER_TYPE > && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (type0), > TREE_TYPE (type1))) > - return pointer_diff (op0, op1, common_pointer_type (type0, type1), > - complain); > + return pointer_diff (location, op0, op1, > + common_pointer_type (type0, type1), complain); > /* In all other cases except pointer - int, the usual arithmetic > rules apply. */ > else if (!(code0 == POINTER_TYPE && code1 == INTEGER_TYPE)) > @@ -4260,8 +4261,8 @@ cp_build_binary_op (location_t location, > result_type = TREE_TYPE (ptr_operand); > break; > } > - return cp_pointer_int_sum (code, > - ptr_operand, > + return cp_pointer_int_sum (location, code, > + ptr_operand, > int_operand, > complain); > } > @@ -5226,8 +5227,8 @@ build_x_vec_perm_expr (location_t loc, > of pointer PTROP and integer INTOP. */ > > static tree > -cp_pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop, > - tsubst_flags_t complain) > +cp_pointer_int_sum (location_t loc, enum tree_code resultcode, tree ptrop, > + tree intop, tsubst_flags_t complain) > { > tree res_type = TREE_TYPE (ptrop); > > @@ -5238,7 +5239,7 @@ cp_pointer_int_sum (enum tree_code resultcode, tree > ptrop, tree intop, > pointer_int_sum() anyway. */ > complete_type (TREE_TYPE (res_type)); > > - return pointer_int_sum (input_location, resultcode, ptrop, > + return pointer_int_sum (loc, resultcode, ptrop, > intop, complain & tf_warning_or_error); > } > > @@ -5246,7 +5247,8 @@ cp_pointer_int_sum (enum tree_code resultcode, tree > ptrop, tree intop, > The resulting tree has type int. */ > > static tree > -pointer_diff (tree op0, tree op1, tree ptrtype, tsubst_flags_t complain) > +pointer_diff (location_t loc, tree op0, tree op1, tree ptrtype, > + tsubst_flags_t complain) > { > tree result; > tree restype = ptrdiff_type_node; > @@ -5258,7 +5260,7 @@ pointer_diff (tree op0, tree op1, tree ptrtype, > tsubst_flags_t complain) > if (VOID_TYPE_P (target_type)) > { > if (complain & tf_error) > - permerror (input_location, "ISO C++ forbids using pointer of " > + permerror (loc, "ISO C++ forbids using pointer of " > "type %<void *%> in subtraction"); > else > return error_mark_node; > @@ -5266,7 +5268,7 @@ pointer_diff (tree op0, tree op1, tree ptrtype, > tsubst_flags_t complain) > if (TREE_CODE (target_type) == FUNCTION_TYPE) > { > if (complain & tf_error) > - permerror (input_location, "ISO C++ forbids using pointer to " > + permerror (loc, "ISO C++ forbids using pointer to " > "a function in subtraction"); > else > return error_mark_node; > @@ -5274,7 +5276,7 @@ pointer_diff (tree op0, tree op1, tree ptrtype, > tsubst_flags_t complain) > if (TREE_CODE (target_type) == METHOD_TYPE) > { > if (complain & tf_error) > - permerror (input_location, "ISO C++ forbids using pointer to " > + permerror (loc, "ISO C++ forbids using pointer to " > "a method in subtraction"); > else > return error_mark_node; > @@ -5283,7 +5285,7 @@ pointer_diff (tree op0, tree op1, tree ptrtype, > tsubst_flags_t complain) > /* First do the subtraction as integers; > then drop through to build the divide operator. */ > > - op0 = cp_build_binary_op (input_location, > + op0 = cp_build_binary_op (loc, > MINUS_EXPR, > cp_convert (restype, op0, complain), > cp_convert (restype, op1, complain), > @@ -5293,8 +5295,8 @@ pointer_diff (tree op0, tree op1, tree ptrtype, > tsubst_flags_t complain) > if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (op1)))) > { > if (complain & tf_error) > - error ("invalid use of a pointer to an incomplete type in " > - "pointer arithmetic"); > + error_at (loc, "invalid use of a pointer to an incomplete type in " > + "pointer arithmetic"); > else > return error_mark_node; > } > @@ -5302,19 +5304,19 @@ pointer_diff (tree op0, tree op1, tree ptrtype, > tsubst_flags_t complain) > if (pointer_to_zero_sized_aggr_p (TREE_TYPE (op1))) > { > if (complain & tf_error) > - error ("arithmetic on pointer to an empty aggregate"); > + error_at (loc, "arithmetic on pointer to an empty aggregate"); > else > return error_mark_node; > } > > op1 = (TYPE_PTROB_P (ptrtype) > - ? size_in_bytes (target_type) > + ? size_in_bytes_loc (loc, target_type) > : integer_one_node); > > /* Do the division. */ > > - result = build2 (EXACT_DIV_EXPR, restype, op0, > - cp_convert (restype, op1, complain)); > + result = build2_loc (loc, EXACT_DIV_EXPR, restype, op0, > + cp_convert (restype, op1, complain)); > return result; > } > > @@ -7470,13 +7472,14 @@ cp_build_c_cast (tree type, tree expr, tsubst_flags_t > complain) > > /* For use from the C common bits. */ > tree > -build_modify_expr (location_t /*location*/, > +build_modify_expr (location_t location, > tree lhs, tree /*lhs_origtype*/, > enum tree_code modifycode, > location_t /*rhs_location*/, tree rhs, > tree /*rhs_origtype*/) > { > - return cp_build_modify_expr (lhs, modifycode, rhs, tf_warning_or_error); > + return cp_build_modify_expr (location, lhs, modifycode, rhs, > + tf_warning_or_error); > } > > /* Build an assignment expression of lvalue LHS from value RHS. > @@ -7487,8 +7490,8 @@ build_modify_expr (location_t /*location*/, > C++: If MODIFYCODE is INIT_EXPR, then leave references unbashed. */ > > tree > -cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs, > - tsubst_flags_t complain) > +cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode, > + tree rhs, tsubst_flags_t complain) > { > tree result; > tree newrhs = rhs; > @@ -7510,7 +7513,7 @@ cp_build_modify_expr (tree lhs, enum tree_code > modifycode, tree rhs, > lhs = build2 (TREE_CODE (lhs), TREE_TYPE (lhs), > cp_stabilize_reference (TREE_OPERAND (lhs, 0)), > TREE_OPERAND (lhs, 1)); > - newrhs = cp_build_modify_expr (TREE_OPERAND (lhs, 0), > + newrhs = cp_build_modify_expr (loc, TREE_OPERAND (lhs, 0), > modifycode, rhs, complain); > if (newrhs == error_mark_node) > return error_mark_node; > @@ -7518,7 +7521,7 @@ cp_build_modify_expr (tree lhs, enum tree_code > modifycode, tree rhs, > > /* Handle (a, b) used as an "lvalue". */ > case COMPOUND_EXPR: > - newrhs = cp_build_modify_expr (TREE_OPERAND (lhs, 1), > + newrhs = cp_build_modify_expr (loc, TREE_OPERAND (lhs, 1), > modifycode, rhs, complain); > if (newrhs == error_mark_node) > return error_mark_node; > @@ -7530,8 +7533,8 @@ cp_build_modify_expr (tree lhs, enum tree_code > modifycode, tree rhs, > lhs = build2 (TREE_CODE (lhs), TREE_TYPE (lhs), > cp_stabilize_reference (TREE_OPERAND (lhs, 0)), > TREE_OPERAND (lhs, 1)); > - newrhs = cp_build_modify_expr (TREE_OPERAND (lhs, 0), modifycode, rhs, > - complain); > + newrhs = cp_build_modify_expr (loc, TREE_OPERAND (lhs, 0), modifycode, > + rhs, complain); > if (newrhs == error_mark_node) > return error_mark_node; > return build2 (COMPOUND_EXPR, lhstype, lhs, newrhs); > @@ -7580,9 +7583,9 @@ cp_build_modify_expr (tree lhs, enum tree_code > modifycode, tree rhs, > > cond = build_conditional_expr > (input_location, TREE_OPERAND (lhs, 0), > - cp_build_modify_expr (TREE_OPERAND (lhs, 1), > + cp_build_modify_expr (loc, TREE_OPERAND (lhs, 1), > modifycode, rhs, complain), > - cp_build_modify_expr (TREE_OPERAND (lhs, 2), > + cp_build_modify_expr (loc, TREE_OPERAND (lhs, 2), > modifycode, rhs, complain), > complain); > > @@ -7680,9 +7683,7 @@ cp_build_modify_expr (tree lhs, enum tree_code > modifycode, tree rhs, > lhs = cp_stabilize_reference (lhs); > rhs = rvalue (rhs); > rhs = stabilize_expr (rhs, &init); > - newrhs = cp_build_binary_op (input_location, > - modifycode, lhs, rhs, > - complain); > + newrhs = cp_build_binary_op (loc, modifycode, lhs, rhs, complain); > if (newrhs == error_mark_node) > { > if (complain & tf_error) > @@ -7893,7 +7894,7 @@ build_x_modify_expr (location_t loc, tree lhs, enum > tree_code modifycode, > return rval; > } > } > - return cp_build_modify_expr (lhs, modifycode, rhs, complain); > + return cp_build_modify_expr (loc, lhs, modifycode, rhs, complain); > } > > /* Helper function for get_delta_difference which assumes FROM is a base > diff --git gcc/cp/typeck2.c gcc/cp/typeck2.c > index e59ad51..1c4e832 100644 > --- gcc/cp/typeck2.c > +++ gcc/cp/typeck2.c > @@ -451,8 +451,8 @@ cxx_incomplete_type_inform (const_tree type) > type of diagnostic (see diagnostic.def). */ > > void > -cxx_incomplete_type_diagnostic (const_tree value, const_tree type, > - diagnostic_t diag_kind) > +cxx_incomplete_type_diagnostic (location_t loc, const_tree value, > + const_tree type, diagnostic_t diag_kind) > { > bool is_decl = false, complained = false; > > @@ -475,8 +475,6 @@ cxx_incomplete_type_diagnostic (const_tree value, > const_tree type, > retry: > /* We must print an error message. Be clever about what it says. */ > > - location_t loc = EXPR_LOC_OR_LOC (value, input_location); > - > switch (TREE_CODE (type)) > { > case RECORD_TYPE: > @@ -570,13 +568,14 @@ cxx_incomplete_type_diagnostic (const_tree value, > const_tree type, > } > } > > -/* Backward-compatibility interface to incomplete_type_diagnostic; > - required by ../tree.c. */ > -#undef cxx_incomplete_type_error > +/* Print an error message for invalid use of an incomplete type. > + VALUE is the expression that was used (or 0 if that isn't known) > + and TYPE is the type that was invalid. */ > + > void > -cxx_incomplete_type_error (const_tree value, const_tree type) > +cxx_incomplete_type_error (location_t loc, const_tree value, const_tree type) > { > - cxx_incomplete_type_diagnostic (value, type, DK_ERROR); > + cxx_incomplete_type_diagnostic (loc, value, type, DK_ERROR); > } > > > diff --git gcc/langhooks-def.h gcc/langhooks-def.h > index a2566ec..034b3b7 100644 > --- gcc/langhooks-def.h > +++ gcc/langhooks-def.h > @@ -52,7 +52,7 @@ extern void lhd_print_error_function (diagnostic_context *, > const char *, struct diagnostic_info *); > extern void lhd_set_decl_assembler_name (tree); > extern bool lhd_warn_unused_global_decl (const_tree); > -extern void lhd_incomplete_type_error (const_tree, const_tree); > +extern void lhd_incomplete_type_error (location_t, const_tree, const_tree); > extern tree lhd_type_promotes_to (tree); > extern void lhd_register_builtin_type (tree, const char *); > extern bool lhd_decl_ok_for_sibcall (const_tree); > diff --git gcc/langhooks.c gcc/langhooks.c > index 7c07175..6444631 100644 > --- gcc/langhooks.c > +++ gcc/langhooks.c > @@ -199,7 +199,8 @@ lhd_register_builtin_type (tree ARG_UNUSED (type), > > /* Invalid use of an incomplete type. */ > void > -lhd_incomplete_type_error (const_tree ARG_UNUSED (value), const_tree type) > +lhd_incomplete_type_error (location_t ARG_UNUSED (loc), > + const_tree ARG_UNUSED (value), const_tree type) > { > gcc_assert (TREE_CODE (type) == ERROR_MARK); > return; > diff --git gcc/langhooks.h gcc/langhooks.h > index bcfd389..0593424 100644 > --- gcc/langhooks.h > +++ gcc/langhooks.h > @@ -100,8 +100,9 @@ struct lang_hooks_for_types > /* This routine is called in tree.c to print an error message for > invalid use of an incomplete type. VALUE is the expression that > was used (or 0 if that isn't known) and TYPE is the type that was > - invalid. */ > - void (*incomplete_type_error) (const_tree value, const_tree type); > + invalid. LOC is the location of the use. */ > + void (*incomplete_type_error) (location_t loc, const_tree value, > + const_tree type); > > /* Called from assign_temp to return the maximum size, if there is one, > for a type. */ > diff --git gcc/testsuite/c-c++-common/pr70756-2.c > gcc/testsuite/c-c++-common/pr70756-2.c > index e69de29..b7df3b7 100644 > --- gcc/testsuite/c-c++-common/pr70756-2.c > +++ gcc/testsuite/c-c++-common/pr70756-2.c > @@ -0,0 +1,12 @@ > +/* PR c/70756 */ > +/* { dg-do compile } */ > +/* { dg-options "-Wpointer-arith" } */ > + > +extern void bar (void); > + > +void > +fn (void *p) > +{ > + void *a = p + 1; /* { dg-warning "15:pointer of type" } */ > + void (*a2)(void) = &bar + 1; /* { dg-warning "27:pointer to a function" } > */ > +} > diff --git gcc/testsuite/c-c++-common/pr70756.c > gcc/testsuite/c-c++-common/pr70756.c > index e69de29..3725922 100644 > --- gcc/testsuite/c-c++-common/pr70756.c > +++ gcc/testsuite/c-c++-common/pr70756.c > @@ -0,0 +1,23 @@ > +/* PR c/70756 */ > +/* { dg-do compile } */ > +/* { dg-options "" } */ > + > +enum E e; /* { dg-error "storage size|use of enum" } */ > +int (*A)[]; > + > +void > +fn0 (void) > +{ > + struct > + { > + int x; > + int y[]; > + } s; > + 1234 && &s.y + 1; /* { dg-error "16:invalid use of" } */ > +} > + > +void > +fn1 (void) > +{ > + 1234, A += 1; /* { dg-error "11:invalid use of array with unspecified > bounds" } */ > +} > diff --git gcc/tree.c gcc/tree.c > index c565337..b63f64c 100644 > --- gcc/tree.c > +++ gcc/tree.c > @@ -2939,7 +2939,7 @@ ctor_to_vec (tree ctor) > make_unsigned_type). */ > > tree > -size_in_bytes (const_tree type) > +size_in_bytes_loc (location_t loc, const_tree type) > { > tree t; > > @@ -2951,7 +2951,7 @@ size_in_bytes (const_tree type) > > if (t == 0) > { > - lang_hooks.types.incomplete_type_error (NULL_TREE, type); > + lang_hooks.types.incomplete_type_error (loc, NULL_TREE, type); > return size_zero_node; > } > > diff --git gcc/tree.h gcc/tree.h > index 6e52e3d..37324bf 100644 > --- gcc/tree.h > +++ gcc/tree.h > @@ -4224,7 +4224,13 @@ extern tree type_hash_canon (unsigned int, tree); > > extern tree convert (tree, tree); > extern unsigned int expr_align (const_tree); > -extern tree size_in_bytes (const_tree); > +extern tree size_in_bytes_loc (location_t, const_tree); > +inline tree > +size_in_bytes (const_tree t) > +{ > + return size_in_bytes_loc (input_location, t); > +} > + > extern HOST_WIDE_INT int_size_in_bytes (const_tree); > extern HOST_WIDE_INT max_int_size_in_bytes (const_tree); > extern tree bit_position (const_tree); > > Marek
Marek