Message ID | 5385B756.8070707@oracle.com |
---|---|
State | New |
Headers | show |
On 05/28/2014 06:15 AM, Paolo Carlini wrote: > + bool do_inject = (!current_class_ref > + && TREE_CODE (t) == METHOD_TYPE > + && TREE_CODE (TREE_TYPE (t)) == DECLTYPE_TYPE); Let's do this for any METHOD_TYPE; the decltype could be nested as a template argument. And current_class_ref might be for the wrong class. > + /* DR 1207: 'this' is in scope in the trailing return type. */ > + tree this_type = (current_class_type > + ? current_class_type > + : TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t)))); And here let's use class_of_this_parm unconditionally. Jason
Hi, On 05/28/2014 05:14 PM, Jason Merrill wrote: > On 05/28/2014 06:15 AM, Paolo Carlini wrote: >> + bool do_inject = (!current_class_ref >> + && TREE_CODE (t) == METHOD_TYPE >> + && TREE_CODE (TREE_TYPE (t)) == DECLTYPE_TYPE); > > Let's do this for any METHOD_TYPE; the decltype could be nested as a > template argument. And current_class_ref might be for the wrong class. Ok. > >> + /* DR 1207: 'this' is in scope in the trailing return type. */ >> + tree this_type = (current_class_type >> + ? current_class_type >> + : TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t)))); > > And here let's use class_of_this_parm unconditionally. But unconditionally doesn't work, without doing something more. For example for the first test, as reported: when current_class_type is set and equal to "struct X<int>", class_of_this_parm is "struct X< <template-parameter-1-1> >". I'm trying to paste below the trees: (gdb) p debug_tree(class_of_this_parm(t)) <record_type 0x7ffff6819a80 X type_0 type_5 type_6 VOID size <integer_cst 0x7ffff66d58a0 type <integer_type 0x7ffff66d7150 bitsizetype> constant 0> unit size <integer_cst 0x7ffff66d5858 type <integer_type 0x7ffff66d70a8 sizetype> constant 0> align 8 symtab 0 alias set -1 canonical type 0x7ffff6819a80 fields <type_decl 0x7ffff6813b80 X type <record_type 0x7ffff6819b28 X type_0 type_5 type_6 VOID size <integer_cst 0x7ffff66d58a0 0> unit size <integer_cst 0x7ffff66d5858 0> align 8 symtab 0 alias set -1 canonical type 0x7ffff6819a80 fields <type_decl 0x7ffff6813b80 X> context <translation_unit_decl 0x7ffff66e0170 D.1> full-name "struct X< <template-parameter-1-1> >" n_parents=0 use_template=0 interface-unknown chain <type_decl 0x7ffff6813a10 X>> used nonlocal decl_4 VOID file 57543_1.C line 5 col 1 align 1 context <record_type 0x7ffff6819a80 X> result <record_type 0x7ffff6819a80 X> > context <translation_unit_decl 0x7ffff66e0170 D.1> full-name "struct X< <template-parameter-1-1> >" n_parents=0 use_template=0 interface-unknown pointer_to_this <pointer_type 0x7ffff6819d20> chain <type_decl 0x7ffff6813a10 X>> $3 = void (gdb) p current_class_type $4 = (tree) 0x7ffff682a2a0 (gdb) p debug_tree(current_class_type) <record_type 0x7ffff682a2a0 X type_5 type_6 VOID align 8 symtab 0 alias set -1 canonical type 0x7ffff682a2a0 fields <type_decl 0x7ffff682c0b8 X type <record_type 0x7ffff682a348 X used type_5 type_6 VOID align 8 symtab 0 alias set -1 canonical type 0x7ffff682a2a0 context <translation_unit_decl 0x7ffff66e0170 D.1> full-name "struct X<int>" n_parents=0 use_template=1 interface-unknown chain <type_decl 0x7ffff6813f18 X>> used external nonlocal suppress-debug decl_4 VOID file 57543_1.C line 5 col 1 align 8 context <record_type 0x7ffff682a2a0 X> result <record_type 0x7ffff682a2a0 X> > context <translation_unit_decl 0x7ffff66e0170 D.1> full-name "struct X<int>" n_parents=0 use_template=1 interface-unknown pointer_to_this <pointer_type 0x7ffff682a3f0> chain <type_decl 0x7ffff6813f18 X>>
On 05/28/2014 11:38 AM, Paolo Carlini wrote: > But unconditionally doesn't work, without doing something more. For > example for the first test, as reported: when current_class_type is set > and equal to "struct X<int>", class_of_this_parm is "struct X< > <template-parameter-1-1> >". Right, it needs to be the substituted this parameter. Let's remember when we had a trailing return type (probably by setting a flag in splice_late_return_type and then preserving it when we rebuild METHOD/FUNCTION_TYPEs) and if it's set, tsubst the return type after the argument types rather than before so that SFINAE consistently works in lexical order. Jason
Hi, On 05/28/2014 05:49 PM, Jason Merrill wrote: > On 05/28/2014 11:38 AM, Paolo Carlini wrote: >> But unconditionally doesn't work, without doing something more. For >> example for the first test, as reported: when current_class_type is set >> and equal to "struct X<int>", class_of_this_parm is "struct X< >> <template-parameter-1-1> >". > > Right, it needs to be the substituted this parameter. > > Let's remember when we had a trailing return type (probably by setting > a flag in splice_late_return_type and then preserving it when we > rebuild METHOD/FUNCTION_TYPEs) and if it's set, tsubst the return type > after the argument types rather than before so that SFINAE > consistently works in lexical order. I see. Even not considering this issue, there are many regression if I inject for all method types. I'm afraid the issue turns out to be much more tricky than I hoped, I guess I'm going to unassign myself, for now, and work on some other pending issues in my todo. You are of course more than welcome to take it and include my additional tests in your work! Thanks, Paolo.
On 05/28/2014 11:59 AM, Paolo Carlini wrote: > I see. Even not considering this issue, there are many regression if I > inject for all method types. I'm afraid the issue turns out to be much > more tricky than I hoped, I guess I'm going to unassign myself, for now, > and work on some other pending issues in my todo. You are of course more > than welcome to take it and include my additional tests in your work! OK. Please add a link to this thread in the PR, if you haven't already. Jason
Index: cp/pt.c =================================================================== --- cp/pt.c (revision 211003) +++ cp/pt.c (working copy) @@ -11323,7 +11323,28 @@ tsubst_function_type (tree t, gcc_assert (TYPE_CONTEXT (t) == NULL_TREE); /* Substitute the return type. */ + tree save_ccp = current_class_ptr; + tree save_ccr = current_class_ref; + bool do_inject = (!current_class_ref + && TREE_CODE (t) == METHOD_TYPE + && TREE_CODE (TREE_TYPE (t)) == DECLTYPE_TYPE); + if (do_inject) + { + /* DR 1207: 'this' is in scope in the trailing return type. */ + tree this_type = (current_class_type + ? current_class_type + : TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t)))); + inject_this_parameter (this_type, type_memfn_quals (t)); + } + return_type = tsubst (TREE_TYPE (t), args, complain, in_decl); + + if (do_inject) + { + current_class_ptr = save_ccp; + current_class_ref = save_ccr; + } + if (return_type == error_mark_node) return error_mark_node; /* DR 486 clarifies that creation of a function type with an Index: testsuite/g++.dg/cpp0x/decltype59.C =================================================================== --- testsuite/g++.dg/cpp0x/decltype59.C (revision 0) +++ testsuite/g++.dg/cpp0x/decltype59.C (working copy) @@ -0,0 +1,41 @@ +// PR c++/57543 +// { dg-do compile { target c++11 } } + +template< typename > struct X +{ + void foo(); + auto bar() -> decltype( X::foo() ); +}; + +template< typename > struct Y +{ + void foo(); + template< typename > + auto bar() -> decltype( Y::foo() ); +}; + +template< typename > struct Z +{ + void foo(); + template< typename T > + auto bar() -> decltype( T::foo() ); +}; + +template< typename > struct K +{ + void foo(); + template< typename T > + auto bar() -> decltype( T::foo() ); +}; + +template<> +template<> +auto K<int>::bar<K<int>>() -> decltype( K<int>::foo() ); + +int main() +{ + X<int>().bar(); + Y<int>().bar<double>(); + Z<int>().bar<Z<int>>(); + K<int>().bar<K<int>>(); +}