Created attachment 27847 [details] test case, C++ source The attached input file is culled from Chromium sources. Past versions of GCC do not complain about this and nor does Clang. Trunk G++ started giving a warning fairly recently (sometime after I left for Prague). It happens with no special options, and also with -std=gnu++98; I didn't test other modes. foo.cc:3:35: warning: invalid use of incomplete type ‘class scoped_ptr<C>’ [enabled by default] private: struct RValue : public scoped_ptr { RValue(); ~RValue(); RValue(cons ^ foo.cc:2:7: warning: declaration of ‘class scoped_ptr<C>’ [enabled by default] class scoped_ptr { ^ This code pattern comes from using the macro MOVE_ONLY_TYPE_FOR_CPP_03 as defined here: http://src.chromium.org/viewvc/chrome/trunk/src/base/move.h?view=markup Is this code really invalid C++? If so, was it intended to start rejecting it without any new -std= or -Wfoo options when G++ never did before?
Your example can be reduced to the following model code: template<typename T> struct A { struct B : A { }; }; I can assure you that you cannot rely on that. This example has recently been raised to the committee and it was not 100% clear what the result should be. A new core language issue will be opened for this. The problem is that some arguments were brought pointing to the equivalent example struct A { struct B : A { }; }; being invalid since ages. There is no tendency to make the latter valid, but is has to be clarified what the state of the first (your) example will be.
The code is IMHO invalid, and apparently EDG compilers reject it. [class.derived] says "The type denoted by a base-type-specifier shall be a class type that is not an incompletely defined class (Clause 9)" and scoped_ptr is not complete until the end of its definition. Jason asked about exactly this situation on the c++ core reflector 3 days ago, so I assume he changed it intentionally, or at least is aware of it. You can make the code portable (whatever the resolution of the core issue) by moving the definition of scoped_ptr::Rvalue to a point where scoped_ptr is complete: template<class C> struct scoped_ptr { struct RValue; // declare }; // define template<class C> struct scoped_ptr<C>::Rvalue : scoped_ptr<C> { };
Yes, it was intentional, based on the discussion mentioned in the other comments. I made it a pedwarn rather than a hard error so that affected code would continue to compile.
Let's close this then.