Message ID | 3c94265be0a93211393264ac16908baa@imap.force9.net |
---|---|
State | New |
Headers | show |
On 23.09.2013 08:15, Adam Butcher wrote: > On 22.09.2013 18:57, Adam Butcher wrote: >> The following solves the canonical type issue in the general case >> (pointers and refs) and makes it equivalent to the explicit template >> case -- in terms of canonical type at least. >> >> for (tree t = TREE_TYPE (TREE_VALUE (p)); t; t = TREE_CHAIN >> (t)) >> TYPE_CANONICAL (t) = t; >> > The above is insufficient; the traversal doesn't handle function > pointers. Currently, to get my local testcases passing, I have the > following workaround that abuses find_type_usage. I intend for this > to be replaced with a better solution but it will at least mean that > people can start experimenting with this feature now (as they appear > to be doing http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58500). This > supports that testcase also. > Shall I push the patch below to trunk as an intermediate workaround whilst I get to refactoring to support on-the-fly template parm synthesis? On the subject of on-the-fly synthesis: I haven't started yet but I'm thinking to trigger in 'cp_parser_simple_type_specifier' when 'current_binding_level->kind == sk_function_parms'. I can foresee a potential issue with packs in that, upon reading the 'auto' (potentially nested in some other type), a plain template parm will be synthesized; but it may need to be a pack parm type if '...' is found later. My initial testcase is: template <typename T> struct X { T m(int, float); }; auto f(X<auto>, auto (X<auto>::*) (auto...)) { char* s = "warn"; } int main() { X<char> x; f(x, &X<void>::m); } where f should be translated as similar to: template <typename A1, typename A2, typename A3, typename... A4> auto f(X<A1>, A2 (X<A3>::*) (A4...)) { char* s = "warn"; } In the case of something like: auto f(X<auto>&&...) the translation would need to be: template <typename... A> auto f(X<A>&&...) I'm thinking that getting that to happen correctly might be tricky (but haven't tried yet). The 'auto' would trigger plain template parameter synthesis. Perhaps a 'could_be_parameter_pack_p' on the template_type_parm? Though I don't know how the following could be handled as implicit template <typename T, typename A...> auto f(X<T, A>&&...) It would not be possible to infer which of the template parms to make the pack. auto f(X<auto, auto>&&...) Probably multiple generic-type pack expansions should be forbidden. I'll see what happens when I get there but any guidance/thoughts you have on the subject will be valuable. Cheers, Adam > Workaround implicit function template parameter canonical type > issue. > > * parser.c (add_implicit_template_parms): Workaround to fix > up canonical > type references left over from before substation of 'auto'. > Better > solution needed but this makes test cases functional. > > diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c > index f3133f3..4171476 100644 > --- a/gcc/cp/parser.c > +++ b/gcc/cp/parser.c > @@ -28987,6 +28987,25 @@ add_implicit_template_parms (cp_parser > *parser, size_t expect_count, > if (!generic_type_ptr) > continue; > > + /* Make the canonical type of each part of the parameter > distinct. > + FIXME: A better solution is needed for this. Not least the > abuse of > + find_type_usage. Need foreach_type or similar for proper > mutable > + access. If something like this does turn out to be > necessary then the > + find_type_usage loop above can be replaced by a foreach_type > that fixes > + up the canonical types on the way to finding the 'auto'. */ > + > + struct helper { static bool fixup_canonical_types (tree t) { > + t = TREE_TYPE (t); > + if (!t) > + return false; > + if (is_auto_or_concept (t)) > + return true; > + TYPE_CANONICAL (t) = t; > + return false; > + }}; > + find_type_usage (TREE_VALUE (p), (bool (*)(const_tree)) > + helper::fixup_canonical_types); > + > ++synth_count; > > tree synth_id = make_generic_type_name ();
On 09/24/2013 02:05 AM, Adam Butcher wrote: > Shall I push the patch below to trunk as an intermediate workaround > whilst I get to refactoring to support on-the-fly template parm synthesis? I think let's wait for a better fix. > On the subject of on-the-fly synthesis: I haven't started yet but I'm > thinking to trigger in 'cp_parser_simple_type_specifier' when > 'current_binding_level->kind == sk_function_parms'. I can foresee a > potential issue with packs in that, upon reading the 'auto' (potentially > nested in some other type), a plain template parm will be synthesized; > but it may need to be a pack parm type if '...' is found later. Hmm, good point. I think there are two options: 1) Build up the type as normal and use tsubst to replace the non-pack template parameter with a pack if needed. 2) If we see 'auto', scan ahead (possibly via tentative parsing) to see if there's a ... Jason
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index f3133f3..4171476 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -28987,6 +28987,25 @@ add_implicit_template_parms (cp_parser *parser, size_t expect_count, if (!generic_type_ptr) continue; + /* Make the canonical type of each part of the parameter distinct. + FIXME: A better solution is needed for this. Not least the abuse of + find_type_usage. Need foreach_type or similar for proper mutable + access. If something like this does turn out to be necessary then the + find_type_usage loop above can be replaced by a foreach_type that fixes + up the canonical types on the way to finding the 'auto'. */ + + struct helper { static bool fixup_canonical_types (tree t) { + t = TREE_TYPE (t); + if (!t) + return false; + if (is_auto_or_concept (t)) + return true; + TYPE_CANONICAL (t) = t; + return false; + }};