diff options
author | Jason Merrill <jason@redhat.com> | 2016-07-27 10:31:30 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2016-07-27 10:31:30 -0400 |
commit | 270430ff3eb2632320372e6974ce9ef7038e31d2 (patch) | |
tree | a1799237fa9426cb2869bdb2fc49a23d865b5afa /gcc | |
parent | 8de22ea0b15dbfdb61461d8732b05c9ce9ce0f48 (diff) | |
download | gcc-270430ff3eb2632320372e6974ce9ef7038e31d2.zip gcc-270430ff3eb2632320372e6974ce9ef7038e31d2.tar.gz gcc-270430ff3eb2632320372e6974ce9ef7038e31d2.tar.bz2 |
PR c++/71747 - ICE with self-referential partial spec
* pt.c (get_partial_spec_bindings): Replace tparms and spec_args
parameters with spec_tmpl. Call push_tinst_level.
(most_specialized_partial_spec): Adjust.
(more_specialized_partial_spec): Adjust.
From-SVN: r238785
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/pt.c | 65 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/initlist-template2.C | 23 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/pr55843.C | 9 |
4 files changed, 61 insertions, 44 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0e3e826..99c7c28 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2016-07-27 Jason Merrill <jason@redhat.com> + + PR c++/71747 + * pt.c (get_partial_spec_bindings): Replace tparms and spec_args + parameters with spec_tmpl. Call push_tinst_level. + (most_specialized_partial_spec): Adjust. + (more_specialized_partial_spec): Adjust. + 2016-07-25 Jason Merrill <jason@redhat.com> PR c++/65970 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 97d5000..a23a05a 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -140,7 +140,7 @@ static int unify (tree, tree, tree, tree, int, bool); static void add_pending_template (tree); static tree reopen_tinst_level (struct tinst_level *); static tree tsubst_initializer_list (tree, tree); -static tree get_partial_spec_bindings (tree, tree, tree, tree); +static tree get_partial_spec_bindings (tree, tree, tree); static tree coerce_template_parms (tree, tree, tree, tsubst_flags_t, bool, bool); static tree coerce_innermost_template_parms (tree, tree, tree, tsubst_flags_t, @@ -20689,8 +20689,6 @@ more_specialized_partial_spec (tree tmpl, tree pat1, tree pat2) tree tmpl1 = TREE_VALUE (pat1); tree tmpl2 = TREE_VALUE (pat2); - tree parms1 = DECL_INNERMOST_TEMPLATE_PARMS (tmpl1); - tree parms2 = DECL_INNERMOST_TEMPLATE_PARMS (tmpl2); tree specargs1 = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (tmpl1))); tree specargs2 = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (tmpl2))); @@ -20699,14 +20697,14 @@ more_specialized_partial_spec (tree tmpl, tree pat1, tree pat2) types in the arguments, and we need our dependency check functions to behave correctly. */ ++processing_template_decl; - targs = get_partial_spec_bindings (tmpl, parms1, specargs1, specargs2); + targs = get_partial_spec_bindings (tmpl, tmpl1, specargs2); if (targs) { --winner; any_deductions = true; } - targs = get_partial_spec_bindings (tmpl, parms2, specargs2, specargs1); + targs = get_partial_spec_bindings (tmpl, tmpl2, specargs1); if (targs) { ++winner; @@ -20790,23 +20788,23 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype) } /* Return the innermost template arguments that, when applied to a partial - specialization of TMPL whose innermost template parameters are - TPARMS, and whose specialization arguments are SPEC_ARGS, yield the - ARGS. + specialization SPEC_TMPL of TMPL, yield the ARGS. For example, suppose we have: template <class T, class U> struct S {}; template <class T> struct S<T*, int> {}; - Then, suppose we want to get `S<double*, int>'. The TPARMS will be - {T}, the SPEC_ARGS will be {T*, int} and the ARGS will be {double*, - int}. The resulting vector will be {double}, indicating that `T' - is bound to `double'. */ + Then, suppose we want to get `S<double*, int>'. SPEC_TMPL will be the + partial specialization and the ARGS will be {double*, int}. The resulting + vector will be {double}, indicating that `T' is bound to `double'. */ static tree -get_partial_spec_bindings (tree tmpl, tree tparms, tree spec_args, tree args) +get_partial_spec_bindings (tree tmpl, tree spec_tmpl, tree args) { + tree tparms = DECL_INNERMOST_TEMPLATE_PARMS (spec_tmpl); + tree spec_args + = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (spec_tmpl))); int i, ntparms = TREE_VEC_LENGTH (tparms); tree deduced_args; tree innermost_deduced_args; @@ -20832,6 +20830,13 @@ get_partial_spec_bindings (tree tmpl, tree tparms, tree spec_args, tree args) if (! TREE_VEC_ELT (innermost_deduced_args, i)) return NULL_TREE; + tree tinst = build_tree_list (spec_tmpl, deduced_args); + if (!push_tinst_level (tinst)) + { + excessive_deduction_depth = true; + return NULL_TREE; + } + /* Verify that nondeduced template arguments agree with the type obtained from argument deduction. @@ -20848,6 +20853,9 @@ get_partial_spec_bindings (tree tmpl, tree tparms, tree spec_args, tree args) spec_args = coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (tmpl), spec_args, tmpl, tf_none, false, false); + + pop_tinst_level (); + if (spec_args == error_mark_node /* We only need to check the innermost arguments; the other arguments will always agree. */ @@ -21057,44 +21065,21 @@ most_specialized_partial_spec (tree target, tsubst_flags_t complain) for (t = DECL_TEMPLATE_SPECIALIZATIONS (main_tmpl); t; t = TREE_CHAIN (t)) { - tree partial_spec_args; tree spec_args; tree spec_tmpl = TREE_VALUE (t); - partial_spec_args = TREE_PURPOSE (t); - - ++processing_template_decl; - if (outer_args) { - /* Discard the outer levels of args, and then substitute in the - template args from the enclosing class. */ - partial_spec_args = INNERMOST_TEMPLATE_ARGS (partial_spec_args); - partial_spec_args = tsubst_template_args - (partial_spec_args, outer_args, tf_none, NULL_TREE); - - /* And the same for the partial specialization TEMPLATE_DECL. */ + /* Substitute in the template args from the enclosing class. */ + ++processing_template_decl; spec_tmpl = tsubst (spec_tmpl, outer_args, tf_none, NULL_TREE); + --processing_template_decl; } - partial_spec_args = - coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (tmpl), - partial_spec_args, - tmpl, tf_none, - /*require_all_args=*/true, - /*use_default_args=*/true); - - --processing_template_decl; - - if (partial_spec_args == error_mark_node) - return error_mark_node; if (spec_tmpl == error_mark_node) return error_mark_node; - tree parms = DECL_INNERMOST_TEMPLATE_PARMS (spec_tmpl); - spec_args = get_partial_spec_bindings (tmpl, parms, - partial_spec_args, - args); + spec_args = get_partial_spec_bindings (tmpl, spec_tmpl, args); if (spec_args) { if (outer_args) diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-template2.C b/gcc/testsuite/g++.dg/cpp0x/initlist-template2.C new file mode 100644 index 0000000..40e3075 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-template2.C @@ -0,0 +1,23 @@ +// PR c++/71747 +// { dg-do compile { target c++11 } } +// { dg-options -ftemplate-depth=20 } + +template < bool > struct A +{ + typedef int type; + constexpr bool operator() () const + { + return true; + } +}; + +template < bool, typename = int > struct F; +template < bool X > +// should be: struct F < X, typename A < A < X > {} () >::type > +struct F < X, typename A < F < X > {} () >::type > // { dg-error "" } +{ +}; + +F < true > f; + +// { dg-prune-output "compilation terminated" } diff --git a/gcc/testsuite/g++.dg/template/pr55843.C b/gcc/testsuite/g++.dg/template/pr55843.C index e1691d5..467dd82 100644 --- a/gcc/testsuite/g++.dg/template/pr55843.C +++ b/gcc/testsuite/g++.dg/template/pr55843.C @@ -7,11 +7,11 @@ template<bool b> struct if_c { }; template< typename T > struct has_type { struct gcc_3_2_wknd { - template< typename U > static yes_tag test( type_wrapper<U> const volatile* + template< typename U > static yes_tag test( type_wrapper<U> const volatile* // { dg-message "required" } , type_wrapper<typename U::type>* = 0 ); }; typedef type_wrapper<T> t_; - static const bool value = sizeof(gcc_3_2_wknd::test(static_cast<t_*>(0))) == + static const bool value = sizeof(gcc_3_2_wknd::test(static_cast<t_*>(0))) == // { dg-message "required" } sizeof(yes_tag); }; template <class K, class T, class=void> struct Get_type { @@ -19,9 +19,10 @@ template <class K, class T, class=void> struct Get_type { struct FT_tag {}; struct RT_tag {}; template <class K> struct Get_type<K, RT_tag, typename if_c< -!has_type<Get_type<K, FT_tag> >::value >::type> { }; +!has_type<Get_type<K, FT_tag> >::value >::type> { }; // { dg-message "required" } template <class K> struct Get_type<K, FT_tag, typename if_c< -!has_type<Get_type<K, RT_tag> >::value >::type> { }; // { dg-error "depth" } +!has_type<Get_type<K, RT_tag> >::value >::type> { }; // { dg-message "required" } typedef Get_type<int, FT_tag>::type P; +// { dg-prune-output "-ftemplate-depth" } // { dg-prune-output "compilation terminated" } |