public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* C++ PATCH: PR 2922
@ 2005-05-28 23:57 Douglas Gregor
  0 siblings, 0 replies; only message in thread
From: Douglas Gregor @ 2005-05-28 23:57 UTC (permalink / raw)
  To: gcc-patches, gcc

[-- Attachment #1: Type: text/plain, Size: 1866 bytes --]

Hello,

This amusingly small patch fixes PR 2922 (two-stage lookup for unqualified 
function calls with type-dependent arguments). We need only keep the set of 
functions we found in the first stage, and it will be augmented by those 
functions found using argument-dependent lookup at the second stage. Also, we 
explicitly deal with DR 164 by not optimizing away checks for functions found 
via ADL in the namespace of the template.

Note that this only fixes two-stage lookup for function names. Operations are 
still handled improperly. I've reported PR c++/21802 that illustrates this 
problem. The testcase from that PR is included in this testsuite patch.

Tested i686-pc-linux-gnu. No new regressions on the g++ or libstdc++ test 
suites. The new tests (from PR 2922) pass; the new one from PR 21802 is 
XFAIL'd; some tests needed tweaking because error-messages changed or the 
test should not have been passing in the first place.

Okay for mainline? 

 Doug Gregor

2005-05-28  Douglas Gregor <doug.gregor@gmail.com>

 PR c++/2922
 * semantics.c (perform_koenig_lookup): For dependent calls, just
 return the set of functions we've found so far. Later, it will be
 augmented by those found through argument-dependent lookup.
 * name-lookup.c (lookup_arg_dependent): 

2005-05-28  Douglas Gregor <doug.gregor@gmail.com>

 PR c++/2922
 * g++.dg/lookup/two-stage2.C: New.
 * g++.dg/lookup/two-stage3.C: New.
 * g++.dg/lookup/two-stage4.C: New. Illustrates how we have not yet
 fixed two-stage name lookup for operators.
 * g++.dg/template/call3.C: Compiler now produces an appropriate
 error message. 
 * g++.dg/template/crash37.C: Compiler now describes bla() on line
 14 as a candidate. 
 * g++.dg/template/ptrmem4.C: Compiler produces different error
 message.
 * g++.old-deja/g++.other/pmf3.C: Compiler now describes
 connect_to_method as a candidate.
 

[-- Attachment #2: 2922-cp.patch --]
[-- Type: text/x-diff, Size: 3017 bytes --]

Index: name-lookup.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/name-lookup.c,v
retrieving revision 1.120
diff -c -3 -p -r1.120 name-lookup.c
*** name-lookup.c	25 May 2005 04:17:36 -0000	1.120
--- name-lookup.c	28 May 2005 19:57:48 -0000
*************** tree
*** 4452,4485 ****
  lookup_arg_dependent (tree name, tree fns, tree args)
  {
    struct arg_lookup k;
-   tree fn = NULL_TREE;
  
    timevar_push (TV_NAME_LOOKUP);
    k.name = name;
    k.functions = fns;
    k.classes = NULL_TREE;
  
!   /* We've already looked at some namespaces during normal unqualified
!      lookup -- but we don't know exactly which ones.  If the functions
!      we found were brought into the current namespace via a using
!      declaration, we have not really checked the namespace from which
!      they came.  Therefore, we check all namespaces here -- unless the
!      function we have is from the current namespace.  Even then, we
!      must check all namespaces if the function is a local
!      declaration; any other declarations present at namespace scope
!      should be visible during argument-dependent lookup.  */
!   if (fns)
!     fn = OVL_CURRENT (fns);
!   if (fn && TREE_CODE (fn) == FUNCTION_DECL 
!       && (CP_DECL_CONTEXT (fn) != current_decl_namespace ()
! 	  || DECL_LOCAL_FUNCTION_P (fn)))
!     k.namespaces = NULL_TREE;
!   else
!     /* Setting NAMESPACES is purely an optimization; it prevents
!        adding functions which are already in FNS.  Adding them would
!        be safe -- "joust" will eliminate the duplicates -- but
!        wasteful.  */
!     k.namespaces = build_tree_list (current_decl_namespace (), NULL_TREE);
  
    arg_assoc_args (&k, args);
    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, k.functions);
--- 4452,4469 ----
  lookup_arg_dependent (tree name, tree fns, tree args)
  {
    struct arg_lookup k;
  
    timevar_push (TV_NAME_LOOKUP);
    k.name = name;
    k.functions = fns;
    k.classes = NULL_TREE;
  
!   /* We previously performed an optimization here by setting
!      NAMESPACES to the current namespace when it was safe. However, DR
!      164 says that namespaces that were already searched in the first
!      stage of template processing are searched again (potentially
!      picking up later definitions) in the second stage. */
!   k.namespaces = NULL_TREE;
  
    arg_assoc_args (&k, args);
    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, k.functions);
Index: semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.473
diff -c -3 -p -r1.473 semantics.c
*** semantics.c	28 May 2005 01:38:11 -0000	1.473
--- semantics.c	28 May 2005 19:57:50 -0000
*************** perform_koenig_lookup (tree fn, tree arg
*** 1739,1746 ****
  	/* The unqualified name could not be resolved.  */
  	fn = unqualified_fn_lookup_error (identifier);
      }
-   else
-     fn = identifier;
  
    return fn;
  }
--- 1739,1744 ----

[-- Attachment #3: 2922-testsuite.patch --]
[-- Type: text/x-diff, Size: 5266 bytes --]

Index: g++.dg/lookup/two-stage2.C
===================================================================
RCS file: g++.dg/lookup/two-stage2.C
diff -N g++.dg/lookup/two-stage2.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- g++.dg/lookup/two-stage2.C	28 May 2005 19:58:08 -0000
***************
*** 0 ****
--- 1,19 ----
+ // { dg-do compile }
+ // PR c++/2922
+ 
+ char& f(char);
+ 
+ template<class T>
+ void g(T t)
+ {
+   char& c1 = f(1);        // not dependent
+   char& c2 = f(t);        // dependent
+ }
+ 
+ int&f (int);
+ 
+ int main()
+ {
+   g(2);    // f(char) followed by f(int)
+   g('a');  // two f(char)
+ }
Index: g++.dg/lookup/two-stage3.C
===================================================================
RCS file: g++.dg/lookup/two-stage3.C
diff -N g++.dg/lookup/two-stage3.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- g++.dg/lookup/two-stage3.C	28 May 2005 19:58:08 -0000
***************
*** 0 ****
--- 1,22 ----
+ // { dg-do compile }
+ // PR c++/2922
+ 
+ namespace tpl_ {
+ 
+ template<class T>
+ char test(T);
+ 
+ template<class T>
+ struct check
+ {
+     static T const t;
+     enum { value = 1 == sizeof(test(t)) };
+ };
+ 
+ double test(int);
+ 
+ }
+ 
+ bool const two_phase_lookup_supported = tpl_::check<int>::value;
+ 
+ int compile_time_assert[two_phase_lookup_supported ? 1 : -1];
Index: g++.dg/lookup/two-stage4.C
===================================================================
RCS file: g++.dg/lookup/two-stage4.C
diff -N g++.dg/lookup/two-stage4.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- g++.dg/lookup/two-stage4.C	28 May 2005 19:58:08 -0000
***************
*** 0 ****
--- 1,20 ----
+ PR c++/21802
+ // Contributed by Douglas Gregor <doug.gregor@gmail.com>
+ 
+ template<class T> struct wrap {};
+ 
+ template<typename T> bool& operator==(wrap<T>, wrap<T>);
+ 
+ template<typename T>
+ void g(T, wrap<wrap<int> > x)
+ {
+   bool& b = x == x; // { dg-bogus "invalid initialization of reference" "" { xfail *-*-*} }
+ }
+ 
+ template<typename T> int& operator==(wrap<wrap<T> >, wrap<wrap<T> >);
+ 
+ void h()
+ {
+   wrap<wrap<int> > x;
+   g(17, x);
+ }
Index: g++.dg/template/call3.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/template/call3.C,v
retrieving revision 1.1
diff -c -3 -p -r1.1 call3.C
*** g++.dg/template/call3.C	12 Nov 2004 21:47:13 -0000	1.1
--- g++.dg/template/call3.C	28 May 2005 19:58:09 -0000
*************** struct A
*** 9,15 ****
  
  template <typename T> struct B : T
  {
!   B() { foo(T()); }
  };
  
  B<A> b;
--- 9,15 ----
  
  template <typename T> struct B : T
  {
!   B() { foo(T()); } // { dg-error "cannot convert" }
  };
  
  B<A> b;
Index: g++.dg/template/crash37.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/template/crash37.C,v
retrieving revision 1.1
diff -c -3 -p -r1.1 crash37.C
*** g++.dg/template/crash37.C	5 May 2005 19:08:12 -0000	1.1
--- g++.dg/template/crash37.C	28 May 2005 19:58:09 -0000
*************** struct coperator_stack
*** 11,17 ****
  struct helper {};
  
  template<class F>
! void bla(F f)
  {
  }
  
--- 11,17 ----
  struct helper {};
  
  template<class F>
! void bla(F f) // { dg-error "candidates" }
  {
  }
  
*************** struct definition
*** 20,26 ****
  {
   definition()
   {
!    bla(coperator_stack::push3<helper>); // { dg-error "" } 
   }
  };
  
--- 20,26 ----
  {
   definition()
   {
!    bla(coperator_stack::push3<helper>); // { dg-error "" }
   }
  };
  
Index: g++.dg/template/ptrmem4.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/template/ptrmem4.C,v
retrieving revision 1.2
diff -c -3 -p -r1.2 ptrmem4.C
*** g++.dg/template/ptrmem4.C	7 Oct 2003 07:07:07 -0000	1.2
--- g++.dg/template/ptrmem4.C	28 May 2005 19:58:09 -0000
***************
*** 6,12 ****
  // Pointer to member function template argument deduction ICE.
  
  
! template <class CONT> void queryAliases(CONT& fill_me); // { dg-error "argument" }
  
  struct SpyExample
  {
--- 6,12 ----
  // Pointer to member function template argument deduction ICE.
  
  
! template <class CONT> void queryAliases(CONT& fill_me); // { dg-error "candidates" }
  
  struct SpyExample
  {
*************** struct SpyExample
*** 16,20 ****
  
  void SpyExample::ready()
  {
!   queryAliases(inputs);	// { dg-error "" }
  }
--- 16,20 ----
  
  void SpyExample::ready()
  {
!   queryAliases(inputs); // { dg-error "" }
  }
Index: g++.old-deja/g++.other/pmf3.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.old-deja/g++.other/pmf3.C,v
retrieving revision 1.3
diff -c -3 -p -r1.3 pmf3.C
*** g++.old-deja/g++.other/pmf3.C	1 May 2003 02:02:50 -0000	1.3
--- g++.old-deja/g++.other/pmf3.C	28 May 2005 19:58:12 -0000
***************
*** 5,15 ****
  template<class T>
    void connect_to_method(
      T *receiver,
!     void (T::*method)())
    {}
  
  class Gtk_Base
! { 
  public:
    void expose();
    void show();
--- 5,15 ----
  template<class T>
    void connect_to_method(
      T *receiver,
!     void (T::*method)()) // { dg-error "candidates are" }
    {}
  
  class Gtk_Base
! {
  public:
    void expose();
    void show();

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2005-05-28 22:47 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-05-28 23:57 C++ PATCH: PR 2922 Douglas Gregor

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).