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 ();