Bug 240819 - GCC miscompiles heavily inlined code at -O2
GCC miscompiles heavily inlined code at -O2
Status: CLOSED NOTABUG
Product: Fedora
Classification: Fedora
Component: gcc (Show other bugs)
6
All Linux
high Severity high
: ---
: ---
Assigned To: Jakub Jelinek
:
Depends On:
Blocks:
  Show dependency treegraph
 
Reported: 2007-05-21 20:07 EDT by James Antill
Modified: 2007-11-30 17:12 EST (History)
0 users

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2007-05-22 06:13:43 EDT
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)
Tarball of GCC miscompiling problem, just type make check (80.00 KB, application/octet-stream)
2007-05-21 20:07 EDT, James Antill
no flags Details

  None (edit)
Description James Antill 2007-05-21 20:07:43 EDT
Description of problem:
 I've got some code that heavily uses inline, and GCC seems to be miscompiling
it at -O2 (-O1 works). Specifically this code (505 to 510 in ustr-main-code.h):

  printf("1. p=%p, osz=%zu, nsz=%zu\n", p, osz, nsz);
  if (p != NULL)
  {
    printf("2. p=%p, osz=%zu, nsz=%zu\n", p, osz, nsz);
    ret = USTR_CONF_POOL_REALLOC(p, *ps1, osz, nsz);
  }

...produces the following:

1. p=(nil), osz=8, nsz=256
2. p=(nil), osz=8, nsz=256
/bin/sh: line 3: 14360 Segmentation fault      ./$tst

...the last line because p isn't supposed to be NULL after there, and the code
doesn't handle it.

Version-Release number of selected component (if applicable):
% rpm -q gcc
gcc(0:4.1.1-51.fc6).i386

How reproducible:
 Always.

Steps to Reproduce:
1. grab: http://illiter.at/gcc-test-ustr.tar (attached)
2. untar
3. make check

Additional info:
 Again, note that compiling with -O1 works.
 Also if I change the #if on line 36 of ustr-fmt-code.h to be 0, the problem
disappears ... even though that if branch isn't taken anyway.

 I'm not 100% sure that this is a problem in GCC, although everything I can test
heavily implies that.

 I've put the severity/priority up on the assumption that it is miscompiling the
code.

 I'll also attached the tarball of source.
Comment 1 James Antill 2007-05-21 20:07:43 EDT
Created attachment 155143 [details]
Tarball of GCC miscompiling problem, just type make check
Comment 2 Jakub Jelinek 2007-05-22 06:13:43 EDT
That's not a GCC bug, but documented behavior.
USTR_CONF_e_PROTO
int ustrp__rw_realloc(void *, struct Ustr **, int, size_t, size_t)
    USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A();
where USTR__COMPILE_ATTR_NONNULL_A() expands to __attribute__((nonnull)).
This means you say that the first and second arguments to the function
must be non-null.
`nonnull (ARG-INDEX, ...)'
     The `nonnull' attribute specifies that some function parameters
     should be non-null pointers.  For instance, the declaration:

          extern void *
          my_memcpy (void *dest, const void *src, size_t len)
                __attribute__((nonnull (1, 2)));

     causes the compiler to check that, in calls to `my_memcpy',
     arguments DEST and SRC are non-null.  If the compiler determines
     that a null pointer is passed in an argument slot marked as
     non-null, and the `-Wnonnull' option is enabled, a warning is
     issued.  The compiler may also choose to make optimizations based
     on the knowledge that certain function arguments will not be null.

     If no argument index list is given to the `nonnull' attribute, all
     pointer arguments are marked as non-null.  To illustrate, the
     following declaration is equivalent to the previous example:

          extern void *
          my_memcpy (void *dest, const void *src, size_t len)
                __attribute__((nonnull));

Especially note the 'The compiler may also choose'... sentence.
With -O2 the compiler chose to take advantage of that guarantee (in VRP pass
particularly), but at runtime you violated that promise.
Comment 3 James Antill 2007-05-22 09:31:37 EDT
int ustrp__rw_realloc(void *, struct Ustr **, int, size_t, size_t)
    USTR__COMPILE_ATTR_WARN_UNUSED_RET() USTR__COMPILE_ATTR_NONNULL_A();


...argghhh ... damn, I was looking for a screwup like that on the external
functions, for some reason I didn't think about the internal ones. Sorry, and
thanks Jackub.

Note You need to log in before you can comment on or make changes to this bug.