Consider the following: template <class T> T * foo (T * x) { return x++; } struct aclass; aclass * addone (aclass * x) { return foo<aclass>(x); } struct aclass { int x; }; At the point where foo<aclass> is instantiated, 'aclass' is incomplete, and 'x++' requires it to be complete, so this program is not well-formed, and a diagnostic is required.
Confirmed. I'm sure Giovanni has something to say about this. W.
I am not 100% sure about this. Geoff, why do you think GCC is wrong? FWIW EDG does exactly the same. Do you have a specific quote from the standard?
Subject: Re: g++ doesn't diagnose instantiation of template that uses incomplete type On 30/07/2004, at 5:25 PM, giovannibajo at libero dot it wrote: > > ------- Additional Comments From giovannibajo at libero dot it > 2004-07-31 00:25 ------- > I am not 100% sure about this. Geoff, why do you think GCC is wrong? > FWIW EDG > does exactly the same. Do you have a specific quote from the standard? Um, why do you think GCC is right? [expr.add] says in paragraph 1, "one operand shall be a pointer to a completely defined object type". [temp.inst], paragraph 2, says "the function template specialization is implicitly instantiated when the specialization is referenced in a context that requires a function definition to exist", which is at the point of the call to foo<aclass> in the original example. [temp.res] says in paragraph 8 "The lookup of names dependent on the template parameters is postponed until the actual template argument is known (14.6.2)" and 'until' in the standard is precise, it means lookup happens at that point, which here is also the point of the call. [temp.res] also says in paragraph 7 "if a template is instantiated, errors will be diagnosed according to the other rules in this Standard", although I think it's just trying to be helpful by clarifying the rest of the paragraph, which is mostly about how you don't have to have any diagnostics when a template isn't instantiated, and which makes it valid to write 'some_class<incomplete_type> *' even if some_class<incomplete_type> has 'incomplete_type' as a member. So at the point of the call, name lookup is complete, and errors are diagnosed according to the rest of the standard, including the rule in [expr.add].
Created attachment 6859 [details] smime.p7s
Here's the same thing with overloaded functions, causing a wrong-code error. If the last definition of 'bar' is commented out, the testcase passes, but otherwise not. template <class T> int func(T & x) { return bar (x); } int bar(const int & x) { return x; } extern "C" void abort (); int main (void) { int x = 3; if (func<int>(x) != 3) abort (); } int bar (int &x) { return x + 3; }
(In reply to comment #5) > Here's the same thing with overloaded functions, causing a wrong-code error. If the last definition of > 'bar' is commented out, the testcase passes, but otherwise not. That code is acutally invalid and really should have been rejected see PR 2922 for that.
(In reply to comment #6) > (In reply to comment #5) > > Here's the same thing with overloaded functions, causing a wrong-code error. If the last definition of > > 'bar' is commented out, the testcase passes, but otherwise not. > That code is acutally invalid and really should have been rejected see PR 2922 for that. Also if we move the template func after bar and main after the second bar, we get back to basicially PR 2922. So the first testcase is the only one which the problem for this bug.
Subject: Re: g++ instantiates templates at the wrong place On 22/06/2005, at 9:19 PM, pinskia at gcc dot gnu dot org wrote: > > ------- Additional Comments From pinskia at gcc dot gnu dot org > 2005-06-23 01:19 ------- > (In reply to comment #5) > >> Here's the same thing with overloaded functions, causing a wrong- >> code error. If the last definition of >> 'bar' is commented out, the testcase passes, but otherwise not. >> > That code is acutally invalid and really should have been rejected > see PR 2922 for that. Yes, apparently it should, following the discussion in DR 197. The following example, similar to the corrected one from DR 197, is a wrong-code: void f(char); template <class T> void g(T t) { f(T(1)); // dependent f(t); // dependent } enum E { e }; void h() { g(e); // calls f(char) twice } void f(E); // should make no difference because it calls f(E) twice rather than f(char).
Created attachment 9137 [details] smime.p7s
Here's another issue in this area. Is it the same, or a separate bug? This code is adapted from the example in DR197. #include <stdio.h> struct C1 {}; struct C2 : C1 { }; C1 c1; C2 c2; void f(C1); template <class T> void g(T t) { f(c2); // f(C1) should be the nearest match f(t); // dependent } void f(C2); int main() { g(c2); // will cause one call of f(C1) followed // by one calls of f(C2) g(c1); // will cause two calls of f(C1) } void f(C1) { printf ("C1\n");} void f(C2) { printf ("C2\n");} What actually happens (with the 4.1.1 I have anyway) is three calls to f(C2) followed by one call to f(C1). This shows that the *non-dependent* call is being resolved in the wrong scope also - it should not be able to see f(C2). If the prototype for f(C2) is removed, then the previously described problem is apparent also, and the (incorrect) behaviour of the program is unchanged.
*** Bug 35799 has been marked as a duplicate of this bug. ***
*** Bug 37225 has been marked as a duplicate of this bug. ***
*** Bug 38762 has been marked as a duplicate of this bug. ***
*** Bug 42292 has been marked as a duplicate of this bug. ***
I believe http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#993 will be resolved to allow the G++ behavior. Suspending.
(In reply to comment #15) > I believe http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#993 will > be resolved to allow the G++ behavior. Suspending. http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#993 so this is INVALID?
Yep.