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
This commit is contained in:
parent
8de22ea0b1
commit
270430ff3e
@ -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
|
||||
|
65
gcc/cp/pt.c
65
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)
|
||||
|
23
gcc/testsuite/g++.dg/cpp0x/initlist-template2.C
Normal file
23
gcc/testsuite/g++.dg/cpp0x/initlist-template2.C
Normal file
@ -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" }
|
@ -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" }
|
||||
|
Loading…
Reference in New Issue
Block a user