diff options
author | Jason Merrill <jason@redhat.com> | 2024-12-23 09:18:41 -0500 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2025-01-09 14:32:34 -0500 |
commit | c6b54302df470bf09801ad6785d5713ef23dcb38 (patch) | |
tree | eccf232465b62b314bc90717689e42ef110d62da | |
parent | 04f4ac9218259a1508f9a86ca98cf1d36cab2df2 (diff) | |
download | gcc-c6b54302df470bf09801ad6785d5713ef23dcb38.zip gcc-c6b54302df470bf09801ad6785d5713ef23dcb38.tar.gz gcc-c6b54302df470bf09801ad6785d5713ef23dcb38.tar.bz2 |
c, c++: preserve type name in conversion [PR116060]
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.svensson@foss.st.com>
Signed-off-by: Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>
-rw-r--r-- | gcc/c/c-typeck.cc | 3 | ||||
-rw-r--r-- | gcc/cp/call.cc | 68 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/analyzer/out-of-bounds-diagram-11.c | 28 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/analyzer/out-of-bounds-diagram-8.c | 28 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/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 dbb688c..6e40f7e 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 5dbaec9..602f496 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 63ae083..048a1b9 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 c8ff2fd..4d1f522 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 4a7b8e3..f719c48 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 "" } */ |