public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c/100403] New: Bogus "function may return address of local variable" warning
@ 2021-05-03 18:52 lavr at ncbi dot nlm.nih.gov
  2021-05-03 19:09 ` [Bug c/100403] " pinskia at gcc dot gnu.org
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: lavr at ncbi dot nlm.nih.gov @ 2021-05-03 18:52 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100403

            Bug ID: 100403
           Summary: Bogus "function may return address of local variable"
                    warning
           Product: gcc
           Version: 10.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: lavr at ncbi dot nlm.nih.gov
  Target Milestone: ---

$ gcc --version
gcc (GCC) 10.2.0


$ cat test.c
#include <stdio.h>
#include <string.h>

#define RECLEN  128


struct R {
    int  head;
    int  code;
    char text[1];
};


const char* fun(int n, const struct R* p)
{
    union {
        struct R r;
        char     rec[RECLEN];
    } x;
    const char* err = 0;

    memset(&x, 0, sizeof(x));
    if (p)
        memcpy(&x.r, p, sizeof(*p));
    else
        err = "Invalid argument";

    if (!err) {
        static const char magic[] = "MAGIC";
        const char* msg;
        if (memcmp(x.rec, magic, sizeof(magic)-1) == 0)
            msg = x.rec;
        else if (x.r.text[0])
            msg = x.r.text;
        else
            msg = "Error w/code";
        if (msg)
            printf("%s\n", msg);
        if (x.rec <= msg  &&  msg < x.rec + sizeof(x))
            err = "Error detected";
        else
            err = msg;
    } else
        printf("%s\n", err);
    return err;
}


$ gcc -Wall -O2 -c test.c
test.c: In function ‘fun’:
test.c:45:12: warning: function may return address of local variable
[-Wreturn-local-addr]
   45 |     return err;
      |            ^~~
test.c:19:7: note: declared here
   19 |     } x;
      |       ^
test.c:19:7: note: declared here


Noted that does not matter whether "sizeof(x)" or "sizeof(x.rec)" is used at
the end of the "if()" statement on line 39.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Bug c/100403] Bogus "function may return address of local variable" warning
  2021-05-03 18:52 [Bug c/100403] New: Bogus "function may return address of local variable" warning lavr at ncbi dot nlm.nih.gov
@ 2021-05-03 19:09 ` pinskia at gcc dot gnu.org
  2021-05-03 20:14 ` lavr at ncbi dot nlm.nih.gov
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: pinskia at gcc dot gnu.org @ 2021-05-03 19:09 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100403

--- Comment #1 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
Note, the following condition in the if statement
        if (x.rec <= msg  &&  msg < x.rec + sizeof(x))

Is undefined if msg is not in the range of x.rec[0]...x.rec[RECLEN] .

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Bug c/100403] Bogus "function may return address of local variable" warning
  2021-05-03 18:52 [Bug c/100403] New: Bogus "function may return address of local variable" warning lavr at ncbi dot nlm.nih.gov
  2021-05-03 19:09 ` [Bug c/100403] " pinskia at gcc dot gnu.org
@ 2021-05-03 20:14 ` lavr at ncbi dot nlm.nih.gov
  2021-05-03 20:46 ` [Bug middle-end/100403] " msebor at gcc dot gnu.org
  2021-05-03 20:49 ` msebor at gcc dot gnu.org
  3 siblings, 0 replies; 5+ messages in thread
From: lavr at ncbi dot nlm.nih.gov @ 2021-05-03 20:14 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100403

--- Comment #2 from lavr at ncbi dot nlm.nih.gov ---
> undefined if msg is not in the range of x.rec[0]...x.rec[RECLEN]

Indeed for the segmented data address space.  But in most systems it's linear,
and the warning is then architecture dependent, and is only expected on those,
where the comparison cannot be safely made.  Besides, the warning then should
be about that fact, not the return address being of a local variable -- that's
misleading, at best.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Bug middle-end/100403] Bogus "function may return address of local variable" warning
  2021-05-03 18:52 [Bug c/100403] New: Bogus "function may return address of local variable" warning lavr at ncbi dot nlm.nih.gov
  2021-05-03 19:09 ` [Bug c/100403] " pinskia at gcc dot gnu.org
  2021-05-03 20:14 ` lavr at ncbi dot nlm.nih.gov
@ 2021-05-03 20:46 ` msebor at gcc dot gnu.org
  2021-05-03 20:49 ` msebor at gcc dot gnu.org
  3 siblings, 0 replies; 5+ messages in thread
From: msebor at gcc dot gnu.org @ 2021-05-03 20:46 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100403

Martin Sebor <msebor at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |diagnostic
          Component|c                           |middle-end
                 CC|                            |msebor at gcc dot gnu.org
         Resolution|---                         |INVALID
             Status|UNCONFIRMED                 |RESOLVED

--- Comment #3 from Martin Sebor <msebor at gcc dot gnu.org> ---
The warning behaves as designed.  There's no way for it tell from the IL that
the function cannot return the address of x:

  <bb 7> [local count: 375809640]:
  # msg_21 = PHI <"Error w/code"(6), msg_19(10)>
  if (&MEM <char[128]> [(void *)&x + 128B] > msg_21)
    goto <bb 9>; [50.00%]
  else
    goto <bb 8>; [50.00%]

  <bb 8> [local count: 187904820]:

  <bb 9> [local count: 1073741824]:
  # err_3 = PHI <msg_21(8), "Invalid argument"(4), "Error detected"(7), "Error
w/code"(6)>
  x ={v} {CLOBBER};
  return err_3;                              <<< -Wreturn-local-addr

  <bb 10> [local count: 375809641]:
  # msg_19 = PHI <&x.r.text(5), &x.rec(3)>   <<< x is on stack
  __builtin_puts (msg_19);
  goto <bb 7>; [100.00%]

}

As Andrew explained, the pointer relational expression is undefined if msg
points to the string literal (changing it to equality avoids the warning).  In
addition, and arguably more important, GCC's ability to extract useful
information from pointer relationships is quite limited so it doesn't "see
through" the expression.  The underlying problem (and the limitation) can be
reduced to the failure to fold and the false positive for the much simpler test
case below.  For a + n to be valid n must be zero or one, and so the function
must return null.  If GCC used that to fold the function the warning wouldn't
trigger.

With that, I think the report can be resolved as invalid (I'm sure the pointer
range optimization has its own bug.)

$ cat z.c && gcc -O2 -S -Wall -fdump-tree-isolate-paths=/dev/stdout z.c
void* f (int n)
{
  char a[1], *p = a + n;
  if (p <= a + 1)
    p = 0;
  return p;
}

;; Function f (f, funcdef_no=0, decl_uid=1943, cgraph_uid=1, symbol_order=0)

z.c: In function ‘f’:
z.c:6:10: warning: function may return address of local variable
[-Wreturn-local-addr]
    6 |   return p;
      |          ^
z.c:3:8: note: declared here
    3 |   char a[1], *p = a + n;
      |        ^

SSA replacement table
N_i -> { O_1 ... O_j } means that N_i replaces O_1, ..., O_j

p_7 -> { p_2 }
.MEM_8 -> { .MEM_6 }
Incremental SSA update started at block: 2
Number of blocks in CFG: 6
Number of blocks to update: 2 ( 33%)


Removing basic block 3
void * f (int n)
{
  char * p;
  char a[1];
  sizetype _1;

  <bb 2> [local count: 1073741824]:
  _1 = (sizetype) n_3(D);
  p_4 = &a + _1;
  if (&MEM <char[1]> [(void *)&a + 1B] >= p_4)
    goto <bb 3>; [100.00%]
  else
    goto <bb 4>; [0.00%]

  <bb 3> [local count: 311385128]:
  # p_2 = PHI <0B(2)>
  a ={v} {CLOBBER};
  return p_2;

  <bb 4> [count: 0]:
  # p_7 = PHI <p_4(2)>
  a ={v} {CLOBBER};
  return 0B;

}

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Bug middle-end/100403] Bogus "function may return address of local variable" warning
  2021-05-03 18:52 [Bug c/100403] New: Bogus "function may return address of local variable" warning lavr at ncbi dot nlm.nih.gov
                   ` (2 preceding siblings ...)
  2021-05-03 20:46 ` [Bug middle-end/100403] " msebor at gcc dot gnu.org
@ 2021-05-03 20:49 ` msebor at gcc dot gnu.org
  3 siblings, 0 replies; 5+ messages in thread
From: msebor at gcc dot gnu.org @ 2021-05-03 20:49 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100403

Martin Sebor <msebor at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           See Also|                            |https://gcc.gnu.org/bugzill
                   |                            |a/show_bug.cgi?id=91227

--- Comment #4 from Martin Sebor <msebor at gcc dot gnu.org> ---
The pointer limitation is discussed in more detail in pr91227.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-05-03 20:49 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-03 18:52 [Bug c/100403] New: Bogus "function may return address of local variable" warning lavr at ncbi dot nlm.nih.gov
2021-05-03 19:09 ` [Bug c/100403] " pinskia at gcc dot gnu.org
2021-05-03 20:14 ` lavr at ncbi dot nlm.nih.gov
2021-05-03 20:46 ` [Bug middle-end/100403] " msebor at gcc dot gnu.org
2021-05-03 20:49 ` msebor at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).