+/* If DC is a C++17 fold-expression, print it and return true; otherwise
+ return false. */
+
+static int
+d_maybe_print_fold_expression (struct d_print_info *dpi, int options,
+ struct demangle_component *dc)
+{
+ struct demangle_component *ops, *operator_, *op1, *op2;
+ int save_idx;
+
+ const char *fold_code = d_left (dc)->u.s_operator.op->code;
+ if (fold_code[0] != 'f')
+ return 0;
+
+ ops = d_right (dc);
+ operator_ = d_left (ops);
+ op1 = d_right (ops);
+ op2 = 0;
+ if (op1->type == DEMANGLE_COMPONENT_TRINARY_ARG2)
+ {
+ op2 = d_right (op1);
+ op1 = d_left (op1);
+ }
+
+ /* Print the whole pack. */
+ save_idx = dpi->pack_index;
+ dpi->pack_index = -1;
+
+ switch (fold_code[1])
+ {
+ /* Unary left fold, (... + X). */
+ case 'l':
+ d_append_string (dpi, "(...");
+ d_print_expr_op (dpi, options, operator_);
+ d_print_subexpr (dpi, options, op1);
+ d_append_char (dpi, ')');
+ break;
+
+ /* Unary right fold, (X + ...). */
+ case 'r':
+ d_append_char (dpi, '(');
+ d_print_subexpr (dpi, options, op1);
+ d_print_expr_op (dpi, options, operator_);
+ d_append_string (dpi, "...)");
+ break;
+
+ /* Binary left fold, (42 + ... + X). */
+ case 'L':
+ /* Binary right fold, (X + ... + 42). */
+ case 'R':
+ d_append_char (dpi, '(');
+ d_print_subexpr (dpi, options, op1);
+ d_print_expr_op (dpi, options, operator_);
+ d_append_string (dpi, "...");
+ d_print_expr_op (dpi, options, operator_);
+ d_print_subexpr (dpi, options, op2);
+ d_append_char (dpi, ')');
+ break;
+ }
+
+ dpi->pack_index = save_idx;
+ return 1;
+}
+
+/* True iff DC represents a C99-style designated initializer. */
+
+static int
+is_designated_init (struct demangle_component *dc)
+{
+ if (dc->type != DEMANGLE_COMPONENT_BINARY
+ && dc->type != DEMANGLE_COMPONENT_TRINARY)
+ return 0;
+
+ struct demangle_component *op = d_left (dc);
+ const char *code = op->u.s_operator.op->code;
+ return (code[0] == 'd'
+ && (code[1] == 'i' || code[1] == 'x' || code[1] == 'X'));
+}
+
+/* If DC represents a C99-style designated initializer, print it and return
+ true; otherwise, return false. */
+
+static int
+d_maybe_print_designated_init (struct d_print_info *dpi, int options,
+ struct demangle_component *dc)
+{
+ if (!is_designated_init (dc))
+ return 0;
+
+ const char *code = d_left (dc)->u.s_operator.op->code;
+
+ struct demangle_component *operands = d_right (dc);
+ struct demangle_component *op1 = d_left (operands);
+ struct demangle_component *op2 = d_right (operands);
+
+ if (code[1] == 'i')
+ d_append_char (dpi, '.');
+ else
+ d_append_char (dpi, '[');
+
+ d_print_comp (dpi, options, op1);
+ if (code[1] == 'X')
+ {
+ d_append_string (dpi, " ... ");
+ d_print_comp (dpi, options, d_left (op2));
+ op2 = d_right (op2);
+ }
+ if (code[1] != 'i')
+ d_append_char (dpi, ']');
+ if (is_designated_init (op2))
+ {
+ /* Don't put '=' or '(' between chained designators. */
+ d_print_comp (dpi, options, op2);
+ }
+ else
+ {
+ d_append_char (dpi, '=');
+ d_print_subexpr (dpi, options, op2);
+ }
+ return 1;
+}
+