This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Re: C++ bug 764
- To: Nathan Sidwell <nathan at codesourcery dot com>
- Subject: Re: C++ bug 764
- From: Martin Sebor <sebor at roguewave dot com>
- Date: Sat, 05 May 2001 16:59:43 -0600
- CC: gcc-bugs at gcc dot gnu dot org, mark at codesourcery dot com, jason at redhat dot com
- Organization: Rogue Wave Software, Inc.
- References: <3AF29153.935B582@codesourcery.com>
Nathan Sidwell wrote:
>
> Hi,
> In reexamining bug 764, I'm not convinced the code is well-formed.
Why wouldn't it be? The only fishy part is dereferencing the null pointer,
but I'm sure you see that is unrelated to the error. You can replace the
definition of p with an extern declaration and still reproduce the bug.
> (Martin, we may have corresponded on this, but I cannot find any of
> that email).
We only exchanged one other email on the subject (in addition to what's
already in GNATS). The email is attached.
Martin
>
> The code in question is this [note, that this is in a follow up, as the
> original bug report code wasn't what martin intended]
>
> template <class T>
> struct S
> {
> friend bool operator== (const S&, const S&) {
> return true;
> }
> };
>
> int main ()
> {
> // S<int> s;
>
> const S<int> *p = 0;
> *p == *p; // error
> }
>
> g++ says,
>
> test.cpp: In function `int main()':
> test.cpp:33: no match for `const S<int> & == const S<int> &'
>
> S<T>::operator== declares an ordinary non-template function. See 14.5.3/1
> last bullet, and in the example is is 'process'. Each specialization of
> S<T> gets an appropriate non-template operator== as a friend. Does the
> declaration of that function exist before the instantiation of the
> corresponding S<T>? As you'll see from the above code, nothing before
> the *p == *p requires the instantiation of S<int>. Uncommenting the
> declaration of s above will instantiate S<int> and remove the error.
>
> 11.4/5 gives the non-template case, and the friend function declaration
> exists (in the enclosing namespace scope), at the end of the class
> definition.
>
> 14.7.1 is also relevant and says that instantiation happens 'when the
> completeness of the class type affects the semantics of the program'.
> Well, it looks like it does here, but that sure seems weird. We'd have
> to instantiate templates which declared such friend functions earlier
> than we do.
>
> nathan
> --
> Dr Nathan Sidwell :: http://www.codesourcery.com :: CodeSourcery LLC
> 'But that's a lie.' - 'Yes it is. What's your point?'
> nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org
- To: Nathan Sidwell <nathan at codesourcery dot com>
- Subject: Re: PR 764
- From: Martin Sebor <sebor at roguewave dot com>
- Date: Fri, 17 Nov 2000 12:10:14 -0700
- CC: gcc-bugs at gcc dot gnu dot org
- Organization: Rogue Wave Software, Inc.
- References: <3A150D3D.8A646184@codesourcery.com>
Nathan Sidwell wrote:
>
> Hi,
> this is about C++ bug 764. The attached test case (derived from
> Martin's second test case) produces the following diagnostics,
>
> nathan@uha:21>./g++ -B ./ -c current/764-3.ii
> current/764-3.ii:4: warning: friend declaration `bool operator==(const
> S<T>&,
> const S<T>&)' declares a non-template function
> current/764-3.ii:4: warning: (if this is not what you intended, make
> sure the
> function template has already been declared and add <> after the
> function
> name here) -Wno-non-template-friend disables this warning.
> current/764-3.ii: In function `void foo(S<int>*)':
> current/764-3.ii:12: no match for `S<int>& == S<int>&' operator
> current/764-3.ii: In function `void baz(S<float>*)':
> current/764-3.ii:16: no match for `S<float>& != S<float>&' operator
> current/764-3.ii:6: candidates are: bool operator!=(const S<int>&, const
>
> There's clearly some kind of bug here, something about foo causes S<int>
> to be instantiated, but too late to find a match for operator==
>
> I don't understand is why we issue a warning for the declaration
> of S<T>::operator==, but not for the definition of S<T>::operator!=.
>
> The relevant bit of the std is 14.5.3, that lists what sort of thing a
> friend declaration is. In this case it's neither a template-id nor a
> qualified id, therefore the last choice is,
> the name shall be an unqualified id that declares an ordinary
> (non-template) function
> but here we've used the template type as parameters, so it's templatized
> on something. Shouldn't we issue an error here in both cases?
I don't believe there is an error in the derived testcase. The operators
are, as you said, ordinary functions. They just happen to be defined in
the body of the template which is allowed in 11.4, p5.
The fact that they take S<T> as an argument means that there is exactly
one ordinary function for each specialization of S<T> and that function
is a friend of the respective specialization (this is analogous to the
::process (task<T>*) function in the example in 14.5.3).
There's no other way to express such a relationship and there's nothing
that outlaws the syntax. The friend could be defined outside of the
template but since it's an ordinary function it would have to be defined
separately for each specialization of S<T>.
As for the warning, I believe that while it may be useful to novices it
shouldn't be issued unless explicitly requested (e.g., as a remark).
Even then I'm not sure it's the best idea for a compiler to give
"helpful" hints on how to "improve" one's code, especially if the code
is perfectly correct.
Regards
Martin
>
> nathan
>
> --
> Dr Nathan Sidwell :: http://www.codesourcery.com :: CodeSourcery
> LLC
> 'But that's a lie.' - 'Yes it is. What's your point?'
> nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ :
> nathan@acm.org
>
> ------------------------------------------------------------------------
>
> 764-3.iiName: 764-3.ii
> Type: ASCII text file (text/plain)