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

            Bug ID: 100717
           Summary: missing warning for a call to a function with
                    attribute access inlined into caller
           Product: gcc
           Version: 11.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: msebor at gcc dot gnu.org
  Target Milestone: ---

GCC issues warnings for (likely) out of bounds accesses by calls to functions
declared with attribute access.  An example is the call to f0() in f1() below. 
But no warning is issued when the called function is inlined, as happens with
g0() in g1().  This is because the attribute on the called function disappears
once it's inlined.

This problem could be solved either by (also) issuing the warning early, just
before inlining, for the subset of calls with constant arguments, or by
preserving the call statements in some data structure even after they have been
inlined and analyzing them much later, after constant and range propagation, if
they're not removed by dead code elimination.

$ cat a.c && gcc -O2 -S -Wall a.c
__attribute__ ((access (write_only, 1, 3), access (read_only, 2, 3)))
__attribute__ ((noinline))
void f0 (int *a, const int *b, unsigned n)
{
  for (unsigned i = 0; i != n; ++i)
    a[i] += b[i];
}

void f1 (int a[4])
{
  f0 (a, (int[]){ 3, 3, 3 }, 4);   // warning (good)
}


__attribute__ ((access (write_only, 1, 3), access (read_only, 2, 3))) 
void g0 (int *a, const int *b, unsigned n)
{
  for (unsigned i = 0; i != n; ++i)
    a[i] += b[i];
}

void g1 (int a[4])
{
  g0 (a, (int[]){ 3, 3, 3 }, 4);   // missing warning
}
a.c: In function ‘f1’:
a.c:11:3: warning: ‘f0’ reading 16 bytes from a region of size 12
[-Wstringop-overread]
   11 |   f0 (a, (int[]){ 3, 3, 3 }, 4);   // warning (good)
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
a.c:11:17: note: source object ‘<Uabd0>’ of size 12
   11 |   f0 (a, (int[]){ 3, 3, 3 }, 4);   // warning (good)
      |                 ^
a.c:3:6: note: in a call to function ‘f0’ declared with attribute ‘access
(read_only, 2, 3)’
    3 | void f0 (int *a, const int *b, unsigned n)
      |      ^~

Reply via email to