From: Jason Merrill Date: Wed, 10 Jun 2015 15:17:57 +0000 (-0400) Subject: re PR c++/66289 ("error: ambiguous template instantiation" with partial specializatio... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1a4cd2cd7e7266b07e28fe4d127cfd6e6bac0916;p=gcc.git re PR c++/66289 ("error: ambiguous template instantiation" with partial specialization defined in terms of alias template) PR c++/66289 * cp-tree.h (TEMPLATE_DECL_COMPLEX_ALIAS_P): New. * pt.c (push_template_decl_real): Set it. (dependent_alias_template_spec_p): Use it. (dependent_type_p_r): Use dependent_alias_template_spec_p. (uses_all_template_parms_data, uses_all_template_parms_r) (complex_alias_template_p): New. (get_template_parm_index): Handle BOUND_TEMPLATE_TEMPLATE_PARM. From-SVN: r224331 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 35a13457b26..a3dd1db9157 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2015-06-10 Jason Merrill + + PR c++/66289 + * cp-tree.h (TEMPLATE_DECL_COMPLEX_ALIAS_P): New. + * pt.c (push_template_decl_real): Set it. + (dependent_alias_template_spec_p): Use it. + (dependent_type_p_r): Use dependent_alias_template_spec_p. + (uses_all_template_parms_data, uses_all_template_parms_r) + (complex_alias_template_p): New. + (get_template_parm_index): Handle BOUND_TEMPLATE_TEMPLATE_PARM. + 2015-06-09 Jason Merrill DR 1467 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 603a8718278..1eac6367d25 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -155,6 +155,7 @@ c-common.h, not after. LABEL_DECL_CONTINUE (in LABEL_DECL) 2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL). DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL) + TEMPLATE_DECL_COMPLEX_ALIAS_P (in TEMPLATE_DECL) 3: DECL_IN_AGGR_P. 4: DECL_C_BIT_FIELD (in a FIELD_DECL) DECL_ANON_UNION_VAR_P (in a VAR_DECL) @@ -2732,6 +2733,10 @@ extern void decl_shadowed_for_var_insert (tree, tree); #define TYPE_DECL_ALIAS_P(NODE) \ DECL_LANG_FLAG_6 (TYPE_DECL_CHECK (NODE)) +/* Nonzero for TEMPLATE_DECL means that it is a 'complex' alias template. */ +#define TEMPLATE_DECL_COMPLEX_ALIAS_P(NODE) \ + DECL_LANG_FLAG_2 (TEMPLATE_DECL_CHECK (NODE)) + /* Nonzero for a type which is an alias for another type; i.e, a type which declaration was written 'using name-of-type = another-type'. */ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 2ebeb658726..7f04fe618b4 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -211,6 +211,7 @@ static tree template_parm_to_arg (tree t); static tree current_template_args (void); static tree tsubst_template_parm (tree, tree, tsubst_flags_t); static tree instantiate_alias_template (tree, tree, tsubst_flags_t); +static bool complex_alias_template_p (const_tree tmpl); /* Make the current scope suitable for access checking when we are processing T. T can be FUNCTION_DECL for instantiated function @@ -4420,6 +4421,7 @@ get_template_parm_index (tree parm) || TREE_CODE (parm) == TEMPLATE_DECL) parm = TREE_TYPE (parm); if (TREE_CODE (parm) == TEMPLATE_TYPE_PARM + || TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM || TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM) parm = TEMPLATE_TYPE_PARM_INDEX (parm); gcc_assert (TREE_CODE (parm) == TEMPLATE_PARM_INDEX); @@ -5096,6 +5098,11 @@ template arguments to %qD do not match original template %qD", if (TREE_CODE (parm) == TEMPLATE_DECL) DECL_CONTEXT (parm) = tmpl; } + + if (TREE_CODE (decl) == TYPE_DECL + && TYPE_DECL_ALIAS_P (decl) + && complex_alias_template_p (tmpl)) + TEMPLATE_DECL_COMPLEX_ALIAS_P (tmpl) = true; } /* The DECL_TI_ARGS of DECL contains full set of arguments referring @@ -5353,13 +5360,56 @@ alias_template_specialization_p (const_tree t) return false; } -/* Return TRUE iff T is a specialization of an alias template with +/* An alias template is complex from a SFINAE perspective if a template-id + using that alias can be ill-formed when the expansion is not, as with + the void_t template. We determine this by checking whether the + expansion for the alias template uses all its template parameters. */ + +struct uses_all_template_parms_data +{ + int level; + bool *seen; +}; + +static int +uses_all_template_parms_r (tree t, void *data_) +{ + struct uses_all_template_parms_data &data + = *(struct uses_all_template_parms_data*)data_; + tree idx = get_template_parm_index (t); + + if (TEMPLATE_PARM_LEVEL (idx) == data.level) + data.seen[TEMPLATE_PARM_IDX (idx)] = true; + return 0; +} + +static bool +complex_alias_template_p (const_tree tmpl) +{ + struct uses_all_template_parms_data data; + tree pat = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (tmpl)); + tree parms = DECL_TEMPLATE_PARMS (tmpl); + data.level = TMPL_PARMS_DEPTH (parms); + int len = TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS (parms)); + data.seen = XALLOCAVEC (bool, len); + for (int i = 0; i < len; ++i) + data.seen[i] = false; + + for_each_template_parm (pat, uses_all_template_parms_r, &data, NULL, true); + for (int i = 0; i < len; ++i) + if (!data.seen[i]) + return true; + return false; +} + +/* Return TRUE iff T is a specialization of a complex alias template with dependent template-arguments. */ 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))))); } @@ -20951,9 +21001,7 @@ dependent_type_p_r (tree type) return true; /* For an alias template specialization, check the arguments both to the class template and the alias template. */ - else if (alias_template_specialization_p (type) - && (any_dependent_template_arguments_p - (INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (type))))) + else if (dependent_alias_template_spec_p (type)) return true; /* All TYPEOF_TYPEs, DECLTYPE_TYPEs, and UNDERLYING_TYPEs are diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-48.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-48.C new file mode 100644 index 00000000000..8d5eb23de8b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-48.C @@ -0,0 +1,13 @@ +// PR c++/66289 +// { dg-do compile { target c++11 } } + +template struct A {}; + +template struct shared_ptr { }; +template using APtr = shared_ptr>; + +template struct foo; +template struct foo> { }; +template struct foo> { }; + +foo>> aa;