This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: gcc 2.95.1 can't compile correnct code (SUN's CC can)



Martin,

thanks for the detailed explanation. Especially the reference to the standard 
is very valuable, if the goal is portable code.

Thanks.

--Rainer.

> > Thanks for the clarification. Is this a limitation of C++ template concept:
> 
> It's not a limitation of the C++ templates, but rather a side effect
> of the list template.
> 
> > If I would implement the list myself (non-templete, something like
> > list_b), I wouldn't need a complete type of b, because my list
> > implementation would contain only pointers to b, because it has no
> > instance of b when the constructor is called.
> 
> g++ is quite specific about the actual cause. You write
> 
>   a(){}
> 
> This is the default constructor; it invokes the default constructors
> for all members, in particular:
> 
>   explicit list(const allocator_type& __a = allocator_type()) : _Base(__a) {}
> 
> When this template is instantiated and invoked, it in turn
> instantiates the base class (of std::list, which is internal):
> 
>   _List_base(const allocator_type& __a) : _Base(__a) {
>     _M_node = _M_get_node();
>     _M_node->_M_next = _M_node;
>     _M_node->_M_prev = _M_node;
>   }
> 
> This, in turn, invokes _M_get_node:
> 
>   _List_node<_Tp>* _M_get_node() { return _Alloc_type::allocate(1); }
> 
> This allocates one element:
> 
>     static _Tp* allocate(size_t __n)
>       { return 0 == __n ? 0 : (_Tp*) _Alloc::allocate(__n * sizeof (_Tp)); }
> 
> which in turns needs to find out the size of a list node, which is
> 
> template <class _Tp>
> struct _List_node {
>   typedef void* _Void_pointer;
>   _Void_pointer _M_next;
>   _Void_pointer _M_prev;
>   _Tp _M_data;
> };
> 
> which contains a member of type b (_M_data). Hence the error that you
> are using an incomplete type.
> 
> Now, I agree there are alternatives which would avoid this
> problem. Also, I withdraw my earlier claim that Sun CC should have
> detected that error. The effect of your code is explained in 17.4.3.6,
> [lib.res.on.functions]:
> 
> # 1 In certain cases (replacement functions, handler functions,
> # operations on types used to instantiate standard library template
> # components), the C++ Standard Library depends on components supplied
> # by a C++ pro­gram. If these components do not meet their
> # requirements, the Standard places no requirements on the
> # implementation.
> #
> # 2 In particular, the effects are undefined in the following cases:
> [...]
> # - if an incomplete type (3.9) is used as a template argument when
> # instantiating a template component.
> 
> So the effect of your program is undefined. It may compile on one
> compiler, and fail to compile on another. If it compiles, it may have
> the effect you want, or it may cause a power-outage in your city.
> 
> If you want to compile your program with g++, moving the constructor
> out-of-line will work around the problem:
> 
> #include<list>
> 
> using namespace std;
> 
> class b;
> 
> class a{
> public:
>   a();
>   list<b> c;
> };
> 
> class b{
> public:
>   b(){}
>   list<a> d;
> };
> 
> a::a(){}
> 
> int main(){
>   a x;
>   b y;
>   exit(0);
> }
> 
> Please note that this is code has still undefined behaviour; it just
> happens (by coincidence) that gcc 2.95 accepts it.
> 
> Hope this helps,
> Martin

-- 
Rainer Dorsch
Abt. Rechnerarchitektur  e-mail:rainer.dorsch@informatik.uni-stuttgart.de
Uni Stuttgart            Tel.: 0711-7816-215



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]