This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH for c++/39070
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches List <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 13 Feb 2009 14:13:22 -0500
- Subject: 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];