Jason Merrill <[email protected]> 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
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() {}
+};
--
1.7.6.4
--
Dodji