Bug 240819

Summary: GCC miscompiles heavily inlined code at -O2
Product: [Fedora] Fedora Reporter: James Antill <james.antill>
Component: gccAssignee: Jakub Jelinek <jakub>
Status: CLOSED NOTABUG QA Contact:
Severity: high Docs Contact:
Priority: high    
Version: 6   
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2007-05-22 10:13:43 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
Tarball of GCC miscompiling problem, just type make check none

Description James Antill 2007-05-22 00:07:43 UTC
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-22 00:07:43 UTC
Created attachment 155143 [details]
Tarball of GCC miscompiling problem, just type make check

Comment 2 Jakub Jelinek 2007-05-22 10:13:43 UTC
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 13:31:37 UTC
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.