Bug 38477 - [strict-aliasing] warning message contains compiler-generated symbols
Summary: [strict-aliasing] warning message contains compiler-generated symbols
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.4.0
: P3 normal
Target Milestone: 4.4.0
Assignee: Richard Biener
URL:
Keywords: diagnostic
Depends on: 38503 38826
Blocks:
  Show dependency treegraph
 
Reported: 2008-12-10 17:16 UTC by Dmitry G. Dyachenko
Modified: 2009-01-14 16:47 UTC (History)
5 users (show)

See Also:
Host: i686-pc-linux-gnu
Target: i686-pc-linux-gnu
Build: i686-pc-linux-gnu
Known to work:
Known to fail:
Last reconfirmed: 2009-01-12 14:25:54


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Dmitry G. Dyachenko 2008-12-10 17:16:04 UTC
[root@localhost gcc_err]# g++ -Wall -c -O3 test.cpp
test.cpp: In member function 'void
test::bar(std::_List_iterator<KeyPairPtr<int, int> >&)':
test.cpp:14: warning: dereferencing pointer '__x.13' does break
strict-aliasing rules
/usr/local/gcc_current/lib/gcc/i686-pc-linux-gnu/4.4.0/include/c++/bits/stl_tree.h:530:
note: initialized from here
test.cpp:14: warning: dereferencing pointer '__x.13' does break
strict-aliasing rules
/usr/local/gcc_current/lib/gcc/i686-pc-linux-gnu/4.4.0/include/c++/bits/stl_tree.h:530:
note: initialized from here

[root@localhost gcc_err]# g++ -v
Using built-in specs.
Target: i686-pc-linux-gnu
Configured with: ../gcc_current/configure
--prefix=/usr/local/gcc_current --enable-shared --enable-threads=posix
--enable-checking=release --enable-__cxa_atexit
--enable-version-specific-runtime-libs --enable-languages=c,c++ :
(reconfigured) ../gcc_current/configure
--prefix=/usr/local/gcc_current --enable-shared --enable-threads=posix
--enable-checking=release --enable-__cxa_atexit
--enable-version-specific-runtime-libs --enable-languages=c,c++
--no-create --no-recursion : (reconfigured) ../gcc_current/configure
--prefix=/usr/local/gcc_current --enable-shared --enable-threads=posix
--enable-checking=release --enable-__cxa_atexit
--enable-version-specific-runtime-libs --enable-languages=c,c++
--no-create --no-recursion : (reconfigured) ../gcc_current/configure
--prefix=/usr/local/gcc_current --enable-shared --enable-threads=posix
--enable-checking=release --enable-__cxa_atexit
--enable-version-specific-runtime-libs --enable-languages=c,c++
--no-create --no-recursion : (reconfigured) ../gcc_current/configure
--prefix=/usr/local/gcc_current --enable-shared --enable-threads=posix
--enable-checking=release --enable-__cxa_atexit
--enable-version-specific-runtime-libs --enable-languages=c,c++
--no-create --no-recursion : (reconfigured) ../gcc_current/configure
--prefix=/usr/local/gcc_current --enable-shared --enable-threads=posix
--enable-checking=release --enable-__cxa_atexit
--enable-version-specific-runtime-libs --enable-languages=c,c++
--no-create --no-recursion : (reconfigured) ../gcc_current/configure
--prefix=/usr/local/gcc_current --enable-shared --enable-threads=posix
--enable-checking=release --enable-__cxa_atexit
--enable-version-specific-runtime-libs --enable-languages=c,c++
--no-create --no-recursion : (reconfigured) ../gcc_current/configure
--prefix=/usr/local/gcc_current --enable-shared --enable-threads=posix
--enable-checking=release --enable-__cxa_atexit
--enable-version-specific-runtime-libs --enable-languages=c,c++
--no-create --no-recursion : (reconfigured) ../gcc_current/configure
--prefix=/usr/local/gcc_current --enable-shared --enable-threads=posix
--enable-checking=release --enable-__cxa_atexit
--enable-version-specific-runtime-libs --enable-languages=c,c++
--no-create --no-recursion : (reconfigured) ../gcc_current/configure
--prefix=/usr/local/gcc_current --enable-shared --enable-threads=posix
--enable-checking=release --enable-__cxa_atexit
--enable-version-specific-runtime-libs --enable-languages=c,c++
--no-create --no-recursion : (reconfigured) ../gcc_current/configure
--prefix=/usr/local/gcc_current --enable-shared --enable-threads=posix
--enable-checking=release --enable-__cxa_atexit
--enable-version-specific-runtime-libs --enable-languages=c,c++
--no-create --no-recursion
Thread model: posix
gcc version 4.4.0 20081210 (experimental) [trunk revision 142645] (GCC)

[root@localhost gcc_err]# uname -a
Linux localhost.localdomain 2.6.26.6-49.fc8 #1 SMP Fri Oct 17 15:59:36
EDT 2008 i686 i686 i386 GNU/Linux

[root@localhost gcc_err]# cat test.cpp
#include <set>
#include <list>

template<class Key, class Info>
class KeyPairPtr
{
public:
   typedef typename std::pair< const Key, Info > Pair;
   Pair *pair_ptr;
};

template<class Key, class Info>
bool operator <( const KeyPairPtr<Key, Info> &left, const
KeyPairPtr<Key, Info> &right ) {
   return left.pair_ptr < right.pair_ptr;
}

typedef KeyPairPtr<int,int> key_val;

class test
{
   test();
   void bar( std::list<key_val>::iterator &ci );

   std::set<key_val> foo;
};

void test::bar( std::list<key_val>::iterator &ci )
{
   test ctx;
   ctx.foo.insert( *ci );
}
Comment 1 Richard Biener 2008-12-10 17:37:13 UTC
Note that the reason the diagnostic happens is either a bug in libstdc++ or
the points-to solver or the TBAA pruning in the points-to solver.

In the end we access the object 'ctx' via a pointer of type
const struct _Rb_tree_node *.  So the question is if anywhere in 'ctx' there
is such a struct.

It seems to access the _M_t._M_impl._M_header field which is a _Rb_tree_node_base
but I cannot see a _Rb_tree_node object in it.  Instead _Rb_tree_node is derived
from _Rb_tree_node_base and adds a _M_value_field.  But accessing this via
this path in

        struct _Rb_tree_impl : public _Node_allocator
        {
          _Key_compare          _M_key_compare;
          _Rb_tree_node_base    _M_header;
          size_type             _M_node_count;

certainly violates aliasing rules.  I do not see what _Rb_tree_impl::_S_value
wants to access.  There seems to be nothing there?
Comment 2 Richard Biener 2008-12-10 17:44:54 UTC
The relevant path through the CFG is

  struct test ctx;

<bb 2>:
  # ctx_108 = VDEF <ctx_103(D)>
  # SMT.120_109 = VDEF <SMT.120_104(D)>
  # SMT.121_110 = VDEF <SMT.121_105(D)>
  # SMT.122_111 = VDEF <SMT.122_106(D)>
  # SMT.123_112 = VDEF <SMT.123_107(D)>
  __comp_ctor  (&ctx);
  # VUSE <SMT.121_110>
  D.10437_5 = ci_1(D)->_M_node;
  D.10438_6 = (struct _List_node *) D.10437_5;
  # VUSE <ctx_108>
  D.10494_9 = ctx.foo._M_t._M_impl._M_header._M_parent;
  __y_10 = (struct _Rb_tree_node *) D.10494_9;
  __y_12 = (struct _Rb_tree_node *) &ctx.foo._M_t._M_impl._M_header;
...

<bb 7>:
  # __y_21 = PHI <__y_56(6), __y_12(2)>
...

<bb 21>:
  D.10504_36 = &__y_21->D.9518;
...

...
<bb 23>:
  __x.13_77 = (const struct _Rb_tree_node *) D.10504_36;
  # VUSE <SMT.123_100>
  D.11044_78 = D.10438_6->_M_data.pair_ptr;
  # VUSE <SMT.122_96>
  D.11045_79 = __x.13_77->_M_value_field.pair_ptr;


(it's not clear to me what &__y_21->D.9518 accesses - this seems to be a
magic, anonymous thing.  The constraints tell me its at offset zero though.)
Comment 3 Paolo Carlini 2008-12-12 11:10:28 UTC
Can you explain in better detail which aliasing issues you are seeing in _Rb_tree_impl (per Comment #1)? At line 530 I cannot see anything obviously wrong: a pointer to the base is casted to the derived type (just a static cast) and then _M_value_field of the latter is accessed.
Comment 4 Richard Biener 2008-12-12 11:24:10 UTC
The access is
  ((const struct _Rb_tree_node *)
     &ctx.foo._M_t._M_impl._M_header.D.9518)->_M_value_field.pair_ptr

but _M_header is of type _Rb_tree_node_base (and is embedded in _M_impl).
 _Rb_tree_node_base does not have a _M_value_field member, so I do not see
that the memory that is accessed is really "there".  This "D.9518" thing
may somehow magically cover for it (but it's at offset zero of _M_header),
but certainly TBAA isn't aware that this is a legal access.

Of course I lack complete understanding of how the implementation details
of the rb tree are supposed to work.  So, if this is not a libstdc++
problem then it is a C++ FE problem.
Comment 5 Paolo Carlini 2008-12-12 11:39:34 UTC
Sorry, but I still do not understand: __x (a const _Rb_tree_node_base *) is casted to _Const_Link_type (a const _Rb_tree_node<_Val> *) before the access, then of course an _M_value_field esists. By the way, all these cast games are very, very old (I hope we are not uncovering one more aliasing issue in the HP/SGI code)...
Comment 6 Richard Biener 2008-12-12 11:44:14 UTC
But there is no space for _Rb_tree_node<_Val> in ctx.foo._M_t._M_impl.

        struct _Rb_tree_impl : public _Node_allocator
        {
          _Key_compare          _M_key_compare;
          _Rb_tree_node_base    _M_header;
          size_type             _M_node_count;

the _M_header member is of type _Rb_tree_node_base, so I don't see how you
can cast that to _Rb_tree_node<_Val> and expect the _M_value_field to magically
appear in memory.  At least this is what the alias analysis code complains
about and thus says this access accesses nothing (legally).

Now you can of course tell me that .D.9518 makes the difference, but this
difference is not communicated to the middle-end properly by the C++
frontend.
Comment 7 Paolo Carlini 2008-12-12 11:53:00 UTC
(In reply to comment #6)
> But there is no space for _Rb_tree_node<_Val> in ctx.foo._M_t._M_impl.
> 
>         struct _Rb_tree_impl : public _Node_allocator
>         {
>           _Key_compare          _M_key_compare;
>           _Rb_tree_node_base    _M_header;
>           size_type             _M_node_count;

This has nothing to do with the allocated nodes.

> 
> the _M_header member is of type _Rb_tree_node_base, so I don't see how you
> can cast that to _Rb_tree_node<_Val> and expect the _M_value_field to magically
> appear in memory.

Hey Richard, don't tell me it's the first time you see production code casting a pointer from base to derived and accessing a member existing only in the derived type. Indeed, the HP / SGI STL people did that, not the worse programmers in the world ;) Anyway, if you think this is something wrong from the aliasing specifications point of view, please point me to the relevant sections of the Standard, let's work this out, is going to be painful and risky, I'm afraid...
Comment 8 Richard Biener 2008-12-12 11:56:56 UTC
Heh, of course not - I have been doing this myself gazillions of times.  I am
just looking at this from the middle-end perspective where the middle-end
appears to see an _object_ ctx with a specific member layout.  If you then
access this with a different layout then you are doomed.

I have to dig into the trees coming from the FE in this case, but now I'm leaving
for a 2+ week vacation w/o internet access, so ... this has to wait.
Comment 9 Richard Biener 2008-12-12 12:09:02 UTC
Btw, if you want to dig yourself - the problem is that the alias set of
const struct _Rb_tree_node is not a subset of struct test.  So the access
of any part of an object of type struct test through a pointer of type
const struct _Rb_tree_node * invokes undefined behavior (from the middle-end
perspective).

See alias.c:record_component_aliases for how the relationship is built.
Comment 10 Benjamin Kosnik 2009-01-05 23:47:25 UTC
Hey y'all, if this isn't a libstdc++ issue can it be re-categorized to the gcc component?
Comment 11 Richard Biener 2009-01-06 19:45:37 UTC
I'm not sure it isn't.
Comment 12 Richard Biener 2009-01-12 14:25:54 UTC
This isn't really a warning from system headers:

test.cpp:14: warning: dereferencing pointer '__x.13' does break strict-aliasing rules

the location for the dereference is in test.cpp (if that is correct or not
is another issue).  There is at least a bug that we will emit the note: part
even if the warning was suppressed - I am going to fix that.

I can omit the warning for pointers that are declared in system headers
in addition to that.  Probably this is what is the better behavior - but
I cannot easily report the dereference location even if it is in a system
header but the pointer is _not_ from a system header -- which is probably
what would be wanted here.

So,

t.h:
#pragma GCC system_header

inline float deref_float (float *p) { return *p; }

t.C:
#include "t.h"

float transform(int i)
{
  return deref_float ((float *)&i);
}

_should_ emit a warning?  Even if it looks like

t.h: In function 'float transform(int)':
t.h:3: warning:  dereferencing pointer 'i.0' does break strict-aliasing rules
t.C:5: note: initialized from here

?

IMHO we want to warn unless _both_, the declaration and the dereference is
in a system header.
Comment 13 Pawel Sikora 2009-01-12 14:43:26 UTC
(In reply to comment #12)
> This isn't really a warning from system headers:
> 
> test.cpp:14: warning: dereferencing pointer '__x.13' does break strict-aliasing
> rules
> 
> the location for the dereference is in test.cpp (if that is correct or not
> is another issue).  There is at least a bug that we will emit the note: part
> even if the warning was suppressed - I am going to fix that.
> 
> I can omit the warning for pointers that are declared in system headers
> in addition to that.  Probably this is what is the better behavior - but
> I cannot easily report the dereference location even if it is in a system
> header but the pointer is _not_ from a system header -- which is probably
> what would be wanted here.
> 
> So,
> 
> t.h:
> #pragma GCC system_header
> 
> inline float deref_float (float *p) { return *p; }
> 
> t.C:
> #include "t.h"
> 
> float transform(int i)
> {
>   return deref_float ((float *)&i);
> }
> 
> _should_ emit a warning?  Even if it looks like
> 
> t.h: In function 'float transform(int)':
> t.h:3: warning:  dereferencing pointer 'i.0' does break strict-aliasing rules
> t.C:5: note: initialized from here
> 
> ?
> 
> IMHO we want to warn unless _both_, the declaration and the dereference is
> in a system header.
> 

this will be painfull for users, e.g. boost::optional uses so called
aligned_storage via mistic void*/casts/etc and now i'm getting these
warnings from boost-system-headers. in this way, the -isystem switch
is completely useless.
Comment 14 Richard Biener 2009-01-12 14:51:37 UTC
Ok, how about -Wstrict-aliasing=3 warning only if both the dereference and the
declaration are not from system-headers (this is then the default for -Wall)
and with -Wstrict-aliasing=2 (or =1) warn if either of them is not from
system-headers?
Comment 15 Richard Biener 2009-01-13 11:03:07 UTC
Smaller testcase for the possible libstdc++ / C++ FE issue, build with
-O2 -finline-functions -Wstrict-aliasing -Wsystem-headers

#include <set>

class test
{
  test();
  void bar(int ci);

  std::set<int> foo;
};

void test::bar(int ci )
{
  test ctx;
  ctx.foo.insert( ci );
}

/usr/include/c++/4.4/bits/stl_function.h: In member function ‘void test::bar(int)’:
/usr/include/c++/4.4/bits/stl_function.h:230: warning: dereferencing pointer ‘__x.13’ does break strict-aliasing rules
/usr/include/c++/4.4/bits/stl_tree.h:530: note: initialized from here
/usr/include/c++/4.4/bits/stl_function.h:230: warning: dereferencing pointer ‘__x.13’ does break strict-aliasing rules
/usr/include/c++/4.4/bits/stl_tree.h:530: note: initialized from here

I am now trying to investigate who is at fault.
Comment 16 Richard Biener 2009-01-13 12:14:43 UTC
There is only a conditional path through the program that violates aliasing rules,
likely never executed.  We do not detect this fact because of a points-to solver
issue, PR38826.
Comment 17 Richard Biener 2009-01-14 16:45:45 UTC
Subject: Bug 38477

Author: rguenth
Date: Wed Jan 14 16:45:22 2009
New Revision: 143374

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=143374
Log:
2009-01-14  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/38826
	PR middle-end/38477
	* tree-ssa-structalias.c (emit_alias_warning): Emit the pointer
	initialization notes only if we actually emitted a warning.
	(intra_create_variable_infos): Add constraints for a result decl
	that is passed by hidden reference.
	(build_pred_graph): Mark all related variables non-direct on
	address-taking.

	* gcc.dg/Wstrict-aliasing-bogus-pta-1.c: New testcase.

Added:
    trunk/gcc/testsuite/gcc.dg/Wstrict-aliasing-bogus-pta-1.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/tree-ssa-structalias.c

Comment 18 Richard Biener 2009-01-14 16:47:28 UTC
Fixed.