Bug List: (This bug is not in your last search results)   Show last search results      Search page      Enter new bug
Bug#: 35200
Product:  
Component:  
Status: RESOLVED
Resolution: INVALID
Assigned To: Not yet assigned to anyone <unassigned@gcc.gnu.org>
Host:
Reported against  
Priority:  
Severity:  
Target Milestone:  
 
 
Target:
Reporter: H.J. Lu <hjl.tools@gmail.com>
Add CC:
CC:
Remove selected CCs
Build:
URL:
Summary:
Keywords:
Known to work:
Known to fail:

Attachment Description Type Created Size Actions
x.i.bz2 A testcase application/octet-stream 2008-02-14 19:52 58.14 KB Edit
Create a New Attachment (proposed patch, testcase, etc.) View All

Bug 35200 depends on: Show dependency tree
Show dependency graph
Bug 35200 blocks:

Additional Comments:






View Bug Activity   |   Format For Printing   |   Clone This Bug


Description:   Last confirmed: Opened: 2008-02-14 19:50
Gcc 4.3 revision 132310 gives bogus error when compiling binutils
on Linux/ia32:

[hjl@gnu-25 gas]$ /usr/gcc-4.3/bin/gcc -O2 x.i -S -Wall
x.c: In function ‘operand_type_match’:
x.c:1025: warning: likely type-punning may break strict-aliasing rules: object
‘*{unknown}’ of main type ‘unsigned int’ is referenced at or around x.c:1025
and may be aliased to object ‘{unknown}’ of main type ‘unsigned char:1’ which
is referenced at or around x.c:1025.
....

This error is very sensitive to gcc revision as well as the input.
If I remove a blank line in the source, I won't see the error. It is
also OK if I compile it on Linux/Intel64 with -m32.

------- Comment #1 From H.J. Lu 2008-02-14 19:52 -------
Created an attachment (id=15152) [edit]
A testcase

------- Comment #2 From Andrew Pinski 2008-02-14 19:57 -------
Hmmmm, I think this might be a valid warning.

------- Comment #3 From Andrew Pinski 2008-02-14 20:00 -------
Oh there is an union here.

------- Comment #4 From H.J. Lu 2008-02-14 20:16 -------
The first time we saw it is last Nov. But it is very hard to reproduce.
Any changes in input will make the warning to disappear. Here is what
Xuepeng got

The warning are caused by SSA and type-punning:

[hjl@gnu-25 gas]$ cat foo.c
typedef union i386_operand_type
{
  struct
    {
      unsigned int reg8:1;
    } bitfield;
  unsigned int array[1];
} i386_operand_type;

extern void f(int *p)
{
  *p = 100;
}

int main()
{
  i386_operand_type t;

  t.bitfield.reg8 = 1;

  f(&t.array[1]);

  return 0;
}
[hjl@gnu-25 gas]$ /usr/gcc-4.3/bin/gcc -O2 foo.c -S -Wall
foo.c: In function ‘main’:
foo.c:21: warning: pointer targets in passing argument 1 of ‘f’ differ in
signedness
foo.c:21: warning: likely type-punning may break strict-aliasing rules: object
‘*{unknown}’ of main type ‘int’ is referenced at or around foo.c:12 and may be
aliased to object ‘{unknown}’ of main type ‘unsigned char:1’ which is
referenced at or around foo.c:21.
[hjl@gnu-25 gas]$ 

It's not the exactly extracted case. But it's enough to
explain the bug698. The SSA and function-inline bring about this bug. If using
-fdump-tree-salias we can get .salias file for the exacted case in which you
can see that compiler will generate a STRUCTURE-FIELD-TAG tree node for each
field of union t, like below:

;;Function main(main)

structure field tag SFT.13 created for var t offset 33 size 31
structrue field tag SFT.14 created for var t offset 32 size 32
structrue field tag SFT.15 created for var t offset 32 size 1
...................
structrue field tag SFT.47 created for var t offset 0 size 32
structrue field tag SFT.48 created for var t offset 0 size 1

Here we can treat the SFT.x as a pointer that points to the field of t. So the
SFT.13 is a pointer that points to t.bitfield.unused whose offset is 33 and
size is 31 and main type is assumed as "unsigned int:31", SFT.14 is a pointer
that points to t.array[1] whose offset is 32 and size is 32 and main type is
int, SFT.15 points t.bitfield.regmem whose offset is 32 and size is 1 and main
type is assumed as "unsigned char:1".

Because of -O2, the function main will inline the function f, the final codes
look like below:

main()
{
  union i386_operand_type t;
  int i;
  int *D.1586;
<bb 2>:
  t.bitfield.reg8 = 1;
  D.1586_1 = (int *)&t.array;
  i_6 = *D.1586_1;
  return i_6;
}

D.1586_1 is a pointer in SSA form that points to t.array and will be used in
the next line. So according to strict aliasing rules, D.1586_1 will be conflict
with SFT.13~SFT.48 because their main types are different(except SFT.14 and
SFT.47)but point to the same memory area union t. The number of warnings equals
to the number of SFT.

In tc-i386.c, function uints_equal has statements:
....
case 2:
 if(x[1]!=y[1])
return 0;
......

function  update_imm has statements:
........
if((....&&!UINTS_EQUAL(overlap, imm8) &&...))
....

and function md_assemble calls function finalize_imm, and finalize_imme calls
update_imm, update_imm calls uints_equal. The optimization of function-inline
will get final statements(in ssa form) like below:

structure field tag SFT.10215 created for var imm8 offset 33 size 31
............

<L168>:;
  ...
  D.29407_741 = &imm8.array[1];
  D.29408_742 = *D.29407_741
  ...

So the ssa variable D.29407_741 is conflict with SFT.10215(and others)
according to the strict-aliasing rules. And please notice that without the
using in the next line, without this warning.

You may be wonder that why I am sure about my conclusion. That because there is
only one place in gcc source files to generate this warning, function
strict_aliasing_warn(tree alias_site, tree object1, bool is_ptr1, tree object2,
bool is_ptr2, bool filter_artificials) in tree-ssa-alias-warnings.c. I have
debuged into this function and investigated the object1 and object2. So it
does.

If you modified the file tc-i386.c, the compiler will not inline some specific
functions based on the inline strategy and at last you won't get code like
above and warnings. That's why I have said it's "unstable".

------- Comment #5 From Andrew Pinski 2008-02-14 20:21 -------
Can you when you debug the function, please dump the VOPs also since then it
should become obvious the issue.

Anyways I don't think this an bogus warning and really I think this is a code
issue.

This is actually documented this way in fact unions cannot be used this way.

That is you cannot do:

float f(int a)
{
  union {
  int i[1];
  float f[1];
  } g;

  int *d = g.i;
  float *f = g.f;
  *d = a;
  return *f;
}

-- Pinski

------- Comment #6 From H.J. Lu 2008-02-14 20:54 -------
(In reply to comment #5)
> Can you when you debug the function, please dump the VOPs also since then it
> should become obvious the issue.
> 
> Anyways I don't think this an bogus warning and really I think this is a code
> issue.
> 
> This is actually documented this way in fact unions cannot be used this way.
> 
> That is you cannot do:
> 
> float f(int a)
> {
>   union {
>   int i[1];
>   float f[1];
>   } g;
> 
>   int *d = g.i;
>   float *f = g.f;
>   *d = a;
>   return *f;
> }
> 
> -- Pinski
> 

Where is this documented in ISO C?

------- Comment #7 From Richard Guenther 2008-02-14 21:19 -------
ISO C even disallows type-punning with unions (which is in fact a GNU
extension):

union { int i; float f } u;
u.i = 1;
return u.f;

invokes undefined behavior in ISO C.  You have to use memcpy and two different
memory objects like

int i = 1;
float f;
memcpy (&f, &i, 4);
return f;

to be portable and ISO C conformant.

------- Comment #8 From Richard Guenther 2008-02-14 21:23 -------
See 6.5/6 and /7

------- Comment #9 From pinskia@gmail.com 2008-02-14 22:09 -------
Subject: Re:  [4.3 Regression] bogus aliasing warning

On 14 Feb 2008 20:54:18 -0000, hjl dot tools at gmail dot com
<gcc-bugzilla@gcc.gnu.org> wrote:
>  Where is this documented in ISO C?

There is a Defect Report explicitly about this:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_236.htm

-- Pinski

------- Comment #10 From H.J. Lu 2008-02-14 22:56 -------
Binutils is fixed by

http://sourceware.org/ml/binutils/2008-02/msg00152.html

Bug List: (This bug is not in your last search results)   Show last search results      Search page      Enter new bug