aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/pt.c30
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic101.C23
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);
+}