public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* koenig lookup in C++
@ 2000-08-15 17:27 Geoff Keating
  2000-08-16 10:07 ` Theodore Papadopoulo
  0 siblings, 1 reply; 12+ messages in thread
From: Geoff Keating @ 2000-08-15 17:27 UTC (permalink / raw)
  To: gcc; +Cc: jason, mark

After looking at the C standard, I think that
g++.old-deja/g++.ns/koenig7.C is legal C++, and so this patch must be
wrong:

2000-08-11  Theodore Papadopoulo <Theodore.Papadopoulo@sophia.inria.fr>

	* decl2.c (add_function): Reorganize.
	(arg_assoc): Do not consider function template decls.

A simplified verson of the test looks like this:

namespace N1 {
  struct A { };
  void f2(float) {}
  void g(void (*)(float)) {}
}

using N1::f2;
template <class T>
void f2(N1::A, T) {}

void g(void (*)(int)) {}

int main() {  
   g(f2); // Works?
}

I believe this should work, because the argument
types of the g(f2) function are:

void f2(float)
template <class T> void f2(N1::A, T)

both of these are function types.  For function types, the associated
namespaces are those associated with their parameter and return
types.  For the first function type, there are no associated
types as all the parameters/return values are fundamental types.  For
the second set of function types, namespace N1 is associated because
one of the parameters is of type N1::A, a structure type in N1, which
has N1 associated with it.

Thus g can be either the g in the default namespace or the g in N1;
and then the only one that matches is the g in N1, and the parameter
must be N1::f2.

Does this sound right?  I'm no C++ language lawyer, I just play one on
TV :-).  If so, I'd appreciate it if someone could either (a) revert
the patch, (b) fix it, or (c) mark the testcase as XFAIL.  Otherwise
the testcase is wrong, which should be easy enough to fix.

-- 
- Geoffrey Keating <geoffk@cygnus.com>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: koenig lookup in C++
  2000-08-15 17:27 koenig lookup in C++ Geoff Keating
@ 2000-08-16 10:07 ` Theodore Papadopoulo
  2000-08-16 10:33   ` Geoff Keating
  0 siblings, 1 reply; 12+ messages in thread
From: Theodore Papadopoulo @ 2000-08-16 10:07 UTC (permalink / raw)
  To: Geoff Keating; +Cc: gcc, jason, mark

> After looking at the C standard, I think that
> g++.old-deja/g++.ns/koenig7.C is legal C++, and so this patch must be
> wrong:
> 
> 2000-08-11  Theodore Papadopoulo <Theodore.Papadopoulo@sophia.inria.fr>
> 
> 	* decl2.c (add_function): Reorganize.
> 	(arg_assoc): Do not consider function template decls.
> 
> A simplified verson of the test looks like this:
> 
> namespace N1 {
>   struct A { };
>   void f2(float) {}
>   void g(void (*)(float)) {}
> }
> 
> using N1::f2;
> template <class T>
> void f2(N1::A, T) {}
> 
> void g(void (*)(int)) {}
> 
> int main() {  
>    g(f2); // Works?
> }
> 
> I believe this should work, because the argument
> types of the g(f2) function are:
> 
> void f2(float)
> template <class T> void f2(N1::A, T)
> 
> both of these are function types.  For function types, the associated
> namespaces are those associated with their parameter and return
> types.  For the first function type, there are no associated
> types as all the parameters/return values are fundamental types.  For
> the second set of function types, namespace N1 is associated because
> one of the parameters is of type N1::A, a structure type in N1, which
> has N1 associated with it.
> 
> Thus g can be either the g in the default namespace or the g in N1;
> and then the only one that matches is the g in N1, and the parameter
> must be N1::f2.
> 
> Does this sound right?  I'm no C++ language lawyer, I just play one on
> TV :-). 

Well, I'm not a C++ language lawyer either (just a poor user that 
sometimes needs to go and have a look to the standard :-) ).
But here I'm quite sure that it is the test case that is wrong:

  Your templated f2 function certainly cannot be associated with any g 
  function as it takes 2 parameters whereas all g functions expect as a 
  parameter a function with ONLY ONE argument.

Thus as proposed by Nathan and Kriang (but for a different reason),
the following patch should be applied.

Index: koenig7.C
===================================================================
RCS file: /cvs/gcc/egcs/gcc/testsuite/g++.old-deja/g++.ns/koenig7.C,v
retrieving revision 1.2
diff -c -3 -p -r1.2 koenig7.C
*** koenig7.C   1998/12/16 21:50:33     1.2
--- koenig7.C   2000/08/16 16:32:19
*************** void g(void (*)(int)) {}
*** 18,22 ****
  
  int main() {  
     g(&f1); // Works?
!    g(f2); // Works?
  }
--- 18,22 ----
  
  int main() {  
     g(&f1); // Works?
!    g(f2);  // ERROR - cannot convert
  }

Then, this being said I must say that I'm no longer so sure (I was 
when I created the patch, but cannot convince myself anymore) of why
only instanciated function templates must be used for Koenig lookup
(This is the hing Mark gave to me). The only line of reasonning that
supports this claim (that I can find) is that the template-name of the function template
might not be used as a function pointer thus the function
type rule in 3.4.2 cannot be used and instead the template-id rule
(also in 3.4.2) must be used (ie you should write g(f2<int>) instead of g(f2)).
Indeed, I'll hate if the compiler had a different behaviour for the two cases g(f2)
and g(f2<int>). Is this the right reasonning ?

Now the question is whether g(f2) (with f2 being a function template) should be allowed at
all? With the above reasonning, it seems to me that no, it should not 
so that we should add a message which:

	- should be an error when all the candidates are template functions names.
        - should be a warning when there is at least one regular 
          function f2.

Is this sounds right ?? If yes then I'll do a patch to issue 
a warning/error.

> If so, I'd appreciate it if someone could either (a) revert
> the patch, (b) fix it, or (c) mark the testcase as XFAIL.  Otherwise
> the testcase is wrong, which should be easy enough to fix.

Unfortunately, I cannot do much in this respect (just propose patches).
I think that the above explanations rules out (a) and (c) and pushes 
toward the stupid patch for the otherwise clause of your demand.

	Sorry to have created this (fake?) regression...

	Theo.

--------------------------------------------------------------------
Theodore Papadopoulo
Email: Theodore.Papadopoulo@sophia.inria.fr Tel: (33) 04 92 38 76 01
 --------------------------------------------------------------------


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: koenig lookup in C++
  2000-08-16 10:07 ` Theodore Papadopoulo
@ 2000-08-16 10:33   ` Geoff Keating
  2000-08-16 11:52     ` Theodore Papadopoulo
  2000-08-16 12:08     ` Jason Merrill
  0 siblings, 2 replies; 12+ messages in thread
From: Geoff Keating @ 2000-08-16 10:33 UTC (permalink / raw)
  To: Theodore.Papadopoulo; +Cc: gcc, jason, mark

> cc: gcc@gcc.gnu.org, jason@cygnus.com, mark@codesourcery.com
> Date: Wed, 16 Aug 2000 19:06:01 +0200
> From: Theodore Papadopoulo <Theodore.Papadopoulo@sophia.inria.fr>

> But here I'm quite sure that it is the test case that is wrong:
> 
>   Your templated f2 function certainly cannot be associated with any g 
>   function as it takes 2 parameters whereas all g functions expect as a 
>   parameter a function with ONLY ONE argument.

Consider this testcase:

namespace N1 {
  struct A { };
  void g(void (*)(A, A)) {}
}

template <class T>
void f2(N1::A, T) {}

void g(void (*)(int)) {}

int main() {  
   g(f2); // Works?
}

t.cc: In function `int main ()':
t.cc:12: no matches converting function `f2' to type `void (*) (int)'
t.cc:7: candidates are: template <class T> void f2 (N1::A, T)

Should it work?

-- 
- Geoffrey Keating <geoffk@cygnus.com>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: koenig lookup in C++
  2000-08-16 10:33   ` Geoff Keating
@ 2000-08-16 11:52     ` Theodore Papadopoulo
  2000-08-16 13:18       ` Jason Merrill
  2000-08-16 12:08     ` Jason Merrill
  1 sibling, 1 reply; 12+ messages in thread
From: Theodore Papadopoulo @ 2000-08-16 11:52 UTC (permalink / raw)
  To: Geoff Keating; +Cc: gcc, jason, mark

> Consider this testcase:
> 
> namespace N1 {
>   struct A { };
>   void g(void (*)(A, A)) {}
> }
> 
> template <class T>
> void f2(N1::A, T) {}
> 
> void g(void (*)(int)) {}
> 
> int main() {  
>    g(f2); // Works?
> }
> 
> t.cc: In function `int main ()':
> t.cc:12: no matches converting function `f2' to type `void (*) (int)'
> t.cc:7: candidates are: template <class T> void f2 (N1::A, T)
> 
> Should it work?

Well, as I said I'm not a langage lawyer...
I'm sure that if you write it:

namespace N1 {
  struct A { };
  void g(void (*)(A, A)) {}
}

template <class T>
void f2(N1::A, T) {}

void g(void (*)(int)) {}

int main() {  
   g(f2<N1::A>); // Works?  //  The change is here.
}

Then, it works. But then, if you write it as:

namespace N1 {
  struct A { };
  void g(void (*)(A, int)) {}  // Changed here
}

template <class T>
void f2(N1::A, T) {}

void g(void (*)(int)) {}

int main() {  
   g(f2<int>); // Works?	// And here.
}

then it should not because the template-id rule only adds the 
namespace into which f2 is defined (in this case ::) plus the namespaces of the 
template arguments (in this case int thus nothing).

So again the question is whether the syntax g(f2) is authorized by the standard ??

+ If yes (and 14.8.2.2 and 13.4 seems to imply that the answer might be yes), then
  some template deduction should happen and the patch must be fixed. But then, if you 
  consider f2 as a function-type and apply the corresponding lookup rule 
  then in the previous example g(f2) and g(f2<int>) would have 
  different behaviours (the first being authorized and not the 
  second even if the instantiation deduces T=int !!). 

  What is misleading is that template argument deduction is 
  certainly authorized for function call... 
  
+ If no I agree that the error message is rather misleading 
  which is why I proposed in my message to add a better one that states that there is 
  a syntax error in this case. But again, I might be wrong so I'd 
  prefer having an advice from someone more acquainted with the arcanes 
  of the C++ standard before going this way.

	Theo. 

--------------------------------------------------------------------
Theodore Papadopoulo
Email: Theodore.Papadopoulo@sophia.inria.fr Tel: (33) 04 92 38 76 01
 --------------------------------------------------------------------






^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: koenig lookup in C++
  2000-08-16 10:33   ` Geoff Keating
  2000-08-16 11:52     ` Theodore Papadopoulo
@ 2000-08-16 12:08     ` Jason Merrill
  2000-08-17  6:04       ` Theodore Papadopoulo
  2000-08-17  6:06       ` Nathan Sidwell
  1 sibling, 2 replies; 12+ messages in thread
From: Jason Merrill @ 2000-08-16 12:08 UTC (permalink / raw)
  To: Geoff Keating; +Cc: Theodore.Papadopoulo, gcc, mark, jason

The standard doesn't seem to say anything about the case of an overloaded
function, much less templates.  It seems to me that either we should not
process any of the overloaded functions, or we should process all of them,
and handle non-dependent parts of the signature of a function template the
same way.

The latter seems more useful.

Jason

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: koenig lookup in C++
  2000-08-16 11:52     ` Theodore Papadopoulo
@ 2000-08-16 13:18       ` Jason Merrill
  0 siblings, 0 replies; 12+ messages in thread
From: Jason Merrill @ 2000-08-16 13:18 UTC (permalink / raw)
  To: Theodore Papadopoulo; +Cc: Geoff Keating, gcc, mark

>>>>> Theodore Papadopoulo <Theodore.Papadopoulo@sophia.inria.fr> writes:

 >   What is misleading is that template argument deduction is 
 >   certainly authorized for function call... 

Except that lookup happens before deduction.

Jason

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: koenig lookup in C++
  2000-08-16 12:08     ` Jason Merrill
@ 2000-08-17  6:04       ` Theodore Papadopoulo
  2000-08-17 11:49         ` Geoff Keating
  2000-08-17 14:13         ` Jason Merrill
  2000-08-17  6:06       ` Nathan Sidwell
  1 sibling, 2 replies; 12+ messages in thread
From: Theodore Papadopoulo @ 2000-08-17  6:04 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Geoff Keating, gcc, mark, jason

jason@redhat.com said:
> The standard doesn't seem to say anything about the case of an
> overloaded function, much less templates.  It seems to me that either
> we should not process any of the overloaded functions, or we should
> process all of them, and handle non-dependent parts of the signature
> of a function template the same way.
> The latter seems more useful. 

Then, maybe the first version of the patch I submitted is better even 
if frankly I'm not so sure whether it fulfills all the requirements 
you mention (but it should). The reference of the patch is:
http://gcc.gnu.org/ml/gcc-patches/2000-06/msg00781.html
Mark's comments for this patch are in:
http://gcc.gnu.org/ml/gcc-patches/2000-06/msg00836.html

Should we submit this problem to comp.std.c++ to get some consensus ???
There has been a thread somewhat related to this problem but I have not seen a 
definitive answer:
http://www.deja.com/[ST_rn=ps]/viewthread.xp?AN=648296191&search=thread&recnum=%3c3975935e@news.isb.net%3e%231/1&group=comp.std.c%2b%2b&frpage=viewthread.xp

The only thing that I would like to ensure is that taking the address of 
a function (given its prototype as in the koenig7.C case or by 
affecting it to a variable of the proper type) or calling a
function leads to the same behaviour from the compiler (ie selects 
the same function). 

One easy way to achieve this would be to consider 
a fake call to the overloaded templated function f2 with parameters of 
the type specified in the function's prototype (the type of the parameter
of g taking Geoff example's notations) and to add the namespace of the selected
function. Since the function f2 is supposed to be called by the g function, 
that would lead to the most sensible behavior. I wonder whether this
is exactly equivalent to your proposal....

jason@redhat.com said:
>>   What is misleading is that template argument deduction is 
>>   certainly authorized for function call... 

> Except that lookup happens before deduction. 

Oups, I was not aware of that... 
The fake function call proposal above in effect seem to mix lookup 
and deduction as template argument deduction can be made for function
parameters during the lookup. But again, it might be a complex way to do
exactly what your proposal already achieves...

	Theo.

--------------------------------------------------------------------
Theodore Papadopoulo
Email: Theodore.Papadopoulo@sophia.inria.fr Tel: (33) 04 92 38 76 01
 --------------------------------------------------------------------


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: koenig lookup in C++
  2000-08-16 12:08     ` Jason Merrill
  2000-08-17  6:04       ` Theodore Papadopoulo
@ 2000-08-17  6:06       ` Nathan Sidwell
  1 sibling, 0 replies; 12+ messages in thread
From: Nathan Sidwell @ 2000-08-17  6:06 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Geoff Keating, Theodore.Papadopoulo, gcc, mark, jason

Jason Merrill wrote:
> 
> The standard doesn't seem to say anything about the case of an overloaded
> function, much less templates.  It seems to me that either we should not
> process any of the overloaded functions, or we should process all of them,
> and handle non-dependent parts of the signature of a function template the
> same way.
> 
> The latter seems more useful.
I agree

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

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: koenig lookup in C++
  2000-08-17  6:04       ` Theodore Papadopoulo
@ 2000-08-17 11:49         ` Geoff Keating
  2000-08-17 14:13         ` Jason Merrill
  1 sibling, 0 replies; 12+ messages in thread
From: Geoff Keating @ 2000-08-17 11:49 UTC (permalink / raw)
  To: Theodore.Papadopoulo; +Cc: jason, gcc, mark, jason

I actually have an alternative interpretation of the standard that I
think makes sense now.

We are talking about a function call

f(g)

where f and g are both overloaded functions.

[over.over] says that the particular overloaded function chosen as an
argument has to make sense in the context.  I think this context
includes both the types of the functions and the visibility of f.
I think that Koenig lookup happens based only on the actual function
types chosen for f and g, not for function types that were considered
in overload resolution.  

So I think the template-ness of one of the overloaded functions
considered is not particularly relevant.  I think all of the following
should produce an error:

==========
namespace N1 {
  struct A { };
  void f2(float) {}
  void g(void (*)(float)) {}
}

using N1::f2;
template <class T>
void f2(N1::A, T) {}

void g(void (*)(int)) {}

int main() {  
   g(f2);
}
==========
namespace N1 {
  struct A { };
  void f2(float) {}
  void g(void (*)(float)) {}
}

using N1::f2;
class T { };
void f2(N1::A, T) {}

void g(void (*)(int)) {}

int main() {  
   g(f2);
}
==========
namespace N1 {
  struct A { };
  void f2(float) {}
  void g(void (*)(float)) {}
}

using N1::f2;
void f2(N1::A) {}

void g(void (*)(int)) {}

int main() {  
   g(f2);
}
==========

You can easily turn these into tests which are required to not
produce an error, and which g++ does fail to compile, by adding some
other resolution of g(f2), like this:

==========
namespace N1 {
  struct A { };
  void f2(float) {}
  void f2(int) {}
  void g(void (*)(float)) {}
}

using N1::f2;
void f2(N1::A) {}

void g(void (*)(int)) {}

int main() {  
   g(f2);
}
==========

I'm still new to this, and would be very interested if anyone else
thinks this makes sense.

In the meantime, does anyone object to my changing the testcase so
that it expects an error?

-- 
- Geoffrey Keating <geoffk@cygnus.com>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: koenig lookup in C++
  2000-08-17  6:04       ` Theodore Papadopoulo
  2000-08-17 11:49         ` Geoff Keating
@ 2000-08-17 14:13         ` Jason Merrill
  2000-08-17 14:38           ` Mark Mitchell
  1 sibling, 1 reply; 12+ messages in thread
From: Jason Merrill @ 2000-08-17 14:13 UTC (permalink / raw)
  To: Theodore Papadopoulo; +Cc: Geoff Keating, gcc, mark, jason

>>>>> Theodore Papadopoulo <Theodore.Papadopoulo@sophia.inria.fr> writes:

 > Then, maybe the first version of the patch I submitted is better even 
 > if frankly I'm not so sure whether it fulfills all the requirements 
 > you mention (but it should). The reference of the patch is:
 > http://gcc.gnu.org/ml/gcc-patches/2000-06/msg00781.html
 > Mark's comments for this patch are in:
 > http://gcc.gnu.org/ml/gcc-patches/2000-06/msg00836.html

Indeed, I disagree with Mark's comments.  Mark, what was your rationale for
treating templates differently?

I also disagree with your earlier patch, however; we shouldn't look through
an implicit typename.

Jason

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: koenig lookup in C++
  2000-08-17 14:13         ` Jason Merrill
@ 2000-08-17 14:38           ` Mark Mitchell
  2000-08-17 16:06             ` Jason Merrill
  0 siblings, 1 reply; 12+ messages in thread
From: Mark Mitchell @ 2000-08-17 14:38 UTC (permalink / raw)
  To: jason; +Cc: Theodore.Papadopoulo, geoffk, gcc, jason

>>>>> "Jason" == Jason Merrill <jason@redhat.com> writes:

    Jason> http://gcc.gnu.org/ml/gcc-patches/2000-06/msg00836.html

    Jason> Indeed, I disagree with Mark's comments.  Mark, what was
    Jason> your rationale for treating templates differently?

Good question.  I can't reconstruct my thinking, and my words don't
make sense to me any more.

I have to admit that I haven't been following the current thread very
closely -- way too many other things on my plate, including some other
GCC issues.

Coincidentally, I just approved a patch from Nathan that I think just
handles TYPENAME_TYPE like TEMPLATE_TYPE_PARAM in arg_assoc_type -- in
particular, it adds no new associated namespaces.  That seems like the
right thing to me.  Or am I delusional again?

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: koenig lookup in C++
  2000-08-17 14:38           ` Mark Mitchell
@ 2000-08-17 16:06             ` Jason Merrill
  0 siblings, 0 replies; 12+ messages in thread
From: Jason Merrill @ 2000-08-17 16:06 UTC (permalink / raw)
  To: Mark Mitchell; +Cc: Theodore.Papadopoulo, geoffk, gcc

>>>>> Mark Mitchell <mark@codesourcery.com> writes:

 > Coincidentally, I just approved a patch from Nathan that I think just
 > handles TYPENAME_TYPE like TEMPLATE_TYPE_PARAM in arg_assoc_type -- in
 > particular, it adds no new associated namespaces.  That seems like the
 > right thing to me.  Or am I delusional again?

Works for me.

Jason

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2000-08-17 16:06 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-08-15 17:27 koenig lookup in C++ Geoff Keating
2000-08-16 10:07 ` Theodore Papadopoulo
2000-08-16 10:33   ` Geoff Keating
2000-08-16 11:52     ` Theodore Papadopoulo
2000-08-16 13:18       ` Jason Merrill
2000-08-16 12:08     ` Jason Merrill
2000-08-17  6:04       ` Theodore Papadopoulo
2000-08-17 11:49         ` Geoff Keating
2000-08-17 14:13         ` Jason Merrill
2000-08-17 14:38           ` Mark Mitchell
2000-08-17 16:06             ` Jason Merrill
2000-08-17  6:06       ` Nathan Sidwell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).