Bug 101854 - [11 Regression] Invalid warning -Wstringop-overflow wrong argument
Summary: [11 Regression] Invalid warning -Wstringop-overflow wrong argument
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 11.2.0
: P3 normal
Target Milestone: 12.0
Assignee: Martin Sebor
URL:
Keywords: diagnostic
Depends on:
Blocks: Wstringop-overflow
  Show dependency treegraph
 
Reported: 2021-08-10 23:39 UTC by nightstrike
Modified: 2024-07-19 07:24 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work: 12.0
Known to fail: 11.2.0
Last reconfirmed: 2021-08-12 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description nightstrike 2021-08-10 23:39:52 UTC
void f() {
        struct Weird {
                float a; // Comment out any member
                float b; // to silence the warning
                float c;
                float d;
                float e;
        };
        struct Weird g(float const Q[2], float const null[6][8]) {
                return (struct Weird){0};
        }

        float const q[2];
        struct Weird ss = g(q, (void *)0);
}

$ gcc -c a.c
a.c: In function 'f':
a.c:14:27: warning: 'g' accessing 192 bytes in a region of size 8 [-Wstringop-overflow=]
   14 |         struct Weird ss = g(q, (void *)0);
      |                           ^~~~~~~~~~~~~~~
a.c:14:27: note: referencing argument 2 of type 'const float (*)[8]'
a.c:9:22: note: in a call to function 'g'
    9 |         struct Weird g(float const Q[2], float const null[6][8]) {
      |                      ^


$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/tmp/bin/../libexec/gcc/x86_64-pc-linux-gnu/11.2.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../src/gcc-11.2.0/configure --disable-nls --disable-multilib --enable-languages=all --prefix=/tmp
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 11.2.0 (GCC)
Comment 1 Andrew Pinski 2021-08-10 23:44:22 UTC
Slightly more reduced:
void f() {
        struct Weird {
                float a[5]; // decrease to 4 will cause the warning to disappear
        };
        struct Weird g(float const Q[2], float const null[6][8]) {
                return (struct Weird){0};
        }

        float const q[2];
        struct Weird ss = g(q, (void *)0);
}
Comment 2 nightstrike 2021-08-10 23:45:00 UTC
So to clarify, the "192 bytes" is the size of the flagged argument #2.  The "size 8" is the size of the first argument.  If you change q and Q to be 3 elements, then size is 12, etc.
Comment 3 Andrew Pinski 2021-08-10 23:48:25 UTC
So this is not related to nested functions at all (just in case people thought it was):
struct Weird {
        float a[5]; // decrease to 4 will cause the warning to disappear
};
struct Weird g(float const Q[2], float const null[6][8]) {
        return (struct Weird){0};
}
void f() {
        float const q[2]={0};
        struct Weird ss = g(q, (void *)0);
}
Comment 4 nightstrike 2021-08-10 23:50:02 UTC
(In reply to Andrew Pinski from comment #3)
> So this is not related to nested functions at all (just in case people
> thought it was):

It's also not due to flexible array members, given the change from 5 members to an array. I only mention it because I've submitted a report in the past about a different warning that was affected by that feature of C.
Comment 5 Andrew Pinski 2021-08-10 23:51:53 UTC
__attribute__((access ("^0[2]^1[6]", )))
struct Weird g (const float * Q, const float[8] * null)

  ss = g (&q, 0B); [return slot optimization]
Comment 6 Andrew Pinski 2021-08-10 23:58:15 UTC
(In reply to Andrew Pinski from comment #5)
> __attribute__((access ("^0[2]^1[6]", )))
> struct Weird g (const float * Q, const float[8] * null)
> 
>   ss = g (&q, 0B); [return slot optimization]

In the 4 case we get:
  ss = g (&q, 0B);

So no RSO.
So yes the code looks like it is counting wrong somewhere.
Comment 7 Martin Sebor 2021-08-12 22:30:05 UTC
Below is a further simplified test case.  The code in initialize_argument_information() that computes the sizes of actual arguments to array parameters and issues a warning if the former is less than expected doesn't consider the implicit pointer argument passed to functions that return structs by value.  It's off by one for those.

$ cat t.c && gcc -S -Wall t.c
struct A { int a[5]; };

struct A g (int*, int[6][8]);

struct A f (void)
{
  int a[2];
  return g (a, 0);
}

t.c: In function ‘f’:
t.c:8:10: warning: ‘g’ accessing 192 bytes in a region of size 8 [-Wstringop-overflow=]
    8 |   return g (a, 0);
      |          ^~~~~~~~
t.c:8:10: note: referencing argument 2 of type ‘int (*)[8]’
t.c:3:10: note: in a call to function ‘g’
    3 | struct A g (int*, int[6][8]);
      |          ^
Comment 8 GCC Commits 2021-08-17 20:51:36 UTC
The master branch has been updated by Martin Sebor <msebor@gcc.gnu.org>:

https://gcc.gnu.org/g:b48d4e6818674898f90d9358378c127511ef0f9f

commit r12-2976-gb48d4e6818674898f90d9358378c127511ef0f9f
Author: Martin Sebor <msebor@redhat.com>
Date:   Tue Aug 17 14:49:05 2021 -0600

    Move more warning code to gimple-ssa-warn-access etc.
    
    Also resolves:
    PR middle-end/101854 - Invalid warning -Wstringop-overflow wrong argument
    
    gcc/ChangeLog:
    
            PR middle-end/101854
            * builtins.c (expand_builtin_alloca): Move warning code to check_alloca
            in gimple-ssa-warn-access.cc.
            * calls.c (alloc_max_size): Move code to check_alloca.
            (get_size_range): Move to pointer-query.cc.
            (maybe_warn_alloc_args_overflow): Move to gimple-ssa-warn-access.cc.
            (get_attr_nonstring_decl): Move to tree.c.
            (fntype_argno_type): Move to gimple-ssa-warn-access.cc.
            (append_attrname): Same.
            (maybe_warn_rdwr_sizes): Same.
            (initialize_argument_information): Move code to
            gimple-ssa-warn-access.cc.
            * calls.h (maybe_warn_alloc_args_overflow): Move to
            gimple-ssa-warn-access.h.
            (get_attr_nonstring_decl): Move to tree.h.
            (maybe_warn_nonstring_arg):  Move to gimple-ssa-warn-access.h.
            (enum size_range_flags): Move to pointer-query.h.
            (get_size_range): Same.
            * gimple-ssa-warn-access.cc (has_location): Remove unused overload
            to avoid Clang -Wunused-function.
            (get_size_range): Declare static.
            (maybe_emit_free_warning): Rename...
            (maybe_check_dealloc_call): ...to this for consistency.
            (class pass_waccess): Add members.
            (pass_waccess::~pass_waccess): Defined.
            (alloc_max_size): Move here from calls.c.
            (maybe_warn_alloc_args_overflow): Same.
            (check_alloca): New function.
            (check_alloc_size_call): New function.
            (check_strncat): Handle another warning flag.
            (pass_waccess::check_builtin): Handle alloca.
            (fntype_argno_type): Move here from calls.c.
            (append_attrname): Same.
            (maybe_warn_rdwr_sizes): Same.
            (pass_waccess::check_call): Define.
            (check_nonstring_args): New function.
            (pass_waccess::check): Call new member functions.
            (pass_waccess::execute): Enable ranger.
            * gimple-ssa-warn-access.h (get_size_range): Move here from calls.h.
            (maybe_warn_nonstring_arg): Same.
            * gimple-ssa-warn-restrict.c: Remove #include.
            * pointer-query.cc (get_size_range): Move here from calls.c.
            * pointer-query.h (enum size_range_flags): Same.
            (get_size_range): Same.
            * tree.c (get_attr_nonstring_decl): Move here from calls.c.
            * tree.h (get_attr_nonstring_decl): Move here from calls.h.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/attr-alloc_size-5.c: Adjust optimization to -O1.
            * gcc.dg/attr-alloc_size-7.c: Use #pragmas to adjust optimization.
            * gcc.dg/attr-alloc_size-8.c: Adjust optimization to -O1.
    
            PR middle-end/101854
            * gcc.dg/Wstringop-overflow-72.c: New test.
Comment 9 Martin Sebor 2021-08-17 20:53:20 UTC
Fixed for GCC 12.  The patch is far too intrusive to backport but the following should fix the problem in GCC 11:

diff --git a/gcc/calls.c b/gcc/calls.c
index fcb0d6dec69..f116923c890 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -2295,14 +2295,15 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
         operand for later processing.  */
       if (attr_access *access = rdwr_idx.get (argpos))
        {
+         int idx = i - !!struct_value_addr_value;
          if (POINTER_TYPE_P (type))
            {
-             access->ptr = args[i].tree_value;
+             access->ptr = args[idx].tree_value;
              // A nonnull ACCESS->SIZE contains VLA bounds.  */
            }
          else
            {
-             access->size = args[i].tree_value;
+             access->size = args[idx].tree_value;
              gcc_assert (access->ptr == NULL_TREE);
            }
        }
Comment 10 Richard Biener 2022-04-21 07:50:08 UTC
GCC 11.3 is being released, retargeting bugs to GCC 11.4.
Comment 11 nightstrike 2022-12-22 02:49:30 UTC
(In reply to Martin Sebor from comment #9)
> Fixed for GCC 12.  The patch is far too intrusive to backport but the
> following should fix the problem in GCC 11:

Would you mind applying it to 11?  Thanks!

Also, I think in your diff below, there's "// A nonnull" that should be "/* A nonnull"... / to *

> diff --git a/gcc/calls.c b/gcc/calls.c
> index fcb0d6dec69..f116923c890 100644
> --- a/gcc/calls.c
> +++ b/gcc/calls.c
> @@ -2295,14 +2295,15 @@ initialize_argument_information (int num_actuals
> ATTRIBUTE_UNUSED,
>          operand for later processing.  */
>        if (attr_access *access = rdwr_idx.get (argpos))
>         {
> +         int idx = i - !!struct_value_addr_value;
>           if (POINTER_TYPE_P (type))
>             {
> -             access->ptr = args[i].tree_value;
> +             access->ptr = args[idx].tree_value;
>               // A nonnull ACCESS->SIZE contains VLA bounds.  */
>             }
>           else
>             {
> -             access->size = args[i].tree_value;
> +             access->size = args[idx].tree_value;
>               gcc_assert (access->ptr == NULL_TREE);
>             }
>         }
Comment 12 Jakub Jelinek 2023-05-29 10:05:27 UTC
GCC 11.4 is being released, retargeting bugs to GCC 11.5.
Comment 13 Richard Biener 2024-07-19 07:24:29 UTC
Fixed in GCC 12.