PR c++/43382
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 26 May 2010 15:00:02 +0000 (15:00 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 26 May 2010 15:00:02 +0000 (15:00 +0000)
* pt.c (fn_type_unification): Don't get confused by recursive
unification.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@159873 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/variadic101.C [new file with mode: 0644]

index ff3bc5f..3ad1aaf 100644 (file)
@@ -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.
index 6c9f31d..fd34d9f 100644 (file)
@@ -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;
index a319f63..a163beb 100644 (file)
@@ -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 (file)
index 0000000..445a770
--- /dev/null
@@ -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);
+}