re PR c++/48969 (ICE with -std=c++0x)
PR c++/48969 * pt.c (deduction_tsubst_fntype): New. (fn_type_unification): Use it. From-SVN: r173741
This commit is contained in:
parent
4877e471e3
commit
b8f2ad7cc5
|
@ -1,5 +1,11 @@
|
|||
2011-05-13 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/48969
|
||||
* pt.c (deduction_tsubst_fntype): New.
|
||||
(fn_type_unification): Use it.
|
||||
(init_template_processing): Initialize hash table.
|
||||
(print_template_statistics): Print hash table stats.
|
||||
|
||||
* call.c (build_op_call): Use timevar_cond_start/stop.
|
||||
(build_user_type_conversion): Likewise.
|
||||
|
||||
|
|
59
gcc/cp/pt.c
59
gcc/cp/pt.c
|
@ -13525,6 +13525,53 @@ check_instantiated_args (tree tmpl, tree args, tsubst_flags_t complain)
|
|||
return result;
|
||||
}
|
||||
|
||||
static GTY((param_is (spec_entry))) htab_t current_deduction_substs;
|
||||
|
||||
/* In C++0x, it's possible to have a function template whose type depends
|
||||
on itself recursively. This is most obvious with decltype, but can also
|
||||
occur with enumeration scope (c++/48969). So we need to catch infinite
|
||||
recursion and reject the substitution at deduction time. */
|
||||
|
||||
static tree
|
||||
deduction_tsubst_fntype (tree fn, tree targs)
|
||||
{
|
||||
spec_entry **slot;
|
||||
spec_entry elt;
|
||||
tree r;
|
||||
hashval_t hash;
|
||||
|
||||
tree fntype = TREE_TYPE (fn);
|
||||
|
||||
/* We don't need to worry about this in C++98. */
|
||||
if (cxx_dialect < cxx0x)
|
||||
return tsubst (fntype, targs, tf_none, NULL_TREE);
|
||||
|
||||
elt.tmpl = fn;
|
||||
elt.args = targs;
|
||||
elt.spec = NULL_TREE;
|
||||
hash = hash_specialization (&elt);
|
||||
|
||||
slot = (spec_entry **)
|
||||
htab_find_slot_with_hash (current_deduction_substs, &elt, hash, INSERT);
|
||||
if (*slot)
|
||||
/* We already have an entry for this. */
|
||||
(*slot)->spec = r = error_mark_node;
|
||||
else
|
||||
{
|
||||
/* Create a new entry. */
|
||||
spec_entry *p = *slot = ggc_alloc_spec_entry ();
|
||||
*p = elt;
|
||||
|
||||
r = tsubst (fntype, targs, tf_none, NULL_TREE);
|
||||
if (p->spec == error_mark_node)
|
||||
r = error_mark_node;
|
||||
|
||||
htab_remove_elt_with_hash (current_deduction_substs, p, hash);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Instantiate the indicated variable or function template TMPL with
|
||||
the template arguments in TARG_PTR. */
|
||||
|
||||
|
@ -13788,7 +13835,7 @@ fn_type_unification (tree fn,
|
|||
incomplete = NUM_TMPL_ARGS (explicit_targs) != NUM_TMPL_ARGS (targs);
|
||||
|
||||
processing_template_decl += incomplete;
|
||||
fntype = tsubst (fntype, converted_args, tf_none, NULL_TREE);
|
||||
fntype = deduction_tsubst_fntype (fn, converted_args);
|
||||
processing_template_decl -= incomplete;
|
||||
|
||||
if (fntype == error_mark_node)
|
||||
|
@ -13859,7 +13906,7 @@ fn_type_unification (tree fn,
|
|||
substitution results in an invalid type, as described above,
|
||||
type deduction fails. */
|
||||
{
|
||||
tree substed = tsubst (TREE_TYPE (fn), targs, tf_none, NULL_TREE);
|
||||
tree substed = deduction_tsubst_fntype (fn, targs);
|
||||
if (substed == error_mark_node)
|
||||
return 1;
|
||||
|
||||
|
@ -19283,6 +19330,10 @@ init_template_processing (void)
|
|||
hash_specialization,
|
||||
eq_specializations,
|
||||
ggc_free);
|
||||
if (cxx_dialect >= cxx0x)
|
||||
current_deduction_substs = htab_create_ggc (37, hash_specialization,
|
||||
eq_specializations,
|
||||
ggc_free);
|
||||
}
|
||||
|
||||
/* Print stats about the template hash tables for -fstats. */
|
||||
|
@ -19298,6 +19349,10 @@ print_template_statistics (void)
|
|||
"%f collisions\n", (long) htab_size (type_specializations),
|
||||
(long) htab_elements (type_specializations),
|
||||
htab_collisions (type_specializations));
|
||||
fprintf (stderr, "current_deduction_substs: size %ld, %ld elements, "
|
||||
"%f collisions\n", (long) htab_size (current_deduction_substs),
|
||||
(long) htab_elements (current_deduction_substs),
|
||||
htab_collisions (current_deduction_substs));
|
||||
}
|
||||
|
||||
#include "gt-cp-pt.h"
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2011-05-13 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* g++.dg/cpp0x/decltype26.C: New.
|
||||
* g++.dg/cpp0x/enum11.C: New.
|
||||
|
||||
2011-05-13 Tobias Burnus <burnus@net-b.de>
|
||||
|
||||
PR fortran/48972
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
// { dg-options -std=c++0x }
|
||||
|
||||
struct A { };
|
||||
|
||||
template <class T>
|
||||
decltype(f(T())) f(T t)
|
||||
{
|
||||
return f(t);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
f(A()); // { dg-error "no match" }
|
||||
}
|
||||
|
||||
// { dg-prune-output "note" }
|
|
@ -0,0 +1,10 @@
|
|||
// PR c++/48969
|
||||
// { dg-options -std=c++0x }
|
||||
|
||||
template<unsigned int N> struct Pair { };
|
||||
struct Foo { enum { Mask = 1 }; } foo;
|
||||
template<typename A, typename B> class Pair<A::Mask | B::Mask>
|
||||
operator|(const A &, const B &)
|
||||
{ }
|
||||
|
||||
Pair<Foo::Mask> f = foo|foo;
|
Loading…
Reference in New Issue