This is the mail archive of the gcc-patches@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]

Re: Better document two-stage name lookup & template base classes, take 2


> > > I have the impression that we try to do it _all_ right already now.
> > > Should this be reworded thus?
>
> I *think* so.

OK, I changed that in the manual, too, then.


> This paragraph, which I know you didn't write, isn't as tight as it
> could be.  How about: [...]

I fixed it. And I _did_ write the paragraph, but in a patch a couple of weeks 
(months?) ago :-)

The patch I'll commit after bootstrapping is attached below.

Regarding this:

> I hadn't thought that we would get this case:
>
>   int f(int) { return 1; }
>   template <typename T> int g(T) { return f('a'); }
>   int f(char) { return 2; }
>   int main () {
>     return g(3);
>   }
>
> right, but it turns out that my implementation of this stuff gets this
> case right automatically.  (The point is that "f('a')" should call
> "f(int)", not "f(char)".)
>
>   void f(int);
>   template <typename T> void g(T) { f('a'); }
>   void f(char);
>   template void g(double);
>
> will, I think, result in a call to "f(char)", not "f(int)".  I hope to
> fix this at some point in the relatively near future, but it's somewhat
> tricky.

I think you're confused here. How can the instantiation context change the 
call to f? In both cases, the call to f is non-dependent, and should thus be 
to f(int). You're thinking of DR 197, I guess, but I'm pretty sure your 
implementation already does the right thing. Don't let this prevent you from 
double-checking, though.

W.

Index: ChangeLog
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ChangeLog,v
retrieving revision 2.593
diff -c -r2.593 ChangeLog
*** ChangeLog	22 Jul 2003 09:25:36 -0000	2.593
--- ChangeLog	22 Jul 2003 16:30:59 -0000
***************
*** 1,3 ****
--- 1,7 ----
+ 2003-07-22  Wolfgang Bangerth  <bangerth@dealii.org>
+ 
+ 	* doc/trouble.texi: Better document two-stage name lookup.
+ 
  2003-07-16  Nathan Sidwell  <nathan@codesourcery.com>
  
  	* c-common.c (handle_packed_attribute): Don't pack a struct via a
Index: cp/ChangeLog
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/ChangeLog,v
retrieving revision 1.3539
diff -c -r1.3539 ChangeLog
*** cp/ChangeLog	22 Jul 2003 09:53:23 -0000	1.3539
--- cp/ChangeLog	22 Jul 2003 16:30:59 -0000
***************
*** 1,3 ****
--- 1,8 ----
+ 2003-07-22  Wolfgang Bangerth  <bangerth@dealii.org>
+ 
+ 	* lex.c (unqualified_fn_lookup_error): Mention that the error
+ 	message needs to be kept in synch with the manual.
+ 
  2003-07-22  Nathan Sidwell  <nathan@codesourcery.com>
  
  	* cp-tree.h (enum cp_lvalue_kind): Add clk_packed.
Index: cp/lex.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/lex.c,v
retrieving revision 1.313
diff -c -r1.313 lex.c
*** cp/lex.c	19 Jul 2003 16:09:47 -0000	1.313
--- cp/lex.c	22 Jul 2003 16:30:59 -0000
***************
*** 708,715 ****
      {
        /* In a template, it is invalid to write "f()" or "f(3)" if no
  	 declaration of "f" is available.  Historically, G++ and most
! 	 other compilers accepted that usage; explain to the user what
! 	 is going wrong.  */
        pedwarn ("there are no arguments to `%D' that depend on a template "
  	       "parameter, so a declaration of `%D' must be available", 
  	       name, name);
--- 708,721 ----
      {
        /* In a template, it is invalid to write "f()" or "f(3)" if no
  	 declaration of "f" is available.  Historically, G++ and most
! 	 other compilers accepted that usage since they deferred all name
! 	 lookup until instantiation time rather than doing unqualified
! 	 name lookup at template definition time; explain to the user what 
! 	 is going wrong.
! 
! 	 Note that we have the exact wording of the following message in
! 	 the manual (trouble.texi, node "Name lookup"), so they need to
! 	 be kept in synch.  */
        pedwarn ("there are no arguments to `%D' that depend on a template "
  	       "parameter, so a declaration of `%D' must be available", 
  	       name, name);
Index: doc/trouble.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/trouble.texi,v
retrieving revision 1.15
diff -c -r1.15 trouble.texi
*** doc/trouble.texi	7 Feb 2003 23:12:03 -0000	1.15
--- doc/trouble.texi	22 Jul 2003 16:30:59 -0000
***************
*** 1,5 ****
  @c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
! @c 1999, 2000, 2001 Free Software Foundation, Inc.
  @c This is part of the GCC manual.
  @c For copying conditions, see the file gcc.texi.
  
--- 1,5 ----
  @c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
! @c 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
  @c This is part of the GCC manual.
  @c For copying conditions, see the file gcc.texi.
  
***************
*** 941,949 ****
  provided, even if after the declaration of @code{struct A}.
  
  This distinction between lookup of dependent and non-dependent names is
! called two-stage (or dependent) name lookup. G++ implements some
! features of it since version 3.4 and is moving towards full compliance
! with the standard.
  
  Two-stage name lookup sometimes leads to situations with behavior
  different from non-template codes. The most common is probably this:
--- 941,948 ----
  provided, even if after the declaration of @code{struct A}.
  
  This distinction between lookup of dependent and non-dependent names is
! called two-stage (or dependent) name lookup.  G++ implements it
! since version 3.4.
  
  Two-stage name lookup sometimes leads to situations with behavior
  different from non-template codes. The most common is probably this:
***************
*** 974,983 ****
  @code{Base<T>::i}. Alternatively, @code{Base<T>::i} might be brought
  into scope by a @code{using}-declaration.
  
! Note that some compilers get this wrong and accept above code without an
! error.  However, this is spurious, since they just don't implement
! two-stage name lookup correctly.  This includes G++ versions prior to
! 3.4.
  
  
  @node Temporaries
--- 973,1019 ----
  @code{Base<T>::i}. Alternatively, @code{Base<T>::i} might be brought
  into scope by a @code{using}-declaration.
  
! Another, similar example involves calling member functions of a base
! class: 
! 
! @example
!   template <typename T> struct Base {
!       int f();
!   };
! 
!   template <typename T> struct Derived : Base<T> {
!       int g() { return f(); };
!   };
! @end example
! 
! Again, the call to @code{f()} is not dependent on template arguments
! (there are no arguments that depend on the type @code{T}, and it is also
! not otherwise specified that the call should be in a dependent context).
! Thus a global declaration of such a function must be available, since
! the one in the base class is not visible until instantiation time.  The
! compiler will consequently produce the following error message:
! 
! @example
!   x.cc: In member function `int Derived<T>::g()':
!   x.cc:6: error: there are no arguments to `f' that depend on a template
!      parameter, so a declaration of `f' must be available
!   x.cc:6: error: (if you use `-fpermissive', G++ will accept your code, but
!      allowing the use of an undeclared name is deprecated)
! @end example
! 
! To make the code valid either use @code{this->f()}, or
! @code{Base<T>::f()}.  Using the @code{-fpermissive} flag will also let
! the compiler accept the code, by marking all function calls for which no
! declaration is visible at the time of definition of the template for
! later lookup at instantiation time, as if it were a dependent call.
! We do not recommend using @code{-fpermissive} to work around invalid
! code, and it will also only catch cases where functions in base classes
! are called, not where variables in base classes are used (as in the
! example above).
! 
! Note that some compilers (including G++ versions prior to 3.4) get these
! examples wrong and accept above code without an error.  Those compilers
! do not implement two-stage name lookup correctly.
  
  
  @node Temporaries


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