diff mbox

C++ PATCH for c++/52043 (ICE with pack expansion)

Message ID 4F28237C.3000902@redhat.com
State New
Headers show

Commit Message

Jason Merrill Jan. 31, 2012, 5:23 p.m. UTC
The problem here is with tsubst_pack_expansion trying to decide whether 
or not to look at local_specializations.  Previously we checked 
cp_unevaluated_context, but that was wrong because some uses in 
trailing-return-types have the pack expansion outside the decltype. 
Then we checked at_function_scope_p(), but that turns out not to be 
right either, because we might be in a different function, or have 
already discarded local_specializations.  This patch fixes the check to 
use whether we were in a function when we parsed the expansion, which is 
more stable.

Tested x86_64-pc-linux-gnu, applying to trunk.
diff mbox

Patch

commit 480a0ab1c458357a701b7ae604b88c058b22d237
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Jan 31 11:10:21 2012 -0500

    	PR c++/52043
    	* cp-tree.h (PACK_EXPANSION_LOCAL_P): New.
    	* pt.c (make_pack_expansion, tsubst_initializer_list): Set it.
    	(tsubst_pack_expansion): Check it.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index f27755e..d435dbd 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -76,6 +76,7 @@  c-common.h, not after.
       TRANSACTION_EXPR_IS_STMT (in TRANSACTION_EXPR)
       CONVERT_EXPR_VBASE_PATH (in CONVERT_EXPR)
       OVL_ARG_DEPENDENT (in OVERLOAD)
+      PACK_EXPANSION_LOCAL_P (in *_PACK_EXPANSION)
    1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
       TI_PENDING_TEMPLATE_FLAG.
       TEMPLATE_PARMS_FOR_INLINE.
@@ -2839,6 +2840,9 @@  extern void decl_shadowed_for_var_insert (tree, tree);
     ? &TYPE_MAXVAL (NODE)			\
     : &TREE_OPERAND ((NODE), 2))
 
+/* True iff this pack expansion is within a function context.  */
+#define PACK_EXPANSION_LOCAL_P(NODE) TREE_LANG_FLAG_0 (NODE)
+
 /* Determine if this is an argument pack.  */
 #define ARGUMENT_PACK_P(NODE)                          \
   (TREE_CODE (NODE) == TYPE_ARGUMENT_PACK              \
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index ad2b4df..4c93b31 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -3238,6 +3238,8 @@  make_pack_expansion (tree arg)
     }
   PACK_EXPANSION_PARAMETER_PACKS (result) = parameter_packs;
 
+  PACK_EXPANSION_LOCAL_P (result) = at_function_scope_p ();
+
   return result;
 }
 
@@ -9340,7 +9342,7 @@  tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
        }
       if (TREE_CODE (parm_pack) == PARM_DECL)
 	{
-	  if (at_function_scope_p ())
+	  if (PACK_EXPANSION_LOCAL_P (t))
 	    arg_pack = retrieve_local_specialization (parm_pack);
 	  else
 	    {
@@ -18905,6 +18907,7 @@  tsubst_initializer_list (tree t, tree argvec)
           /* Build a dummy EXPR_PACK_EXPANSION that will be used to
              expand each argument in the TREE_VALUE of t.  */
           expr = make_node (EXPR_PACK_EXPANSION);
+	  PACK_EXPANSION_LOCAL_P (expr) = true;
           PACK_EXPANSION_PARAMETER_PACKS (expr) =
             PACK_EXPANSION_PARAMETER_PACKS (TREE_PURPOSE (t));
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic122.C b/gcc/testsuite/g++.dg/cpp0x/variadic122.C
new file mode 100644
index 0000000..6a1fb08
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic122.C
@@ -0,0 +1,22 @@ 
+// PR c++/52043
+// { dg-options "-std=c++11 -Wreturn-type" }
+
+template < class T > struct Container
+{
+  T f ();
+};
+
+template < class T >
+T deref (T)
+{}				// { dg-warning "no return" }
+
+template < class T, class ... Args >
+auto deref (T u, int, Args ... args)->decltype (deref (u.f (), args ...))
+{}				// { dg-warning "no return" }
+
+void 
+foo ()
+{
+  Container < Container < int > > v;
+  deref (v, 2);
+}