aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2016-07-15 14:38:23 -0400
committerJason Merrill <jason@gcc.gnu.org>2016-07-15 14:38:23 -0400
commitaa30dfadf3234caa8a29ef23ddc5932101a0e430 (patch)
tree570594e330f0c11c2307922ac7864b02d6a70bdd
parent34bbc4c502157fb08e6eba1d09380e2599ec3720 (diff)
downloadgcc-aa30dfadf3234caa8a29ef23ddc5932101a0e430.zip
gcc-aa30dfadf3234caa8a29ef23ddc5932101a0e430.tar.gz
gcc-aa30dfadf3234caa8a29ef23ddc5932101a0e430.tar.bz2
PR c++/71711 - mangle C++1z fold-expressions.
* 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
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/cp-tree.h10
-rw-r--r--gcc/cp/mangle.c23
-rw-r--r--gcc/cp/operators.def4
-rw-r--r--gcc/cp/pt.c28
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/fold-mangle.C20
6 files changed, 88 insertions, 5 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index eb4f0b9..d0d855e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 74b8c7c..7e84036 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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) \
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 8205da9..d5b26d6 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -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);
}
}
diff --git a/gcc/cp/operators.def b/gcc/cp/operators.def
index aa657fa..5b4f1b0 100644
--- a/gcc/cp/operators.def
+++ b/gcc/cp/operators.def
@@ -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)
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 73b53e2..de70fb2 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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
index 0000000..1a8f16c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/fold-mangle.C
@@ -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 > ({});
+}