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]

C++ PATCH for c++/39070


The problem in this PR was that we end up tsubsting the call twice: the first time we don't perform arg-dependent lookup, but we were passing true for koenig_p so we set KOENIG_LOOKUP_P on the CALL_EXPR and then the second time around we do try to do arg-dependent lookup, which fails because the call is to a template-id rather than a simple name. Fixed by separating in finish_call_expr the notions of actually doing arg-dependent lookup and accepting the results of same.

Tested x86_64-pc-linux-gnu, applied to trunk. Will apply to 4.3 after testing.

2009-02-13  Jason Merrill  <jason@redhat.com>

	PR c++/39070
	* semantics.c (finish_call_expr): Change koenig_p parm to int.
	If -1, don't set KOENIG_LOOKUP_P but do keep hidden candidates.
	* cp-tree.h: Adjust prototype.
	* pt.c (tsubst_copy_and_build) [CALL_EXPR]: Pass -1.
	* g++.dg/cpp0x/decltype16.C: New.

Index: cp/cp-tree.h
===================================================================
*** cp/cp-tree.h	(revision 144138)
--- cp/cp-tree.h	(working copy)
*************** extern tree finish_stmt_expr_expr		(tree
*** 4757,4763 ****
  extern tree finish_stmt_expr			(tree, bool);
  extern tree stmt_expr_value_expr		(tree);
  extern tree perform_koenig_lookup		(tree, tree);
! extern tree finish_call_expr			(tree, tree, bool, bool, 
  						 tsubst_flags_t);
  extern tree finish_increment_expr		(tree, enum tree_code);
  extern tree finish_this_expr			(void);
--- 4757,4763 ----
  extern tree finish_stmt_expr			(tree, bool);
  extern tree stmt_expr_value_expr		(tree);
  extern tree perform_koenig_lookup		(tree, tree);
! extern tree finish_call_expr			(tree, tree, bool, int, 
  						 tsubst_flags_t);
  extern tree finish_increment_expr		(tree, enum tree_code);
  extern tree finish_this_expr			(void);
Index: cp/pt.c
===================================================================
*** cp/pt.c	(revision 144139)
--- cp/pt.c	(working copy)
*************** tsubst_copy_and_build (tree t,
*** 11404,11415 ****
  		       /*fn_p=*/NULL,
  		       complain));
  	  }
! 	/* Pass true for koenig_p so that build_new_function_call will
  	   allow hidden friends found by arg-dependent lookup at template
  	   parsing time.  */
  	return finish_call_expr (function, call_args,
  				 /*disallow_virtual=*/qualified_p,
! 				 /*koenig_p*/true,
  				 complain);
        }
  
--- 11404,11415 ----
  		       /*fn_p=*/NULL,
  		       complain));
  	  }
! 	/* Pass -1 for koenig_p so that build_new_function_call will
  	   allow hidden friends found by arg-dependent lookup at template
  	   parsing time.  */
  	return finish_call_expr (function, call_args,
  				 /*disallow_virtual=*/qualified_p,
! 				 /*koenig_p*/-1,
  				 complain);
        }
  
Index: cp/semantics.c
===================================================================
*** cp/semantics.c	(revision 144138)
--- cp/semantics.c	(working copy)
*************** perform_koenig_lookup (tree fn, tree arg
*** 1839,1848 ****
     qualified.  For example a call to `X::f' never generates a virtual
     call.)
  
     Returns code for the call.  */
  
  tree
! finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p,
  		  tsubst_flags_t complain)
  {
    tree result;
--- 1839,1852 ----
     qualified.  For example a call to `X::f' never generates a virtual
     call.)
  
+    KOENIG_P is 1 if we want to perform argument-dependent lookup,
+    -1 if we don't, but we want to accept functions found by previous
+    argument-dependent lookup, and 0 if we want nothing to do with it.
+ 
     Returns code for the call.  */
  
  tree
! finish_call_expr (tree fn, tree args, bool disallow_virtual, int koenig_p,
  		  tsubst_flags_t complain)
  {
    tree result;
*************** finish_call_expr (tree fn, tree args, bo
*** 1865,1871 ****
  	  || any_type_dependent_arguments_p (args))
  	{
  	  result = build_nt_call_list (fn, args);
! 	  KOENIG_LOOKUP_P (result) = koenig_p;
  	  if (cfun)
  	    {
  	      do
--- 1869,1875 ----
  	  || any_type_dependent_arguments_p (args))
  	{
  	  result = build_nt_call_list (fn, args);
! 	  KOENIG_LOOKUP_P (result) = koenig_p > 0;
  	  if (cfun)
  	    {
  	      do
*************** finish_call_expr (tree fn, tree args, bo
*** 1955,1961 ****
  
        if (!result)
  	/* A call to a namespace-scope function.  */
! 	result = build_new_function_call (fn, args, koenig_p, complain);
      }
    else if (TREE_CODE (fn) == PSEUDO_DTOR_EXPR)
      {
--- 1959,1965 ----
  
        if (!result)
  	/* A call to a namespace-scope function.  */
! 	result = build_new_function_call (fn, args, koenig_p != 0, complain);
      }
    else if (TREE_CODE (fn) == PSEUDO_DTOR_EXPR)
      {
Index: testsuite/g++.dg/cpp0x/decltype16.C
===================================================================
*** testsuite/g++.dg/cpp0x/decltype16.C	(revision 0)
--- testsuite/g++.dg/cpp0x/decltype16.C	(revision 0)
***************
*** 0 ****
--- 1,10 ----
+ // PR c++/39070
+ // { dg-options "-std=c++0x" }
+ 
+ template<typename X> struct junk {
+    template<typename Z> static Z y();
+    template<typename Y> static int  test(...);
+    template<typename Y> static char test(decltype(y<Y>())*);
+    static int const value=sizeof(test<X>(0));
+ };
+ typedef char type[junk<int>::value==sizeof(char) ? 1 : -1];

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