mirror of https://github.com/swig/swig
Improve parsing multi-line expr via skip_balanced()
Fix bad generated code in some cases when a constant expression is split over multiple lines and used as part of a type. This manifested in cases where SWIG's parser calls skip_balanced('(', ')') then grabs the skipped expression's program text from scanner_ccode. Fixes #3127
This commit is contained in:
parent
1bff64d5e2
commit
4a0372aacc
|
@ -7,6 +7,13 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
|
||||||
Version 4.4.0 (in progress)
|
Version 4.4.0 (in progress)
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
|
2025-02-28: olly
|
||||||
|
#3127 Fix bad generated code in some cases when a constant
|
||||||
|
expression is split over multiple lines and used as part of a type.
|
||||||
|
This manifested in cases where SWIG's parser gets the expression
|
||||||
|
text by skipping to the matching closing parenthesis and grabbing
|
||||||
|
the skipped program text.
|
||||||
|
|
||||||
2025-02-19: wsfulton
|
2025-02-19: wsfulton
|
||||||
Add support for $n special variable expansion in the names of typemap
|
Add support for $n special variable expansion in the names of typemap
|
||||||
local variables, such as:
|
local variables, such as:
|
||||||
|
|
|
@ -74,4 +74,22 @@ struct A {
|
||||||
};
|
};
|
||||||
constexpr A a{42};
|
constexpr A a{42};
|
||||||
constexpr int N = a.i;
|
constexpr int N = a.i;
|
||||||
|
|
||||||
|
// Regression test for https://github.com/swig/swig/issues/3127 fixed in 4.4.0:
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
constexpr std::size_t my_enum_size =
|
||||||
|
sizeof(
|
||||||
|
decltype(
|
||||||
|
42
|
||||||
|
)
|
||||||
|
) ? 1 + static_cast<std::size_t>(
|
||||||
|
4
|
||||||
|
) : alignof(
|
||||||
|
std::size_t
|
||||||
|
);
|
||||||
|
|
||||||
|
std::array<bool, my_enum_size> do_something() {
|
||||||
|
return std::array<bool, my_enum_size>{true,true,true,true,true};
|
||||||
|
}
|
||||||
%}
|
%}
|
||||||
|
|
|
@ -1913,6 +1913,25 @@ static SwigType *deduce_type(const struct Define *dtype) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Append scanner_ccode to expr, normalising runs of whitespace to a single
|
||||||
|
// space (in particular newlines are problematic in the generated
|
||||||
|
// swig_type_info).
|
||||||
|
static void append_expr_from_scanner(String *expr) {
|
||||||
|
int len = Len(scanner_ccode);
|
||||||
|
int in_space = 0;
|
||||||
|
for (int i = 0; i < len; ++i) {
|
||||||
|
char ch = Char(scanner_ccode)[i];
|
||||||
|
if (isspace((unsigned char)ch)) {
|
||||||
|
if (!in_space) Putc(' ', expr);
|
||||||
|
in_space = 1;
|
||||||
|
} else {
|
||||||
|
Putc(ch, expr);
|
||||||
|
in_space = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Clear(scanner_ccode);
|
||||||
|
}
|
||||||
|
|
||||||
static Node *new_enum_node(SwigType *enum_base_type) {
|
static Node *new_enum_node(SwigType *enum_base_type) {
|
||||||
Node *n = new_node("enum");
|
Node *n = new_node("enum");
|
||||||
if (enum_base_type) {
|
if (enum_base_type) {
|
||||||
|
@ -6701,8 +6720,8 @@ exprmem : ID[lhs] ARROW ID[rhs] {
|
||||||
| ID[lhs] ARROW ID[rhs] LPAREN {
|
| ID[lhs] ARROW ID[rhs] LPAREN {
|
||||||
if (skip_balanced('(', ')') < 0) Exit(EXIT_FAILURE);
|
if (skip_balanced('(', ')') < 0) Exit(EXIT_FAILURE);
|
||||||
$$ = default_dtype;
|
$$ = default_dtype;
|
||||||
$$.val = NewStringf("%s->%s%s", $lhs, $rhs, scanner_ccode);
|
$$.val = NewStringf("%s->%s", $lhs, $rhs);
|
||||||
Clear(scanner_ccode);
|
append_expr_from_scanner($$.val);
|
||||||
}
|
}
|
||||||
| exprmem[in] ARROW ID {
|
| exprmem[in] ARROW ID {
|
||||||
$$ = $in;
|
$$ = $in;
|
||||||
|
@ -6711,8 +6730,8 @@ exprmem : ID[lhs] ARROW ID[rhs] {
|
||||||
| exprmem[in] ARROW ID LPAREN {
|
| exprmem[in] ARROW ID LPAREN {
|
||||||
if (skip_balanced('(', ')') < 0) Exit(EXIT_FAILURE);
|
if (skip_balanced('(', ')') < 0) Exit(EXIT_FAILURE);
|
||||||
$$ = $in;
|
$$ = $in;
|
||||||
Printf($$.val, "->%s%s", $ID, scanner_ccode);
|
Printf($$.val, "->%s", $ID);
|
||||||
Clear(scanner_ccode);
|
append_expr_from_scanner($$.val);
|
||||||
}
|
}
|
||||||
| ID[lhs] PERIOD ID[rhs] {
|
| ID[lhs] PERIOD ID[rhs] {
|
||||||
$$ = default_dtype;
|
$$ = default_dtype;
|
||||||
|
@ -6721,8 +6740,8 @@ exprmem : ID[lhs] ARROW ID[rhs] {
|
||||||
| ID[lhs] PERIOD ID[rhs] LPAREN {
|
| ID[lhs] PERIOD ID[rhs] LPAREN {
|
||||||
if (skip_balanced('(', ')') < 0) Exit(EXIT_FAILURE);
|
if (skip_balanced('(', ')') < 0) Exit(EXIT_FAILURE);
|
||||||
$$ = default_dtype;
|
$$ = default_dtype;
|
||||||
$$.val = NewStringf("%s.%s%s", $lhs, $rhs, scanner_ccode);
|
$$.val = NewStringf("%s.%s", $lhs, $rhs);
|
||||||
Clear(scanner_ccode);
|
append_expr_from_scanner($$.val);
|
||||||
}
|
}
|
||||||
| exprmem[in] PERIOD ID {
|
| exprmem[in] PERIOD ID {
|
||||||
$$ = $in;
|
$$ = $in;
|
||||||
|
@ -6731,8 +6750,8 @@ exprmem : ID[lhs] ARROW ID[rhs] {
|
||||||
| exprmem[in] PERIOD ID LPAREN {
|
| exprmem[in] PERIOD ID LPAREN {
|
||||||
if (skip_balanced('(', ')') < 0) Exit(EXIT_FAILURE);
|
if (skip_balanced('(', ')') < 0) Exit(EXIT_FAILURE);
|
||||||
$$ = $in;
|
$$ = $in;
|
||||||
Printf($$.val, ".%s%s", $ID, scanner_ccode);
|
Printf($$.val, ".%s", $ID);
|
||||||
Clear(scanner_ccode);
|
append_expr_from_scanner($$.val);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -6772,24 +6791,24 @@ exprsimple : exprnum
|
||||||
| SIZEOF LPAREN {
|
| SIZEOF LPAREN {
|
||||||
if (skip_balanced('(', ')') < 0) Exit(EXIT_FAILURE);
|
if (skip_balanced('(', ')') < 0) Exit(EXIT_FAILURE);
|
||||||
$$ = default_dtype;
|
$$ = default_dtype;
|
||||||
$$.val = NewStringf("sizeof%s", scanner_ccode);
|
$$.val = NewString("sizeof");
|
||||||
Clear(scanner_ccode);
|
append_expr_from_scanner($$.val);
|
||||||
$$.type = T_ULONG;
|
$$.type = T_ULONG;
|
||||||
}
|
}
|
||||||
/* alignof(T) always has type size_t. */
|
/* alignof(T) always has type size_t. */
|
||||||
| ALIGNOF LPAREN {
|
| ALIGNOF LPAREN {
|
||||||
if (skip_balanced('(', ')') < 0) Exit(EXIT_FAILURE);
|
if (skip_balanced('(', ')') < 0) Exit(EXIT_FAILURE);
|
||||||
$$ = default_dtype;
|
$$ = default_dtype;
|
||||||
$$.val = NewStringf("alignof%s", scanner_ccode);
|
$$.val = NewString("alignof");
|
||||||
Clear(scanner_ccode);
|
append_expr_from_scanner($$.val);
|
||||||
$$.type = T_ULONG;
|
$$.type = T_ULONG;
|
||||||
}
|
}
|
||||||
/* noexcept(X) always has type bool. */
|
/* noexcept(X) always has type bool. */
|
||||||
| NOEXCEPT LPAREN {
|
| NOEXCEPT LPAREN {
|
||||||
if (skip_balanced('(', ')') < 0) Exit(EXIT_FAILURE);
|
if (skip_balanced('(', ')') < 0) Exit(EXIT_FAILURE);
|
||||||
$$ = default_dtype;
|
$$ = default_dtype;
|
||||||
$$.val = NewStringf("noexcept%s", scanner_ccode);
|
$$.val = NewString("noexcept");
|
||||||
Clear(scanner_ccode);
|
append_expr_from_scanner($$.val);
|
||||||
$$.type = T_BOOL;
|
$$.type = T_BOOL;
|
||||||
}
|
}
|
||||||
| SIZEOF ELLIPSIS LPAREN identifier RPAREN {
|
| SIZEOF ELLIPSIS LPAREN identifier RPAREN {
|
||||||
|
@ -7253,16 +7272,14 @@ exprcompound : expr[lhs] PLUS expr[rhs] {
|
||||||
}
|
}
|
||||||
| type LPAREN {
|
| type LPAREN {
|
||||||
$$ = default_dtype;
|
$$ = default_dtype;
|
||||||
String *qty;
|
|
||||||
if (skip_balanced('(',')') < 0) Exit(EXIT_FAILURE);
|
if (skip_balanced('(',')') < 0) Exit(EXIT_FAILURE);
|
||||||
qty = Swig_symbol_type_qualify($type,0);
|
|
||||||
|
String *qty = Swig_symbol_type_qualify($type, 0);
|
||||||
if (SwigType_istemplate(qty)) {
|
if (SwigType_istemplate(qty)) {
|
||||||
String *nstr = SwigType_namestr(qty);
|
String *nstr = SwigType_namestr(qty);
|
||||||
Delete(qty);
|
Delete(qty);
|
||||||
qty = nstr;
|
qty = nstr;
|
||||||
}
|
}
|
||||||
$$.val = NewStringf("%s%s",qty,scanner_ccode);
|
|
||||||
Clear(scanner_ccode);
|
|
||||||
/* Try to deduce the type - this could be a C++ "constructor
|
/* Try to deduce the type - this could be a C++ "constructor
|
||||||
* cast" such as `double(4)` or a function call such as
|
* cast" such as `double(4)` or a function call such as
|
||||||
* `some_func()`. In the latter case we get T_USER, but that
|
* `some_func()`. In the latter case we get T_USER, but that
|
||||||
|
@ -7274,7 +7291,9 @@ exprcompound : expr[lhs] PLUS expr[rhs] {
|
||||||
$$.type = SwigType_type(qty);
|
$$.type = SwigType_type(qty);
|
||||||
if ($$.type == T_USER) $$.type = T_UNKNOWN;
|
if ($$.type == T_USER) $$.type = T_UNKNOWN;
|
||||||
$$.unary_arg_type = 0;
|
$$.unary_arg_type = 0;
|
||||||
Delete(qty);
|
|
||||||
|
$$.val = qty;
|
||||||
|
append_expr_from_scanner($$.val);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue