Bug 54055 - spurious(?) "invalid use of incomplete type" warning in template definition
Summary: spurious(?) "invalid use of incomplete type" warning in template definition
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.8.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-07-20 18:38 UTC by roland
Modified: 2012-07-22 11:27 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
test case, C++ source (805 bytes, application/octet-stream)
2012-07-20 18:38 UTC, roland
Details

Note You need to log in before you can comment on or make changes to this bug.
Description roland 2012-07-20 18:38:07 UTC
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?
Comment 1 Daniel Krügler 2012-07-20 19:18:03 UTC
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.
Comment 2 Jonathan Wakely 2012-07-20 19:26:28 UTC
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> {
};
Comment 3 Jason Merrill 2012-07-21 14:11:11 UTC
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.
Comment 4 Paolo Carlini 2012-07-22 11:27:20 UTC
Let's close this then.