2016-12-12 Nathan Sidwell <nathan@acm.org>
PR c++/69481
* cp-tree.h (TYPE_TEMPLATE_INFO): Remove alias type checking.
(TYPE_ALIAS_TEMPLATE_INFO): New.
(TYPE_TEMPLATE_INFO_MAYBE_ALIAS): New. Use those macros.
* error.c (dump_alias_template_specialization): Adjust.
* pt.c (maybe_process_partial_specialization,
iterative_has_template_arg, find_parameter_packs_r,
alias_template_specialization_p, dependent_alias_template_spec_p,
get_underlying_template, lookup_template_class_1, unify): Adjust
template using decl access.
PR c++/69481
* g++.dg/cpp0x/pr69481.C: New.
===================================================================
@@ -3038,23 +3038,30 @@ extern void decl_shadowed_for_var_insert
->template_info)
/* 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. */
+ BOUND_TEMPLATE_TEMPLATE_PARM type. This ignores any alias
+ templateness of NODE. */
#define TYPE_TEMPLATE_INFO(NODE) \
- ((TYPE_ALIAS_P (NODE) && DECL_LANG_SPECIFIC (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))))
+ (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)))
+/* Template information for an alias template type. */
+#define TYPE_ALIAS_TEMPLATE_INFO(NODE) \
+ (DECL_LANG_SPECIFIC (TYPE_NAME (NODE)) \
+ ? DECL_TEMPLATE_INFO (TYPE_NAME (NODE)) \
+ : NULL_TREE)
+
+/* If NODE is a specialization of an alias template, this accessor
+ returns the template info for the alias template. Otherwise behave
+ as TYPE_TEMPLATE_INFO. */
+#define TYPE_TEMPLATE_INFO_MAYBE_ALIAS(NODE) \
+ (TYPE_ALIAS_P (NODE) && DECL_LANG_SPECIFIC (TYPE_NAME (NODE)) \
+ ? TYPE_ALIAS_TEMPLATE_INFO (NODE) \
+ : TYPE_TEMPLATE_INFO (NODE))
/* Set the template information for an ENUMERAL_, RECORD_, or
UNION_TYPE to VAL. */
===================================================================
@@ -365,15 +365,13 @@ dump_template_bindings (cxx_pretty_print
static void
dump_alias_template_specialization (cxx_pretty_printer *pp, tree t, int flags)
{
- tree name;
-
gcc_assert (alias_template_specialization_p (t));
+ tree decl = TYPE_NAME (t);
if (!(flags & TFF_UNQUALIFIED_NAME))
- dump_scope (pp, CP_DECL_CONTEXT (TYPE_NAME (t)), flags);
- name = TYPE_IDENTIFIER (t);
- pp_cxx_tree_identifier (pp, name);
- dump_template_parms (pp, TYPE_TEMPLATE_INFO (t),
+ dump_scope (pp, CP_DECL_CONTEXT (decl), flags);
+ pp_cxx_tree_identifier (pp, DECL_NAME (decl));
+ dump_template_parms (pp, DECL_TEMPLATE_INFO (decl),
/*primary=*/false,
flags & ~TFF_TEMPLATE_HEADER);
}
===================================================================
@@ -940,10 +940,11 @@ maybe_process_partial_specialization (tr
if (TYPE_ALIAS_P (type))
{
- if (TYPE_TEMPLATE_INFO (type)
- && DECL_ALIAS_TEMPLATE_P (TYPE_TI_TEMPLATE (type)))
+ tree tinfo = TYPE_ALIAS_TEMPLATE_INFO (type);
+
+ if (tinfo && DECL_ALIAS_TEMPLATE_P (TI_TEMPLATE (tinfo)))
error ("specialization of alias template %qD",
- TYPE_TI_TEMPLATE (type));
+ TI_TEMPLATE (tinfo));
else
error ("explicit specialization of non-template %qT", type);
return error_mark_node;
@@ -1829,7 +1830,7 @@ iterative_hash_template_arg (tree arg, h
// left alone, or untouched specializations because
// coerce_template_parms returns the unconverted template
// arguments if it sees incomplete argument packs.
- tree ti = TYPE_TEMPLATE_INFO (arg);
+ tree ti = TYPE_ALIAS_TEMPLATE_INFO (arg);
return hash_tmpl_and_args (TI_TEMPLATE (ti), TI_ARGS (ti));
}
if (TYPE_CANONICAL (arg))
@@ -3459,8 +3460,8 @@ find_parameter_packs_r (tree *tp, int *w
/* Handle type aliases/typedefs. */
if (TYPE_ALIAS_P (t))
{
- if (TYPE_TEMPLATE_INFO (t))
- cp_walk_tree (&TYPE_TI_ARGS (t),
+ if (tree tinfo = TYPE_ALIAS_TEMPLATE_INFO (t))
+ cp_walk_tree (&TI_ARGS (tinfo),
&find_parameter_packs_r,
ppd, ppd->visited);
*walk_subtrees = 0;
@@ -5794,15 +5795,9 @@ alias_template_specialization_p (const_t
/* It's an alias template specialization if it's an alias and its
TYPE_NAME is a specialization of a primary template. */
if (TYPE_ALIAS_P (t))
- {
- tree name = TYPE_NAME (t);
- if (DECL_LANG_SPECIFIC (name))
- if (tree ti = DECL_TEMPLATE_INFO (name))
- {
- tree tmpl = TI_TEMPLATE (ti);
- return PRIMARY_TEMPLATE_P (tmpl);
- }
- }
+ if (tree tinfo = TYPE_ALIAS_TEMPLATE_INFO (t))
+ return PRIMARY_TEMPLATE_P (TI_TEMPLATE (tinfo));
+
return false;
}
@@ -5854,10 +5849,18 @@ complex_alias_template_p (const_tree tmp
bool
dependent_alias_template_spec_p (const_tree t)
{
- return (alias_template_specialization_p (t)
- && TEMPLATE_DECL_COMPLEX_ALIAS_P (DECL_TI_TEMPLATE (TYPE_NAME (t)))
- && (any_dependent_template_arguments_p
- (INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (t)))));
+ if (!alias_template_specialization_p (t))
+ return false;
+
+ tree tinfo = TYPE_ALIAS_TEMPLATE_INFO (t);
+ if (!TEMPLATE_DECL_COMPLEX_ALIAS_P (TI_TEMPLATE (tinfo)))
+ return false;
+
+ tree args = INNERMOST_TEMPLATE_ARGS (TI_ARGS (tinfo));
+ if (!any_dependent_template_arguments_p (args))
+ return false;
+
+ return true;
}
/* Return the number of innermost template parameters in TMPL. */
@@ -5879,26 +5882,27 @@ get_underlying_template (tree tmpl)
gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
while (DECL_ALIAS_TEMPLATE_P (tmpl))
{
- tree result = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (tmpl));
- if (TYPE_TEMPLATE_INFO (result))
- {
- tree sub = TYPE_TI_TEMPLATE (result);
- if (PRIMARY_TEMPLATE_P (sub)
- && (num_innermost_template_parms (tmpl)
- == num_innermost_template_parms (sub)))
- {
- tree alias_args = INNERMOST_TEMPLATE_ARGS
- (template_parms_to_args (DECL_TEMPLATE_PARMS (tmpl)));
- if (!comp_template_args (TYPE_TI_ARGS (result), alias_args))
- break;
- /* The alias type is equivalent to the pattern of the
- underlying template, so strip the alias. */
- tmpl = sub;
- continue;
- }
- }
- break;
+ /* Determine if the alias is equivalent to an underlying template. */
+ tree orig_type = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (tmpl));
+ tree tinfo = TYPE_TEMPLATE_INFO_MAYBE_ALIAS (orig_type);
+ if (!tinfo)
+ break;
+
+ tree underlying = TI_TEMPLATE (tinfo);
+ if (!PRIMARY_TEMPLATE_P (underlying)
+ || (num_innermost_template_parms (tmpl)
+ != num_innermost_template_parms (underlying)))
+ break;
+
+ tree alias_args = INNERMOST_TEMPLATE_ARGS
+ (template_parms_to_args (DECL_TEMPLATE_PARMS (tmpl)));
+ if (!comp_template_args (TI_ARGS (tinfo), alias_args))
+ break;
+
+ /* Alias is equivalent. Strip it and repeat. */
+ tmpl = underlying;
}
+
return tmpl;
}
@@ -8375,9 +8379,8 @@ lookup_template_class_1 (tree d1, tree a
TEMPLATE will be `template <class T> template
<class U> struct S1<T>::S2'. We must fill in the missing
arguments. */
- arglist
- = add_outermost_template_args (TYPE_TI_ARGS (TREE_TYPE (templ)),
- arglist);
+ tree ti = TYPE_TEMPLATE_INFO_MAYBE_ALIAS (TREE_TYPE (templ));
+ arglist = add_outermost_template_args (TI_ARGS (ti), arglist);
arg_depth = TMPL_ARGS_DEPTH (arglist);
}
@@ -8407,13 +8410,15 @@ lookup_template_class_1 (tree d1, tree a
the `C<T>' is just the same as `C'. Outside of the
class, however, such a reference is an instantiation. */
- if ((entering_scope
- || !PRIMARY_TEMPLATE_P (gen_tmpl)
- || currently_open_class (template_type))
- /* comp_template_args is expensive, check it last. */
- && comp_template_args (TYPE_TI_ARGS (template_type),
- arglist))
- return template_type;
+ if (entering_scope
+ || !PRIMARY_TEMPLATE_P (gen_tmpl)
+ || currently_open_class (template_type))
+ {
+ tree tinfo = TYPE_TEMPLATE_INFO_MAYBE_ALIAS (template_type);
+
+ if (comp_template_args (TI_ARGS (tinfo), arglist))
+ return template_type;
+ }
/* If we already have this specialization, return it. */
elt.tmpl = gen_tmpl;
@@ -8641,12 +8646,11 @@ lookup_template_class_1 (tree d1, tree a
&& CLASS_TYPE_P (context)
&& !same_type_p (context, DECL_CONTEXT (gen_tmpl)))
{
- tree partial_inst_args;
TREE_VEC_LENGTH (arglist)--;
++processing_template_decl;
- partial_inst_args =
- tsubst (INNERMOST_TEMPLATE_ARGS
- (TYPE_TI_ARGS (TREE_TYPE (gen_tmpl))),
+ tree tinfo = TYPE_TEMPLATE_INFO_MAYBE_ALIAS (TREE_TYPE (gen_tmpl));
+ tree partial_inst_args =
+ tsubst (INNERMOST_TEMPLATE_ARGS (TI_ARGS (tinfo)),
arglist, complain, NULL_TREE);
--processing_template_decl;
TREE_VEC_LENGTH (arglist)++;
@@ -8678,11 +8682,11 @@ lookup_template_class_1 (tree d1, tree a
for parameters in the TYPE_DECL of the alias template
done earlier. So be careful while getting the template
of FOUND. */
- found = TREE_CODE (found) == TEMPLATE_DECL
- ? found
- : TREE_CODE (found) == TYPE_DECL
- ? TYPE_TI_TEMPLATE (TREE_TYPE (found))
- : CLASSTYPE_TI_TEMPLATE (found);
+ found = (TREE_CODE (found) == TEMPLATE_DECL
+ ? found
+ : (TREE_CODE (found) == TYPE_DECL
+ ? DECL_TI_TEMPLATE (found)
+ : CLASSTYPE_TI_TEMPLATE (found)));
}
// Build template info for the new specialization.
@@ -20035,10 +20039,13 @@ unify (tree tparms, tree targs, tree par
return unify_template_deduction_failure (explain_p, parm, arg);
{
tree parmvec = TYPE_TI_ARGS (parm);
+
/* An alias template name is never deduced. */
if (TYPE_ALIAS_P (arg))
arg = strip_typedefs (arg);
- tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg));
+
+ tree tinfo = TYPE_TEMPLATE_INFO_MAYBE_ALIAS (arg);
+ tree argvec = INNERMOST_TEMPLATE_ARGS (TI_ARGS (tinfo));
tree full_argvec = add_to_template_args (targs, argvec);
tree parm_parms
= DECL_INNERMOST_TEMPLATE_PARMS
===================================================================
@@ -0,0 +1,26 @@
+// PR c++/69481
+// { dg-do compile { target c++11 } }
+
+// ICE with canonical type verification
+
+template <typename> struct Traits;
+
+template <typename T>
+struct Bob {
+ using Loc = Traits<T>;
+ using typename Loc::Thing;
+
+ Thing Foo ();
+};
+
+template <class V> struct tt
+{
+ using ut = tt<V>;
+ ut Bob ();
+};
+
+template <class V>
+tt<V> tt<V>::Bob ()
+{
+ return tt();
+}
On 12/12/2016 10:28 PM, Jason Merrill wrote: > I suspect that most uses don't need to change. Indeed. This addresses the ones I could find. Both by grepping pt.c and fixing subsequent test fall out. took the opportunity to make the control flow in get_underlying_template somewhat clearer. I don't think there's anything unsurprising in this patch. ok? nathan -- Nathan Sidwell