mirror of https://github.com/swig/swig
Support C++17 fold expressions
Unary left fold expressions are not supported currently. Also the same restrictions that apply to other expressions apply here too. Fixes #2868
This commit is contained in:
parent
6fed8d96c1
commit
7c2b245cea
|
@ -7,6 +7,9 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
|
|||
Version 4.3.0 (in progress)
|
||||
===========================
|
||||
|
||||
2024-05-15: olly
|
||||
#2868 Support C++17 fold expressions.
|
||||
|
||||
2024-05-15: olly
|
||||
#2876 Report error if parser stack depth exceeded. Previously SWIG
|
||||
would quietly exit with status 0 in this situation.
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<li><a href="#CPlusPlus17_nested_namespaces">Nested namespace definitions</a>
|
||||
<li><a href="#CPlusPlus17_u8_char_literals">UTF-8 character literals</a>
|
||||
<li><a href="#CPlusPlus17_hexadecimal_floating_literals">Hexadecimal floating literals</a>
|
||||
<li><a href="#CPlusPlus17_fold_expressions">Fold expressions</a>
|
||||
</ul>
|
||||
<li><a href="#CPlusPlus17_standard_library_changes">Standard library changes</a>
|
||||
</ul>
|
||||
|
@ -102,6 +103,16 @@ double f = 0xF.68p2;
|
|||
</pre>
|
||||
</div>
|
||||
|
||||
<H3><a name="CPlusPlus17_fold_expressions">9.2.4 Fold expressions</a></H3>
|
||||
|
||||
|
||||
<p>
|
||||
C++17 added template fold expressions. SWIG 4.3.0 and later support
|
||||
parsing these with a few restrictions. Unary left fold expressions are
|
||||
not supported currently. Also the same restrictions that apply to other
|
||||
expressions apply here too.
|
||||
</p>
|
||||
|
||||
<H2><a name="CPlusPlus17_standard_library_changes">9.3 Standard library changes</a></H2>
|
||||
|
||||
|
||||
|
|
|
@ -87,3 +87,32 @@ void tester2() {
|
|||
// xxx<TestStruct>(); // compilation error
|
||||
}
|
||||
%}
|
||||
|
||||
// Check fold expressions parse (#2868):
|
||||
#define FOLD_EXPR_TEST(OP, FUNC) \
|
||||
template< \
|
||||
typename... Ts, \
|
||||
typename R = typename std::common_type_t<Ts...>, \
|
||||
std::enable_if_t< \
|
||||
(std::is_same_v<typename std::decay_t<Ts>,HalfInt> OP ...) \
|
||||
&& (std::is_constructible_v<HalfInt, R> \
|
||||
|| std::is_convertible_v<R, HalfInt>) \
|
||||
>* = nullptr \
|
||||
> \
|
||||
constexpr inline R FUNC(const Ts&... t) { return std::min(static_cast<R>(t)...); }
|
||||
FOLD_EXPR_TEST(+, f1)
|
||||
FOLD_EXPR_TEST(-, f2)
|
||||
FOLD_EXPR_TEST(*, f3)
|
||||
FOLD_EXPR_TEST(/, f4)
|
||||
FOLD_EXPR_TEST(%, f5)
|
||||
FOLD_EXPR_TEST(&, f6)
|
||||
FOLD_EXPR_TEST(|, f7)
|
||||
FOLD_EXPR_TEST(^, f8)
|
||||
FOLD_EXPR_TEST(<<, f9)
|
||||
FOLD_EXPR_TEST(>>, f10)
|
||||
FOLD_EXPR_TEST(&&, f11)
|
||||
FOLD_EXPR_TEST(||, f12)
|
||||
FOLD_EXPR_TEST(==, f13)
|
||||
FOLD_EXPR_TEST(!=, f14)
|
||||
FOLD_EXPR_TEST(>=, f15)
|
||||
FOLD_EXPR_TEST(<=, f16)
|
||||
|
|
|
@ -6907,6 +6907,100 @@ exprcompound : expr[lhs] PLUS expr[rhs] {
|
|||
$$.val = NewStringf("%s <= %s", COMPOUND_EXPR_VAL($lhs), COMPOUND_EXPR_VAL($rhs));
|
||||
$$.type = cparse_cplusplus ? T_BOOL : T_INT;
|
||||
}
|
||||
|
||||
// C++17 fold expressions.
|
||||
//
|
||||
// We don't handle unary left fold currently, since the obvious
|
||||
// approach introduces shift/reduce conflicts. (Binary folds
|
||||
// should be handled by composition of expressions.)
|
||||
//
|
||||
// Fold expressions using the following operators are not
|
||||
// currently handled (because we don't actually seem to handle
|
||||
// these operators in expressions at all!):
|
||||
//
|
||||
// = += -= *= /= %= ^= &= |= <<= >>= , .* ->*.
|
||||
| expr[lhs] PLUS ELLIPSIS {
|
||||
$$.val = NewStringf("%s+...", COMPOUND_EXPR_VAL($lhs));
|
||||
$$.type = promote_type($lhs.type);
|
||||
}
|
||||
| expr[lhs] MINUS ELLIPSIS {
|
||||
$$.val = NewStringf("%s-...", COMPOUND_EXPR_VAL($lhs));
|
||||
$$.type = promote_type($lhs.type);
|
||||
}
|
||||
| expr[lhs] STAR ELLIPSIS {
|
||||
$$.val = NewStringf("%s*...", COMPOUND_EXPR_VAL($lhs));
|
||||
$$.type = promote_type($lhs.type);
|
||||
}
|
||||
| expr[lhs] SLASH ELLIPSIS {
|
||||
$$.val = NewStringf("%s/...", COMPOUND_EXPR_VAL($lhs));
|
||||
$$.type = promote_type($lhs.type);
|
||||
}
|
||||
| expr[lhs] MODULO ELLIPSIS {
|
||||
$$.val = NewStringf("%s%%...", COMPOUND_EXPR_VAL($lhs));
|
||||
$$.type = promote_type($lhs.type);
|
||||
}
|
||||
| expr[lhs] AND ELLIPSIS {
|
||||
$$.val = NewStringf("%s&...", COMPOUND_EXPR_VAL($lhs));
|
||||
$$.type = promote_type($lhs.type);
|
||||
}
|
||||
| expr[lhs] OR ELLIPSIS {
|
||||
$$.val = NewStringf("%s|...", COMPOUND_EXPR_VAL($lhs));
|
||||
$$.type = promote_type($lhs.type);
|
||||
}
|
||||
| expr[lhs] XOR ELLIPSIS {
|
||||
$$.val = NewStringf("%s^...", COMPOUND_EXPR_VAL($lhs));
|
||||
$$.type = promote_type($lhs.type);
|
||||
}
|
||||
| expr[lhs] LSHIFT ELLIPSIS {
|
||||
$$.val = NewStringf("%s << ...", COMPOUND_EXPR_VAL($lhs));
|
||||
$$.type = promote_type($lhs.type);
|
||||
}
|
||||
| expr[lhs] RSHIFT ELLIPSIS {
|
||||
$$.val = NewStringf("%s >> ...", COMPOUND_EXPR_VAL($lhs));
|
||||
$$.type = promote_type($lhs.type);
|
||||
}
|
||||
| expr[lhs] LAND ELLIPSIS {
|
||||
$$.val = NewStringf("%s&&...", COMPOUND_EXPR_VAL($lhs));
|
||||
$$.type = cparse_cplusplus ? T_BOOL : T_INT;
|
||||
}
|
||||
| expr[lhs] LOR ELLIPSIS {
|
||||
$$.val = NewStringf("%s||...", COMPOUND_EXPR_VAL($lhs));
|
||||
$$.type = cparse_cplusplus ? T_BOOL : T_INT;
|
||||
}
|
||||
| expr[lhs] EQUALTO ELLIPSIS {
|
||||
$$.val = NewStringf("%s==...", COMPOUND_EXPR_VAL($lhs));
|
||||
$$.type = cparse_cplusplus ? T_BOOL : T_INT;
|
||||
}
|
||||
| expr[lhs] NOTEQUALTO ELLIPSIS {
|
||||
$$.val = NewStringf("%s!=...", COMPOUND_EXPR_VAL($lhs));
|
||||
$$.type = cparse_cplusplus ? T_BOOL : T_INT;
|
||||
}
|
||||
/* Trying to parse `>` in the general case results in conflicts
|
||||
* in the parser, but all user-reported cases are actually inside
|
||||
* parentheses and we can handle that case.
|
||||
*/
|
||||
| LPAREN expr[lhs] GREATERTHAN ELLIPSIS RPAREN {
|
||||
$$.val = NewStringf("(%s > ...)", COMPOUND_EXPR_VAL($lhs));
|
||||
$$.type = cparse_cplusplus ? T_BOOL : T_INT;
|
||||
}
|
||||
/* Similarly for `<` except trying to handle exprcompound on the
|
||||
* left side gives a shift/reduce conflict, so also restrict
|
||||
* handling to non-compound subexpressions there. Again this
|
||||
* covers all user-reported cases.
|
||||
*/
|
||||
| LPAREN exprsimple[lhs] LESSTHAN ELLIPSIS RPAREN {
|
||||
$$.val = NewStringf("(%s < %s)", COMPOUND_EXPR_VAL($lhs));
|
||||
$$.type = cparse_cplusplus ? T_BOOL : T_INT;
|
||||
}
|
||||
| expr[lhs] GREATERTHANOREQUALTO ELLIPSIS {
|
||||
$$.val = NewStringf("%s >= ...", COMPOUND_EXPR_VAL($lhs));
|
||||
$$.type = cparse_cplusplus ? T_BOOL : T_INT;
|
||||
}
|
||||
| expr[lhs] LESSTHANOREQUALTO ELLIPSIS {
|
||||
$$.val = NewStringf("%s <= ...", COMPOUND_EXPR_VAL($lhs));
|
||||
$$.type = cparse_cplusplus ? T_BOOL : T_INT;
|
||||
}
|
||||
|
||||
| expr[lhs] LESSEQUALGREATER expr[rhs] {
|
||||
$$.val = NewStringf("%s <=> %s", COMPOUND_EXPR_VAL($lhs), COMPOUND_EXPR_VAL($rhs));
|
||||
/* `<=>` returns one of `std::strong_ordering`,
|
||||
|
|
Loading…
Reference in New Issue