diff mbox

C++ PATCH to template template parm partial instantiation

Message ID 559AFCBF.2000102@redhat.com
State New
Headers show

Commit Message

Jason Merrill July 6, 2015, 10:10 p.m. UTC
The concepts work ran into a bug whereby the TEMPLATE_PARM_DECL of a 
TEMPLATE_TEMPLATE_PARM was missing its DECL_TEMPLATE_RESULT.  Looking 
into this more, I see that when instantiating a template template 
parameter we end up with two TEMPLATE_DECLs: the main one and another in 
the TEMPLATE_PARM_DECL.  That's silly, they should be the same.

So this patch fixes reduce_template_parm_level to build up a proper 
TEMPLATE_DECL, and changes tsubst_decl to use it.

Tested x86_64-pc-linux-gnu, applying to trunk.
diff mbox

Patch

commit 4c2688271426e4f6e5cc0d93962efa3b1095b96b
Author: Jason Merrill <jason@redhat.com>
Date:   Sun Jul 5 23:21:34 2015 -0400

    	* pt.c (reduce_template_parm_level): Also build the TYPE_DECL
    	for a template template parameter.
    	(tsubst_decl) [TEMPLATE_DECL]: Use the TEMPLATE_DECL built
    	by reduce_template_parm_level.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 0302de1..3cd7bac 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -3740,9 +3740,14 @@  reduce_template_parm_level (tree index, tree type, int levels, tree args,
 
 	/* Template template parameters need this.  */
       if (TREE_CODE (decl) == TEMPLATE_DECL)
-	DECL_TEMPLATE_PARMS (decl) = tsubst_template_parms
-	  (DECL_TEMPLATE_PARMS (TEMPLATE_PARM_DECL (index)),
-	   args, complain);
+	{
+	  DECL_TEMPLATE_RESULT (decl)
+	    = build_decl (DECL_SOURCE_LOCATION (decl),
+			  TYPE_DECL, DECL_NAME (decl), type);
+	  DECL_ARTIFICIAL (DECL_TEMPLATE_RESULT (decl)) = true;
+	  DECL_TEMPLATE_PARMS (decl) = tsubst_template_parms
+	    (DECL_TEMPLATE_PARMS (orig_decl), args, complain);
+	}
     }
 
   return TEMPLATE_PARM_DESCENDANTS (index);
@@ -10687,22 +10692,15 @@  tsubst_decl (tree t, tree args, tsubst_flags_t complain)
 	    /* Template template parameter is treated here.  */
 	    tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
 	    if (new_type == error_mark_node)
-	      RETURN (error_mark_node);
+	      r = error_mark_node;
 	    /* If we get a real template back, return it.  This can happen in
 	       the context of most_specialized_partial_spec.  */
-	    if (TREE_CODE (new_type) == TEMPLATE_DECL)
-	      return new_type;
-
-	    r = copy_decl (t);
-	    DECL_CHAIN (r) = NULL_TREE;
-	    TREE_TYPE (r) = new_type;
-	    DECL_TEMPLATE_RESULT (r)
-	      = build_decl (DECL_SOURCE_LOCATION (decl),
-			    TYPE_DECL, DECL_NAME (decl), new_type);
-	    DECL_TEMPLATE_PARMS (r)
-	      = tsubst_template_parms (DECL_TEMPLATE_PARMS (t), args,
-				       complain);
-	    TYPE_NAME (new_type) = r;
+	    else if (TREE_CODE (new_type) == TEMPLATE_DECL)
+	      r = new_type;
+	    else
+	      /* The new TEMPLATE_DECL was built in
+		 reduce_template_parm_level.  */
+	      r = TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (new_type);
 	    break;
 	  }