diff mbox

PR c++/51289 - ICE with alias template for bound template

Message ID m339d73phg.fsf@redhat.com
State New
Headers show

Commit Message

Dodji Seketeli Nov. 29, 2011, 3:41 p.m. UTC
Jason Merrill <jason@redhat.com> writes:

> On 11/28/2011 11:54 AM, Dodji Seketeli wrote:
>> @@ -3028,10 +3028,12 @@ find_parameter_packs_r (tree*tp, int *walk_subtrees, void*  data)
>>
>>       case BOUND_TEMPLATE_TEMPLATE_PARM:
>>         /* Check the template itself.  */
>> -      cp_walk_tree (&TREE_TYPE (TYPE_TI_TEMPLATE (t)),
>> +      cp_walk_tree (&TREE_TYPE (TI_TEMPLATE
>> +				(TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t))),
>>   		&find_parameter_packs_r, ppd, ppd->visited);
>>         /* Check the template arguments.  */
>> -      cp_walk_tree (&TYPE_TI_ARGS (t),&find_parameter_packs_r, ppd,
>> +      cp_walk_tree (&TI_ARGS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t)),
>> +		&find_parameter_packs_r, ppd,
>>   		    ppd->visited);
>>         *walk_subtrees = 0;
>>         return NULL_TREE;
>
> Instead of this change, I think we should handle typedefs/aliases at
> the top of the function.  We shouldn't need to look into the
> underlying type for packs.

Thus, I have bootstrapped and tested the below on
x86_64-unknown-linux-gnu against trunk.  I had to make TYPE_ALIAS_P more
robust so that it doesn't crash on TEMPLATE_TEMPLATE_PARMs which
TYPE_NAME are TEMPLATE_DECL nodes, unlike the other types that use
TYPE_DECL nodes that.


gcc/cp/

	PR c++/51289
	* cp-tree.h (TYPE_TEMPLATE_INFO): Rewrite this accessor macro to
	better support aliased types.
	(TYPE_ALIAS_P): Don't crash on TYPE_NAME nodes that are not
	TYPE_DECL.
	* pt.c (find_parameter_packs_r): Handle typedef variant types.

gcc/testsuite/

	PR c++/51289
	* g++.dg/cpp0x/alias-decl-17.C: New test.
---
 gcc/cp/cp-tree.h                           |   28 ++++++++++++++++++----------
 gcc/cp/pt.c                                |   14 ++++++++++++++
 gcc/testsuite/g++.dg/cpp0x/alias-decl-17.C |   13 +++++++++++++
 3 files changed, 45 insertions(+), 10 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-17.C

Comments

Jason Merrill Nov. 29, 2011, 4:32 p.m. UTC | #1
On 11/29/2011 10:41 AM, Dodji Seketeli wrote:
> +      cp_walk_tree (&DECL_ORIGINAL_TYPE (TYPE_NAME (t)),
> +		&find_parameter_packs_r,
> +		    ppd, ppd->visited);

I still don't think we want to walk the underlying type, since it isn't 
part of the syntactic form of the type in this context and therefore 
can't have relevant packs.

Jason
diff mbox

Patch

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 3f4f408..b821928 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2553,6 +2553,7 @@  extern void decl_shadowed_for_var_insert (tree, tree);
 #define TYPE_ALIAS_P(NODE)			\
   (TYPE_P (NODE)				\
    && TYPE_NAME (NODE)				\
+   && TREE_CODE (TYPE_NAME (NODE)) == TYPE_DECL	\
    && TYPE_DECL_ALIAS_P (TYPE_NAME (NODE)))
 
 /* For a class type: if this structure has many fields, we'll sort them
@@ -2605,17 +2606,24 @@  extern void decl_shadowed_for_var_insert (tree, tree);
   (LANG_TYPE_CLASS_CHECK (BOUND_TEMPLATE_TEMPLATE_PARM_TYPE_CHECK (NODE)) \
    ->template_info)
 
-/* Template information for an ENUMERAL_, RECORD_, or UNION_TYPE.  */
+/* Template information for an ENUMERAL_, RECORD_, UNION_TYPE, or
+   BOUND_TEMPLATE_TEMPLATE_PARM type.  Note that if NODE is a
+   specialization of an alias template, this accessor returns the
+   template info for the alias template, not the one (if any) for the
+   template of the underlying type.  */
 #define TYPE_TEMPLATE_INFO(NODE)					\
-  (TREE_CODE (NODE) == ENUMERAL_TYPE					\
-   ? ENUM_TEMPLATE_INFO (NODE) :					\
-   (TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM			\
-    ? TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (NODE) :			\
-    ((CLASS_TYPE_P (NODE) && !TYPE_ALIAS_P (NODE))			\
-     ? CLASSTYPE_TEMPLATE_INFO (NODE)					\
-     : ((TYPE_NAME (NODE) && DECL_LANG_SPECIFIC (TYPE_NAME (NODE)))	\
-	? (DECL_TEMPLATE_INFO (TYPE_NAME (NODE)))			\
-	: NULL_TREE))))
+  (TYPE_ALIAS_P (NODE)							\
+   ? ((TYPE_NAME (NODE) && DECL_LANG_SPECIFIC (TYPE_NAME (NODE)))	\
+      ? DECL_TEMPLATE_INFO (TYPE_NAME (NODE))				\
+      : NULL_TREE)							\
+   : ((TREE_CODE (NODE) == ENUMERAL_TYPE)				\
+      ? ENUM_TEMPLATE_INFO (NODE)					\
+      : ((TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM)		\
+	 ? TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (NODE)			\
+	 : (CLASS_TYPE_P (NODE)						\
+	    ? CLASSTYPE_TEMPLATE_INFO (NODE)				\
+	    : NULL_TREE))))
+
 
 /* Set the template information for an ENUMERAL_, RECORD_, or
    UNION_TYPE to VAL.  */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 4725080..5bc6f23 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -2976,6 +2976,20 @@  find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
     (struct find_parameter_pack_data*)data;
   bool parameter_pack_p = false;
 
+  /* Handle type aliases/typedefs.  */
+  if (TYPE_P (t) && typedef_variant_p (t))
+    {
+      if (TYPE_TEMPLATE_INFO (t))
+	cp_walk_tree (&TYPE_TI_ARGS (t),
+		      &find_parameter_packs_r,
+		      ppd, ppd->visited);
+      cp_walk_tree (&DECL_ORIGINAL_TYPE (TYPE_NAME (t)),
+		    &find_parameter_packs_r,
+		    ppd, ppd->visited);
+      *walk_subtrees = 0;
+      return NULL_TREE;
+    }
+
   /* Identify whether this is a parameter pack or not.  */
   switch (TREE_CODE (t))
     {
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-17.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-17.C
new file mode 100644
index 0000000..a7b2d37
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-17.C
@@ -0,0 +1,13 @@ 
+// Origin PR c++/51289
+// { dg-options "-std=c++11" }
+
+template<typename a, template <typename, typename> class b>
+struct foo {
+  template <typename t>
+  using type = b<a, t>;
+  template <typename t>
+  b<a, t> funca() {}
+
+  template <typename t>
+  type<t> funcb() {}
+};