Gabriel Dos Reis <g...@integrable-solutions.net> writes:

> On Thu, Jan 10, 2013 at 9:22 AM, Dodji Seketeli <do...@redhat.com> wrote:
>
>> But during the instantiation of the *members* of test<int>, we try to
>> instantiate Alias<the_truth<int>>, without coercing (and thus without
>> folding) the argument {the_truth<int>}.  We do this using
>> instantiate_alias_template, called from tsubst.
>>
>> The patch below makes sure instantiate_alias_template coerces the
>> arguments it uses to instantiate the alias template, like what I
>> understood you are suggesting.  I have tested it without boostrap and a
>> full boostrap is currently running.
>
> Hmm, is it necessary to coerce all levels as opposed to just the
> innermost arguments?
>
> -- Gaby

Jason Merrill <ja...@redhat.com> writes:

> On 01/10/2013 11:11 AM, Gabriel Dos Reis wrote:
>> Hmm, is it necessary to coerce all levels as opposed to just the
>> innermost arguments?
>
> No.  But if you read the code, it's really only coercing the innermost
> level.

Correct.  I even documented that in the descriptive comment of the
function.  But ...

>  Just the name is misleading.

... as the name seems to be confusing, I have changed it to
coerce_innermost_template_parms.  I hope that is less confusing.

>> If this approach looks acceptable, could I replace (part of) the
>> template argument coercing code in lookup_class_template_1 with the new
>> coerce_template_parms_all_level I introduced in this patch?
>
> Yes.

OK.  I have done that in the patch below that passed bootstrap and
regression testing on x86_64-unknown-linux-gnu against trunk.

If nothing else, I'd need your opinion on this; in the template argument
coercing code in lookup_template_1 does this:

              /* We temporarily reduce the length of the ARGLIST so
                 that coerce_template_parms will see only the arguments
                 corresponding to the template parameters it is
                 examining.  */
              TREE_VEC_LENGTH (arglist)--;

but when I read the code, it looks like this is not necessary.  Am I
missing something?  In any case, I haven't put that code in the new
coerce_innermost_template_parms.  Is that OK?

Thanks.

gcc/cp/

        PR c++/55663
        * pt.c (coerce_innermost_template_parms): New static function.
        (instantiate_alias_template):  Use it here.
        (lookup_template_class_1): Use it here too, for ease of
        maintenance's sake.

gcc/testsuite/

        PR c++/55663
        * g++.dg/cpp0x/alias-decl-31.C: New test.
---
 gcc/cp/pt.c                                | 130 ++++++++++++++++-------------
 gcc/testsuite/g++.dg/cpp0x/alias-decl-31.C |  20 +++++
 2 files changed, 93 insertions(+), 57 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-31.C

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 30bafa0..67e6c97 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -130,6 +130,8 @@ static tree tsubst_initializer_list (tree, tree);
 static tree get_class_bindings (tree, tree, tree, tree);
 static tree coerce_template_parms (tree, tree, tree, tsubst_flags_t,
                                   bool, bool);
+static tree coerce_innermost_template_parms (tree, tree, tree, tsubst_flags_t,
+                                             bool, bool);
 static void tsubst_enum        (tree, tree, tree);
 static tree add_to_template_args (tree, tree);
 static tree add_outermost_template_args (tree, tree);
@@ -6742,6 +6744,61 @@ coerce_template_parms (tree parms,
   return new_inner_args;
 }
 
+/* Like coerce_template_parms.  If PARMS represents all template
+   parameters levels, this function returns a vector of vectors
+   representing all the resulting argument levels.  Note that in this
+   case, only the innermost arguments are coerced because the
+   outermost ones are supposed to have been coerced already.
+
+   Otherwise, if PARMS represents only (the innermost) vector of
+   parameters, this function returns a vector containing just the
+   innermost resulting arguments.  */
+
+static tree
+coerce_innermost_template_parms (tree parms,
+                                 tree args,
+                                 tree in_decl,
+                                 tsubst_flags_t complain,
+                                 bool require_all_args,
+                                 bool use_default_args)
+{
+  int parms_depth = TMPL_PARMS_DEPTH (parms);
+  int args_depth = TMPL_ARGS_DEPTH (args);
+  tree coerced_args;
+
+  if (parms_depth > 1)
+    {
+      coerced_args = make_tree_vec (parms_depth);
+      tree level;
+      int cur_depth;
+
+      for (level = parms, cur_depth = parms_depth;
+          parms_depth > 0 && level != NULL_TREE;
+          level = TREE_CHAIN (level), --cur_depth)
+       {
+         tree l;
+         if (cur_depth == args_depth)
+           l = coerce_template_parms (TREE_VALUE (level),
+                                      args, in_decl, complain,
+                                      require_all_args,
+                                      use_default_args);
+         else
+           l = TMPL_ARGS_LEVEL (args, cur_depth);
+
+         if (l == error_mark_node)
+           return error_mark_node;
+
+         SET_TMPL_ARGS_LEVEL (coerced_args, cur_depth, l);
+       }
+    }
+  else
+    coerced_args = coerce_template_parms (INNERMOST_TEMPLATE_PARMS (parms),
+                                         args, in_decl, complain,
+                                         require_all_args,
+                                         use_default_args);
+  return coerced_args;
+}
+
 /* Returns 1 if template args OT and NT are equivalent.  */
 
 static int
@@ -7169,63 +7226,14 @@ lookup_template_class_1 (tree d1, tree arglist, tree 
in_decl, tree context,
       /* From here on, we're only interested in the most general
         template.  */
 
-      /* Calculate the BOUND_ARGS.  These will be the args that are
-        actually tsubst'd into the definition to create the
-        instantiation.  */
-      if (parm_depth > 1)
-       {
-         /* We have multiple levels of arguments to coerce, at once.  */
-         int i;
-         int saved_depth = TMPL_ARGS_DEPTH (arglist);
-
-         tree bound_args = make_tree_vec (parm_depth);
-
-         for (i = saved_depth,
-                t = DECL_TEMPLATE_PARMS (gen_tmpl);
-              i > 0 && t != NULL_TREE;
-              --i, t = TREE_CHAIN (t))
-           {
-             tree a;
-             if (i == saved_depth)
-               a = coerce_template_parms (TREE_VALUE (t),
-                                          arglist, gen_tmpl,
-                                          complain,
-                                          /*require_all_args=*/true,
-                                          /*use_default_args=*/true);
-             else
-               /* Outer levels should have already been coerced.  */
-               a = TMPL_ARGS_LEVEL (arglist, i);
-
-             /* Don't process further if one of the levels fails.  */
-             if (a == error_mark_node)
-               {
-                 /* Restore the ARGLIST to its full size.  */
-                 TREE_VEC_LENGTH (arglist) = saved_depth;
-                 return error_mark_node;
-               }
-
-             SET_TMPL_ARGS_LEVEL (bound_args, i, a);
-
-             /* We temporarily reduce the length of the ARGLIST so
-                that coerce_template_parms will see only the arguments
-                corresponding to the template parameters it is
-                examining.  */
-             TREE_VEC_LENGTH (arglist)--;
-           }
-
-         /* Restore the ARGLIST to its full size.  */
-         TREE_VEC_LENGTH (arglist) = saved_depth;
-
-         arglist = bound_args;
-       }
-      else
-       arglist
-         = coerce_template_parms (INNERMOST_TEMPLATE_PARMS (parmlist),
-                                  INNERMOST_TEMPLATE_ARGS (arglist),
-                                  gen_tmpl,
-                                  complain,
-                                  /*require_all_args=*/true,
-                                  /*use_default_args=*/true);
+      /* Convert the innermost template arguments to their appropriate
+        types.  These will be the arguments that are actually
+        tsubst'd into the definition to create the instantiation.  */
+      arglist =
+       coerce_innermost_template_parms (parmlist, arglist,
+                                        gen_tmpl, complain,
+                                        /*require_all_args=*/true,
+                                        /*use_default_args=*/true);
 
       if (arglist == error_mark_node)
        /* We were unable to bind the arguments.  */
@@ -14637,7 +14645,15 @@ instantiate_alias_template (tree tmpl, tree args, 
tsubst_flags_t complain)
       ggc_free (tinst);
       return error_mark_node;
     }
+
+  args =
+    coerce_innermost_template_parms (DECL_TEMPLATE_PARMS (tmpl),
+                                    args, tmpl, complain,
+                                    /*require_all_args=*/true,
+                                    /*use_default_args=*/true);
+
   tree r = instantiate_template (tmpl, args, complain);
+
   pop_tinst_level ();
   /* We can't free this if a pending_template entry or last_error_tinst_level
      is pointing at it.  */
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-31.C 
b/gcc/testsuite/g++.dg/cpp0x/alias-decl-31.C
new file mode 100644
index 0000000..83eea47
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-31.C
@@ -0,0 +1,20 @@
+// Origin: PR c++/55663
+// { dg-do compile { target c++11 } }
+
+template <typename>
+constexpr bool the_truth () { return true; }
+
+template <bool>
+  struct Takes_bool { };
+
+template<bool B>
+  using Alias = Takes_bool<B>;
+
+template<typename T>
+  struct test { using type = Alias<the_truth<T>()>; };
+
+int main () {
+  test<int> a;
+
+  return 0;
+}
-- 
                Dodji

Reply via email to