diff options
author | Jason Merrill <jason@redhat.com> | 2015-06-10 11:17:57 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2015-06-10 11:17:57 -0400 |
commit | 1a4cd2cd7e7266b07e28fe4d127cfd6e6bac0916 (patch) | |
tree | 22325591562920d7d55ce475ed6285db1487f725 /gcc | |
parent | 768b666466931611b0b39f125cb0645b1cf3d102 (diff) | |
download | gcc-1a4cd2cd7e7266b07e28fe4d127cfd6e6bac0916.zip gcc-1a4cd2cd7e7266b07e28fe4d127cfd6e6bac0916.tar.gz gcc-1a4cd2cd7e7266b07e28fe4d127cfd6e6bac0916.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 5 | ||||
-rw-r--r-- | gcc/cp/pt.c | 56 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/alias-decl-48.C | 13 |
4 files changed, 81 insertions, 4 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 35a1345..a3dd1db 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2015-06-10 Jason Merrill <jason@redhat.com> + + 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 <jason@redhat.com> DR 1467 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 603a871..1eac636 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 2ebeb65..7f04fe6 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 0000000..8d5eb23 --- /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<typename T> struct A {}; + +template<typename T> struct shared_ptr { }; +template<typename T> using APtr = shared_ptr<A<T>>; + +template<typename T> struct foo; +template<typename T> struct foo<shared_ptr<T>> { }; +template<typename T> struct foo<APtr<T>> { }; + +foo<shared_ptr<A<int>>> aa; |