PR c++/71711 - mangle C++1z fold-expressions.
authorJason Merrill <jason@redhat.com>
Fri, 15 Jul 2016 18:38:23 +0000 (14:38 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 15 Jul 2016 18:38:23 +0000 (14:38 -0400)
* operators.def: Add *_FOLD_EXPR.
* cp-tree.h (FOLD_EXPR_P): Parenthesize.
* mangle.c (write_expression): Handle fold-expressions.
* pt.c (tsubst_unary_left_fold, tsubst_binary_left_fold)
(tsubst_unary_right_fold, tsubst_binary_right_fold): Handle
partial instantiation.

From-SVN: r238390

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/mangle.c
gcc/cp/operators.def
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp1z/fold-mangle.C [new file with mode: 0644]

index eb4f0b93531eccfee9f98451955322ed019c8cde..d0d855ec088ed9b268498747ca9b8ac7b4c77313 100644 (file)
@@ -1,5 +1,13 @@
 2016-07-15  Jason Merrill  <jason@redhat.com>
 
+       PR c++/71711
+       * operators.def: Add *_FOLD_EXPR.
+       * cp-tree.h (FOLD_EXPR_P): Parenthesize.
+       * mangle.c (write_expression): Handle fold-expressions.
+       * pt.c (tsubst_unary_left_fold, tsubst_binary_left_fold)
+       (tsubst_unary_right_fold, tsubst_binary_right_fold): Handle
+       partial instantiation.
+
        PR c++/71814
        * mangle.c (write_expression): Handle sizeof... an argument pack.
 
index 74b8c7c7963ca5a2c2519c03b0711c69fe14d520..7e84036a893200c73b6c70cf3631737c0ad6b3ed 100644 (file)
@@ -3334,11 +3334,11 @@ extern void decl_shadowed_for_var_insert (tree, tree);
   TREE_CHECK2 (NODE, BINARY_LEFT_FOLD_EXPR, BINARY_RIGHT_FOLD_EXPR)
 
 /* True if NODE is UNARY_FOLD_EXPR or a BINARY_FOLD_EXPR */
-#define FOLD_EXPR_P(NODE) \
-  TREE_CODE (NODE) == UNARY_LEFT_FOLD_EXPR \
-    || TREE_CODE (NODE) == UNARY_RIGHT_FOLD_EXPR \
-    || TREE_CODE (NODE) == BINARY_LEFT_FOLD_EXPR \
-    || TREE_CODE (NODE) == BINARY_RIGHT_FOLD_EXPR
+#define FOLD_EXPR_P(NODE)                              \
+  (TREE_CODE (NODE) == UNARY_LEFT_FOLD_EXPR            \
+   || TREE_CODE (NODE) == UNARY_RIGHT_FOLD_EXPR                \
+   || TREE_CODE (NODE) == BINARY_LEFT_FOLD_EXPR                \
+   || TREE_CODE (NODE) == BINARY_RIGHT_FOLD_EXPR)
 
 /* True when NODE is a fold over a compound assignment operator. */
 #define FOLD_EXPR_MODIFY_P(NODE) \
index 8205da92a31fcabbc176f5059ade27b6dd9f5af5..d5b26d64d8e4421f86c95c9a16ef3f287563eb8e 100644 (file)
@@ -3145,6 +3145,29 @@ write_expression (tree expr)
                         "cannot be mangled");
                  continue;
                }
+             else if (FOLD_EXPR_P (expr))
+               {
+                 /* The first 'operand' of a fold-expression is the operator
+                    that it folds over.  */
+                 if (i == 0)
+                   {
+                     int fcode = TREE_INT_CST_LOW (operand);
+                     write_string (operator_name_info[fcode].mangled_name);
+                     continue;
+                   }
+                 else if (code == BINARY_LEFT_FOLD_EXPR)
+                   {
+                     /* The order of operands of the binary left and right
+                        folds is the same, but we want to mangle them in
+                        lexical order, i.e. non-pack first.  */
+                     if (i == 1)
+                       operand = FOLD_EXPR_INIT (expr);
+                     else
+                       operand = FOLD_EXPR_PACK (expr);
+                   }
+                 if (PACK_EXPANSION_P (operand))
+                   operand = PACK_EXPANSION_PATTERN (operand);
+               }
              write_expression (operand);
            }
        }
index aa657fad5625d3acdb812c8a1dc1062e2791a337..5b4f1b0be2a0983d1e10c2d1fd4d9fc09e1a4fda 100644 (file)
@@ -155,3 +155,7 @@ DEF_SIMPLE_OPERATOR ("()", CALL_EXPR, "cl", -1)
 
 /* Variadic templates extension. */
 DEF_SIMPLE_OPERATOR ("...", EXPR_PACK_EXPANSION, "sp", 1)
+DEF_SIMPLE_OPERATOR ("... +", UNARY_LEFT_FOLD_EXPR, "fl", 2)
+DEF_SIMPLE_OPERATOR ("+ ...", UNARY_RIGHT_FOLD_EXPR, "fr", 2)
+DEF_SIMPLE_OPERATOR ("+ ... +", BINARY_LEFT_FOLD_EXPR, "fL", 3)
+DEF_SIMPLE_OPERATOR ("+ ... +", BINARY_RIGHT_FOLD_EXPR, "fR", 3)
index 73b53e23b4d68fbc9bfc7423ce89ca13987a9d04..de70fb2f1c6104595e986dd1ab1cb2f01f07bd2e 100644 (file)
@@ -10791,6 +10791,12 @@ tsubst_unary_left_fold (tree t, tree args, tsubst_flags_t complain,
   tree pack = tsubst_fold_expr_pack (t, args, complain, in_decl);
   if (pack == error_mark_node)
     return error_mark_node;
+  if (PACK_EXPANSION_P (pack))
+    {
+      tree r = copy_node (t);
+      FOLD_EXPR_PACK (r) = pack;
+      return r;
+    }
   if (TREE_VEC_LENGTH (pack) == 0)
     return expand_empty_fold (t, complain);
   else
@@ -10813,6 +10819,14 @@ tsubst_binary_left_fold (tree t, tree args, tsubst_flags_t complain,
   if (init == error_mark_node)
     return error_mark_node;
 
+  if (PACK_EXPANSION_P (pack))
+    {
+      tree r = copy_node (t);
+      FOLD_EXPR_PACK (r) = pack;
+      FOLD_EXPR_INIT (r) = init;
+      return r;
+    }
+
   tree vec = make_tree_vec (TREE_VEC_LENGTH (pack) + 1);
   TREE_VEC_ELT (vec, 0) = init;
   for (int i = 0; i < TREE_VEC_LENGTH (pack); ++i)
@@ -10854,6 +10868,12 @@ tsubst_unary_right_fold (tree t, tree args, tsubst_flags_t complain,
   tree pack = tsubst_fold_expr_pack (t, args, complain, in_decl);
   if (pack == error_mark_node)
     return error_mark_node;
+  if (PACK_EXPANSION_P (pack))
+    {
+      tree r = copy_node (t);
+      FOLD_EXPR_PACK (r) = pack;
+      return r;
+    }
   if (TREE_VEC_LENGTH (pack) == 0)
     return expand_empty_fold (t, complain);
   else
@@ -10876,6 +10896,14 @@ tsubst_binary_right_fold (tree t, tree args, tsubst_flags_t complain,
   if (init == error_mark_node)
     return error_mark_node;
 
+  if (PACK_EXPANSION_P (pack))
+    {
+      tree r = copy_node (t);
+      FOLD_EXPR_PACK (r) = pack;
+      FOLD_EXPR_INIT (r) = init;
+      return r;
+    }
+
   int n = TREE_VEC_LENGTH (pack);
   tree vec = make_tree_vec (n + 1);
   for (int i = 0; i < n; ++i)
diff --git a/gcc/testsuite/g++.dg/cpp1z/fold-mangle.C b/gcc/testsuite/g++.dg/cpp1z/fold-mangle.C
new file mode 100644 (file)
index 0000000..1a8f16c
--- /dev/null
@@ -0,0 +1,20 @@
+// PR c++/71711
+// { dg-options -std=c++1z }
+
+template < int > struct A {};
+template < int ... N > void unary_left (A < (... + N) >);
+template < int ... N > void unary_right (A < (N + ...) >);
+template < int ... N > void binary_left (A < (42 + ... + N) >);
+template < int ... N > void binary_right (A < (N + ... + 42) >);
+
+void bar ()  
+{
+  // { dg-final { scan-assembler "_Z10unary_leftIJLi1ELi2ELi3EEEv1AIXflplT_EE" } }
+  unary_left < 1, 2, 3 > ({});
+  // { dg-final { scan-assembler "_Z11unary_rightIJLi1ELi2ELi3EEEv1AIXfrplT_EE" } }
+  unary_right < 1, 2, 3 > ({});
+  // { dg-final { scan-assembler "_Z11binary_leftIJLi1ELi2ELi3EEEv1AIXfLplLi42ET_EE" } }
+  binary_left < 1, 2, 3 > ({});
+  // { dg-final { scan-assembler "_Z12binary_rightIJLi1ELi2ELi3EEEv1AIXfRplT_Li42EEE" } }
+  binary_right < 1, 2, 3 > ({});
+}