This is the mail archive of the gcc-bugs@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]
Other format: [Raw text]

[Bug c++/14502] [3.3 Regression] g++ compile fails "no matching function" using forward declaration of class involving inheritance


------- Additional Comments From bangerth at dealii dot org  2004-03-10 22:42 -------
This is actually an interesting problem, and I'm not at all convinced 
that we do the right thing. Here's a redux: 
----------------- 
template <class T> struct B {}; 
 
template <class T> void bar () 
{ B<T> *p = (T*)0; } 
 
struct D; 
 
int foo()  { bar<D>(); }; 
 
struct D : public B<D> {}; 
 
int i = foo(); 
--------------------- 
Now, 3.2.3 compiles this as do 3.4 and mainline, but 3.3.4 doesn't. My 
grapples with this are: when we see foo(), we realize that this is not 
a template, so we should expand its body. At this time, D is only 
forward declared, so when we instantiate bar<D> we realize that we are 
asked to convert a D* to a B<D>* in the assignment. 3.3.x tells us 
 
g/x> /home/bangerth/bin/gcc-3.3*/bin/c++ -c x.cc 
x.cc: In function `void bar() [with T = D]': 
x.cc:8:   instantiated from here 
x.cc:4: error: cannot convert `D*' to `B<D>*' in initialization 
 
I believe this is a sensible error message, since at the time of instantiation 
of bar<D>, we are unaware of the fact that D is actually derived from B<D> 
and that therefore a D* _can_ be converted into a B<D>*. 
 
So apparently the confusion all comes from the fact that 3.3 tries to 
expand the body of foo() when it sees the function definition, while all 
other versions of the compiler only try to do so when this function is 
actually used or at the end of the compilation unit. This is supported by 
the fact that if we remove the last definition of D and of the variable i 
from the file, then suddenly also the other compilers get into trouble. 
 
So, in my view 3.3 is actually the only version that gets it right, i.e. 
expands the body of the function at the point of its definition; we probably 
all agree that this is the sensible thing to do for non-templates. All other 
versions defer expansion of the body of bar() until the end of the translation 
unit, at which point the definition of D is already known. In other words, 
we would have an accepts-invalid in 3.2.3, 3.4 and mainline (and thus a 
regression), not a rejects-valid in 3.3. 
 
Does this all sound sensible? 
 
W. 

-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14502


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