diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 56803bf7748..24ceb04ce57 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2016-12-13 Nathan Sidwell + + 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. + 2016-12-11 Paolo Carlini PR c++/78637 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index f7da76a8e81..cc7ca87376f 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3038,23 +3038,30 @@ extern void decl_shadowed_for_var_insert (tree, tree); ->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)) \ + ? DECL_TEMPLATE_INFO (TYPE_NAME (NODE)) \ + : TYPE_TEMPLATE_INFO (NODE)) /* Set the template information for an ENUMERAL_, RECORD_, or UNION_TYPE to VAL. */ diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 5f8fb2a1838..d025fcb5fa3 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -365,15 +365,13 @@ dump_template_bindings (cxx_pretty_printer *pp, tree parms, tree args, 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); } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 97d0b4840fc..bae96ec9d22 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -940,10 +940,11 @@ maybe_process_partial_specialization (tree type) 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, hashval_t val) // 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 *walk_subtrees, void* data) /* 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_tree 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 tmpl) 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 arglist, tree in_decl, tree context, TEMPLATE will be `template template struct S1::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 arglist, tree in_decl, tree context, the `C' 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 arglist, tree in_decl, tree context, && 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 arglist, tree in_decl, tree context, 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,9 +20039,6 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, 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 full_argvec = add_to_template_args (targs, argvec); tree parm_parms diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 072e617415a..4378e36bbe7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-12-13 Nathan Sidwell + + PR c++/69481 + * g++.dg/cpp0x/pr69481.C: New. + 2016-12-13 Uros Bizjak PR target/78794 diff --git a/gcc/testsuite/g++.dg/cpp0x/pr69481.C b/gcc/testsuite/g++.dg/cpp0x/pr69481.C new file mode 100644 index 00000000000..bab166b70ae --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr69481.C @@ -0,0 +1,26 @@ +// PR c++/69481 +// { dg-do compile { target c++11 } } + +// ICE with canonical type verification + +template struct Traits; + +template +struct Bob { + using Loc = Traits; + using typename Loc::Thing; + + Thing Foo (); +}; + +template struct tt +{ + using ut = tt; + ut Bob (); +}; + +template +tt tt::Bob () +{ + return tt(); +}