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

Reply via email to