I spent way too long poking at various adjustments of this; here's what I settled on for GCC 15.
Tested x86_64-pc-linux-gnu, applying to trunk. -- 8< -- When the program requests a conversion to a typedef, let's try harder to remember the new name. Torbjörn's original patch changed the type of the original expression, but that seems not generally desirable; we might want either or both of the original type and the converted-to type to be represented. So this expresses the name change as a NOP_EXPR. Compiling stdc++.h, this adds 519 allocations out of 1870k, or 0.28%. The -Wsuggest-attribute=format change was necessary to do the check before converting to the target type, which seems like an improvement. PR c/116060 gcc/c/ChangeLog: * c-typeck.cc (convert_for_assignment): Make sure left hand side and right hand side has identical named types to aid diagnostic output. gcc/cp/ChangeLog: * call.cc (standard_conversion): Preserve type name in ck_identity. (maybe_adjust_type_name): New. (convert_like_internal): Use it. Handle -Wsuggest-attribute=format here. (convert_for_arg_passing): Not here. gcc/testsuite/ChangeLog: * c-c++-common/analyzer/out-of-bounds-diagram-8.c: Update to correct type. * c-c++-common/analyzer/out-of-bounds-diagram-11.c: Likewise. * gcc.dg/analyzer/out-of-bounds-diagram-10.c: Likewise. Co-authored-by: Torbjörn SVENSSON <torbjorn.svens...@foss.st.com> Signed-off-by: Torbjörn SVENSSON <torbjorn.svens...@foss.st.com> --- gcc/c/c-typeck.cc | 3 + gcc/cp/call.cc | 68 ++++++++++++++----- .../analyzer/out-of-bounds-diagram-11.c | 28 ++++---- .../analyzer/out-of-bounds-diagram-8.c | 28 ++++---- .../analyzer/out-of-bounds-diagram-10.c | 28 ++++---- 5 files changed, 96 insertions(+), 59 deletions(-) diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index dbb688cabaa..6e40f7edf02 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -7831,6 +7831,9 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype)) { warn_for_address_of_packed_member (type, orig_rhs); + if (type != rhstype) + /* Convert RHS to TYPE in order to not lose TYPE in diagnostics. */ + rhs = convert (type, rhs); return rhs; } diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index 5dbaec983f6..602f496e180 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -1319,6 +1319,9 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p, { if (CLASS_TYPE_P (to) && conv->kind == ck_rvalue) conv->type = qualified_to; + else if (from != to) + /* Use TO in order to not lose TO in diagnostics. */ + conv->type = to; return conv; } @@ -8486,6 +8489,37 @@ maybe_warn_array_conv (location_t loc, conversion *c, tree expr) static tree convert_like (conversion *, tree, tree, int, bool, bool, bool, tsubst_flags_t); +/* Adjust the result EXPR of a conversion to the expected type TOTYPE, which + must be equivalent but might be a typedef. */ + +static tree +maybe_adjust_type_name (tree type, tree expr, conversion_kind kind) +{ + if (expr == error_mark_node + || processing_template_decl) + return expr; + + tree etype = TREE_TYPE (expr); + if (etype == type) + return expr; + + gcc_checking_assert (same_type_ignoring_top_level_qualifiers_p (etype, type) + || is_bitfield_expr_with_lowered_type (expr) + || seen_error ()); + + if (SCALAR_TYPE_P (type) + && (kind == ck_rvalue + /* ??? We should be able to do this for ck_identity of more prvalue + expressions, but checking !obvalue_p here breaks, so for now let's + just handle NON_LVALUE_EXPR (such as the location wrapper for a + literal). Maybe we want to express already-rvalue in the + conversion somehow? */ + || TREE_CODE (expr) == NON_LVALUE_EXPR)) + expr = build_nop (type, expr); + + return expr; +} + /* Perform the conversions in CONVS on the expression EXPR. FN and ARGNUM are used for diagnostics. ARGNUM is zero based, -1 indicates the `this' argument of a method. INNER is nonzero when @@ -8747,7 +8781,7 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum, continue to warn about uses of EXPR as an integer, rather than as a pointer. */ expr = build_int_cst (totype, 0); - return expr; + return maybe_adjust_type_name (totype, expr, convs->kind); case ck_ambig: /* We leave bad_p off ck_ambig because overload resolution considers it valid, it just fails when we try to perform it. So we need to @@ -8885,8 +8919,22 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum, return error_mark_node; } + if ((complain & tf_warning) && fn + && warn_suggest_attribute_format) + { + tree rhstype = TREE_TYPE (expr); + const enum tree_code coder = TREE_CODE (rhstype); + const enum tree_code codel = TREE_CODE (totype); + if ((codel == POINTER_TYPE || codel == REFERENCE_TYPE) + && coder == codel + && check_missing_format_attribute (totype, rhstype)) + warning (OPT_Wsuggest_attribute_format, + "argument of function call might be a candidate " + "for a format attribute"); + } + if (! MAYBE_CLASS_TYPE_P (totype)) - return expr; + return maybe_adjust_type_name (totype, expr, convs->kind); /* Don't introduce copies when passing arguments along to the inherited constructor. */ @@ -9512,21 +9560,7 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain) && tree_int_cst_lt (TYPE_SIZE (type), TYPE_SIZE (integer_type_node))) val = cp_perform_integral_promotions (val, complain); if (complain & tf_warning) - { - if (warn_suggest_attribute_format) - { - tree rhstype = TREE_TYPE (val); - const enum tree_code coder = TREE_CODE (rhstype); - const enum tree_code codel = TREE_CODE (type); - if ((codel == POINTER_TYPE || codel == REFERENCE_TYPE) - && coder == codel - && check_missing_format_attribute (type, rhstype)) - warning (OPT_Wsuggest_attribute_format, - "argument of function call might be a candidate " - "for a format attribute"); - } - maybe_warn_parm_abi (type, cp_expr_loc_or_input_loc (val)); - } + maybe_warn_parm_abi (type, cp_expr_loc_or_input_loc (val)); if (complain & tf_warning) warn_for_address_of_packed_member (type, val); diff --git a/gcc/testsuite/c-c++-common/analyzer/out-of-bounds-diagram-11.c b/gcc/testsuite/c-c++-common/analyzer/out-of-bounds-diagram-11.c index 63ae08347aa..048a1b9698f 100644 --- a/gcc/testsuite/c-c++-common/analyzer/out-of-bounds-diagram-11.c +++ b/gcc/testsuite/c-c++-common/analyzer/out-of-bounds-diagram-11.c @@ -47,20 +47,20 @@ void test7 (size_t size) /* { dg-begin-multiline-output "" } - ┌───────────────────────────────────────┐ - │ write of '(int) 42' │ - └───────────────────────────────────────┘ - │ │ - │ │ - v v - ┌──────────────────────────────────────────────────┐┌──────────────────┐ - │ buffer allocated on stack at (1) ││after valid range │ - └──────────────────────────────────────────────────┘└──────────────────┘ - ├────────────────────────┬─────────────────────────┤├────────┬─────────┤ - │ │ - ╭────────────────┴───────────────╮ ╭─────────┴────────╮ - │capacity: '(size * 4) + 3' bytes│ │overflow of 1 byte│ - ╰────────────────────────────────╯ ╰──────────────────╯ + ┌────────────────────────────────────────┐ + │ write of '(int32_t) 42' │ + └────────────────────────────────────────┘ + │ │ + │ │ + v v + ┌────────────────────────────────────────────────┐ ┌───────────────────┐ + │ buffer allocated on stack at (1) │ │ after valid range │ + └────────────────────────────────────────────────┘ └───────────────────┘ + ├───────────────────────┬────────────────────────┤ ├─────────┬─────────┤ + │ │ + ╭────────────────┴───────────────╮ ╭─────────┴────────╮ + │capacity: '(size * 4) + 3' bytes│ │overflow of 1 byte│ + ╰────────────────────────────────╯ ╰──────────────────╯ { dg-end-multiline-output "" } */ diff --git a/gcc/testsuite/c-c++-common/analyzer/out-of-bounds-diagram-8.c b/gcc/testsuite/c-c++-common/analyzer/out-of-bounds-diagram-8.c index c8ff2fd1e64..4d1f5227049 100644 --- a/gcc/testsuite/c-c++-common/analyzer/out-of-bounds-diagram-8.c +++ b/gcc/testsuite/c-c++-common/analyzer/out-of-bounds-diagram-8.c @@ -18,19 +18,19 @@ void test2 (size_t size) /* { dg-begin-multiline-output "" } - ┌───────────────────┐ - │write of '(int) 42'│ - └───────────────────┘ - │ - │ - v - ┌───────────────────────────────┐ ┌───────────────────┐ - │buffer allocated on heap at (1)│ │ after valid range │ - └───────────────────────────────┘ └───────────────────┘ - ├───────────────┬───────────────┤├───────┬────────┤├─────────┬─────────┤ - │ │ │ - ╭─────────────┴────────────╮ ╭───┴───╮ ╭─────────┴─────────╮ - │capacity: 'size * 4' bytes│ │4 bytes│ │overflow of 4 bytes│ - ╰──────────────────────────╯ ╰───────╯ ╰───────────────────╯ + ┌───────────────────────┐ + │write of '(int32_t) 42'│ + └───────────────────────┘ + │ + │ + v + ┌───────────────────────────────┐ ┌───────────────────────┐ + │buffer allocated on heap at (1)│ │ after valid range │ + └───────────────────────────────┘ └───────────────────────┘ + ├───────────────┬───────────────┤├─────┬──────┤├───────────┬───────────┤ + │ │ │ + ╭─────────────┴────────────╮ ╭───┴───╮ ╭─────────┴─────────╮ + │capacity: 'size * 4' bytes│ │4 bytes│ │overflow of 4 bytes│ + ╰──────────────────────────╯ ╰───────╯ ╰───────────────────╯ { dg-end-multiline-output "" } */ diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-10.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-10.c index 4a7b8e306de..f719c4801dd 100644 --- a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-10.c +++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-10.c @@ -11,19 +11,19 @@ int32_t int_vla_write_element_symbolic_before_start (int32_t x, size_t n) /* { dg-begin-multiline-output "" } - ┌───────────────────┐ - │write of '(int) 42'│ - └───────────────────┘ - │ - │ - v - ┌───────────────────┐ ┌────────────────────────────────┐ - │before valid range │ │buffer allocated on stack at (1)│ - └───────────────────┘ └────────────────────────────────┘ - ├─────────┬─────────┤├───────┬───────┤├───────────────┬────────────────┤ - │ │ │ - ╭─────────┴───────────╮ ╭───┴───╮ ╭───────────┴───────────╮ - │underwrite of 4 bytes│ │4 bytes│ │capacity: 'n * 4' bytes│ - ╰─────────────────────╯ ╰───────╯ ╰───────────────────────╯ + ┌───────────────────────┐ + │write of '(int32_t) 42'│ + └───────────────────────┘ + │ + │ + v + ┌───────────────────────┐ ┌────────────────────────────────┐ + │ before valid range │ │buffer allocated on stack at (1)│ + └───────────────────────┘ └────────────────────────────────┘ + ├───────────┬───────────┤├─────┬─────┤├───────────────┬────────────────┤ + │ │ │ + ╭──────────┴──────────╮ ╭───┴───╮ ╭───────────┴───────────╮ + │underwrite of 4 bytes│ │4 bytes│ │capacity: 'n * 4' bytes│ + ╰─────────────────────╯ ╰───────╯ ╰───────────────────────╯ { dg-end-multiline-output "" } */ base-commit: 04f4ac9218259a1508f9a86ca98cf1d36cab2df2 -- 2.47.1