diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/pt.c | 30 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/variadic101.C | 23 |
4 files changed, 51 insertions, 13 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ff3bc5f..3ad1aaf 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2010-05-26 Jason Merrill <jason@redhat.com> + + PR c++/43382 + * pt.c (fn_type_unification): Don't get confused by recursive + unification. + 2010-05-26 Steven Bosscher <steven@gcc.gnu.org> * cp-lang.c: Do not include expr.h. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 6c9f31d..fd34d9f 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -8251,7 +8251,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, int i, len = -1; tree result; int incomplete = 0; - bool very_local_specializations = false; + htab_t saved_local_specializations = NULL; gcc_assert (PACK_EXPANSION_P (t)); pattern = PACK_EXPANSION_PATTERN (t); @@ -8269,13 +8269,15 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, if (TREE_CODE (parm_pack) == PARM_DECL) { - arg_pack = retrieve_local_specialization (parm_pack); - if (arg_pack == NULL_TREE) + if (!cp_unevaluated_operand) + arg_pack = retrieve_local_specialization (parm_pack); + else { - /* This can happen for a parameter name used later in a function - declaration (such as in a late-specified return type). Just - make a dummy decl, since it's only used for its type. */ - gcc_assert (cp_unevaluated_operand != 0); + /* We can't rely on local_specializations for a parameter + name used later in a function declaration (such as in a + late-specified return type). Even if it exists, it might + have the wrong value for a recursive call. Just make a + dummy decl, since it's only used for its type. */ arg_pack = tsubst_decl (parm_pack, args, complain); arg_pack = make_fnparm_pack (arg_pack); } @@ -8381,11 +8383,13 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, if (len < 0) return error_mark_node; - if (!local_specializations) + if (cp_unevaluated_operand) { - /* We're in a late-specified return type, so we don't have a local - specializations table. Create one for doing this expansion. */ - very_local_specializations = true; + /* We're in a late-specified return type, so create our own local + specializations table; the current table is either NULL or (in the + case of recursive unification) might have bindings that we don't + want to use or alter. */ + saved_local_specializations = local_specializations; local_specializations = htab_create (37, hash_local_specialization, eq_local_specializations, @@ -8476,10 +8480,10 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, } } - if (very_local_specializations) + if (saved_local_specializations) { htab_delete (local_specializations); - local_specializations = NULL; + local_specializations = saved_local_specializations; } return result; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a319f63..a163beb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-05-26 Jason Merrill <jason@redhat.com> + + PR c++/43382 + * g++.dg/cpp0x/variadic101.C: New. + 2010-05-26 Richard Guenther <rguenther@suse.de> PR rtl-optimization/44164 diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic101.C b/gcc/testsuite/g++.dg/cpp0x/variadic101.C new file mode 100644 index 0000000..445a770 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic101.C @@ -0,0 +1,23 @@ +// PR c++/43382 +// { dg-options "-std=c++0x" } + +template<class T> +struct Container +{ T f() const; }; + +template<class T> +T deref(const T& t) +{ return t; } + + +template <class T, class... Args> +auto +deref(const T& u, int r, Args... args) +-> decltype(deref(u.f(), args...)) +{ return deref(u.f(), args...); } + +int main(void) +{ + Container<Container<int>> v; + deref(v,1,2); +} |