Patchwork PR c++/55663 - constexpr function templ instantiation considered non-const as alias templ arg

login
register
mail settings
Submitter Dodji Seketeli
Date Jan. 11, 2013, 4:33 p.m.
Message ID <877gnjof24.fsf@redhat.com>
Download mbox | patch
Permalink /patch/211378/
State New
Headers show

Comments

Dodji Seketeli - Jan. 11, 2013, 4:33 p.m.
Jason Merrill <jason@redhat.com> writes:

> On 01/11/2013 05:38 AM, Dodji Seketeli wrote:
>> 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?
>
> I agree that it seems unnecessary.  But to be safe, let's leave
> lookup_template_class_1 alone until after 4.8 branches.

OK, here are the patches I am proposing then.  The first one is the one
I'd like to commit to 4.8 and the second one would be scheduled for 4.9
when its branch opens.

Is that OK?

gcc/cp/

	PR c++/55663
	* pt.c (coerce_innermost_template_parms): New static function.
	(instantiate_alias_template):  Use it here.

gcc/testsuite/

	PR c++/55663
	* g++.dg/cpp0x/alias-decl-31.C: New test.
---
 gcc/cp/pt.c                                | 64 ++++++++++++++++++++++++++++++
 gcc/testsuite/g++.dg/cpp0x/alias-decl-31.C | 20 ++++++++++
 2 files changed, 84 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-31.C
Jason Merrill - Jan. 14, 2013, 2:09 p.m.
OK.

Jason

Patch

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 6d78dd2..62fa2d9 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
@@ -14642,6 +14699,13 @@  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
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;
+}
-- 
1.7.11.7


gcc/cp/

	* pt.c (lookup_template_class_1): Use coerce_inner_template_parms
	here for the sake of ease of maintenance.
---
 gcc/cp/pt.c | 65 ++++++++-----------------------------------------------------
 1 file changed, 8 insertions(+), 57 deletions(-)

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 62fa2d9..3c63407 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -7226,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.  */