mirror of https://github.com/swig/swig
Improve type deduction
Create a new T_UNKNOWN type code and use this for the cases where we previously abused T_INT. This means we can now reliably deduce `int` when we see T_INT. Fix the deduced result types of unary plus and unary minus which weren't getting integer promotion applied to them. Fix the deduced result type of the C++ logical not operator which was `int` but should be `bool`.
This commit is contained in:
parent
940b41f40a
commit
997616e652
|
@ -548,8 +548,6 @@ Version 4.2.0 (in progress)
|
|||
2023-05-25: olly
|
||||
C++11 `auto` variables and `decltype()` can now deduce the
|
||||
type of some expressions which involve literals of built-in types.
|
||||
Currently int is not supported due to the parser misusing T_INT
|
||||
for situations where the type isn't actually known.
|
||||
|
||||
2023-05-25: olly
|
||||
#1125 Support parsing C++11 auto variables. This uses the
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
static auto t = true;
|
||||
static constexpr auto f = false;
|
||||
|
||||
static auto zero = 0;
|
||||
static constexpr auto one = 1;
|
||||
|
||||
static auto la = 1.0L;
|
||||
static auto da = 1.0;
|
||||
static auto fa = 1.0f;
|
||||
|
|
|
@ -35,6 +35,15 @@
|
|||
DECLARE(a, false);
|
||||
DECLARE(b, true);
|
||||
|
||||
// SWIG < 4.2.0 failed to perform type promotion for the result of unary
|
||||
// plus and unary minus, so these would end up wrapped as bool and char.
|
||||
decltype(+true) should_be_int;
|
||||
decltype(-'x') should_be_int2;
|
||||
|
||||
// SWIG < 4.2.0 incorrectly used int for the result of logical not in C++
|
||||
// so this would end up wrapped as int.
|
||||
decltype(!0) should_be_bool;
|
||||
|
||||
auto get_number_sum(decltype(i+j) a) -> decltype(i+j) {
|
||||
return i+j;
|
||||
}
|
||||
|
|
|
@ -5,16 +5,28 @@ require "tests.php";
|
|||
// No new functions
|
||||
check::functions(array());
|
||||
check::classes(array('cpp11_auto_variable'));
|
||||
check::globals(array('f', 't', 'la', 'da', 'fa', 'lc', 'dc', 'fc', 'pi_approx', 'Bar', 'Bar2', 'Foo', 'Foo2'));
|
||||
check::globals(array('f', 't', 'zero', 'one', 'la', 'da', 'fa', 'lc', 'dc', 'fc', 'pi_approx', 'Bar', 'Bar2', 'Foo', 'Foo2'));
|
||||
|
||||
check::equal(f_get(), false);
|
||||
check::equal(gettype(f_get()), "boolean");
|
||||
check::equal(t_get(), true);
|
||||
check::equal(gettype(t_get()), "boolean");
|
||||
|
||||
t_set(false);
|
||||
check::equal(t_get(), false);
|
||||
|
||||
check::equal(function_exists('f_set'), false, "f should be constant but f_set() exists");
|
||||
|
||||
check::equal(zero_get(), 0);
|
||||
check::equal(gettype(zero_get()), "integer");
|
||||
check::equal(one_get(), 1);
|
||||
check::equal(gettype(one_get()), "integer");
|
||||
|
||||
zero_set(42);
|
||||
check::equal(zero_get(), 42);
|
||||
|
||||
check::equal(function_exists('one_set'), false, "one should be constant but one_set() exists");
|
||||
|
||||
check::equal(fa_get(), 1.0);
|
||||
check::equal(da_get(), 1.0);
|
||||
// PHP doesn't have a native "long double" type, so SWIG/PHP doesn't have
|
||||
|
|
|
@ -31,3 +31,7 @@ check::equal($b->b, true);
|
|||
check::equal($b->negate(true), false);
|
||||
|
||||
check::equal($b->negate(false), true);
|
||||
|
||||
check::equal(gettype($b->should_be_int), "integer");
|
||||
check::equal(gettype($b->should_be_int2), "integer");
|
||||
check::equal(gettype($b->should_be_bool), "boolean");
|
||||
|
|
|
@ -1780,12 +1780,8 @@ static SwigType *deduce_type(const struct Define *dtype) {
|
|||
Node *n = Swig_symbol_clookup(dtype->val, 0);
|
||||
if (n) {
|
||||
return Getattr(n, "type");
|
||||
} else if (dtype->type != T_AUTO && dtype->type != T_INT) {
|
||||
/* Try to deduce the type from the T_* type code.
|
||||
*
|
||||
* Sadly we can't trust T_INT because several places in the parser set
|
||||
* .type = T_INT when it may not be (or even definitely isn't).
|
||||
*/
|
||||
} else if (dtype->type != T_AUTO && dtype->type != T_UNKNOWN) {
|
||||
/* Try to deduce the type from the T_* type code. */
|
||||
return NewSwigType(dtype->type);
|
||||
} else {
|
||||
return NULL;
|
||||
|
@ -5304,7 +5300,7 @@ def_args : EQUAL definetype {
|
|||
if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
|
||||
$$.val = NewString(scanner_ccode);
|
||||
$$.rawval = 0;
|
||||
$$.type = T_INT; /* This may be a lie. */
|
||||
$$.type = T_UNKNOWN;
|
||||
$$.bitfield = 0;
|
||||
$$.throws = 0;
|
||||
$$.throwf = 0;
|
||||
|
@ -5324,7 +5320,7 @@ def_args : EQUAL definetype {
|
|||
| %empty {
|
||||
$$.val = 0;
|
||||
$$.rawval = 0;
|
||||
$$.type = T_INT; /* This is a lie. */
|
||||
$$.type = T_UNKNOWN;
|
||||
$$.bitfield = 0;
|
||||
$$.throws = 0;
|
||||
$$.throwf = 0;
|
||||
|
@ -6549,7 +6545,8 @@ etype : expr {
|
|||
($$.type != T_LONGLONG) && ($$.type != T_ULONGLONG) &&
|
||||
($$.type != T_SHORT) && ($$.type != T_USHORT) &&
|
||||
($$.type != T_SCHAR) && ($$.type != T_UCHAR) &&
|
||||
($$.type != T_CHAR) && ($$.type != T_BOOL)) {
|
||||
($$.type != T_CHAR) && ($$.type != T_BOOL) &&
|
||||
($$.type != T_UNKNOWN)) {
|
||||
Swig_error(cparse_file,cparse_line,"Type error. Expecting an integral type\n");
|
||||
}
|
||||
}
|
||||
|
@ -6561,7 +6558,7 @@ expr : valexpr
|
|||
| type {
|
||||
Node *n;
|
||||
$$.val = $1;
|
||||
$$.type = T_INT; /* This may be a lie. */
|
||||
$$.type = T_UNKNOWN;
|
||||
/* Check if value is in scope */
|
||||
n = Swig_symbol_clookup($1,0);
|
||||
if (n) {
|
||||
|
@ -6878,11 +6875,11 @@ exprcompound : expr PLUS expr {
|
|||
}
|
||||
| MINUS expr %prec UMINUS {
|
||||
$$.val = NewStringf("-%s",$2.val);
|
||||
$$.type = $2.type;
|
||||
$$.type = promote_type($2.type);
|
||||
}
|
||||
| PLUS expr %prec UMINUS {
|
||||
$$.val = NewStringf("+%s",$2.val);
|
||||
$$.type = $2.type;
|
||||
$$.type = promote_type($2.type);
|
||||
}
|
||||
| NOT expr {
|
||||
$$.val = NewStringf("~%s",$2.val);
|
||||
|
@ -6890,7 +6887,7 @@ exprcompound : expr PLUS expr {
|
|||
}
|
||||
| LNOT expr {
|
||||
$$.val = NewStringf("!%s",COMPOUND_EXPR_VAL($2));
|
||||
$$.type = T_INT;
|
||||
$$.type = cparse_cplusplus ? T_BOOL : T_INT;
|
||||
}
|
||||
| type LPAREN {
|
||||
String *qty;
|
||||
|
@ -6903,7 +6900,7 @@ exprcompound : expr PLUS expr {
|
|||
}
|
||||
$$.val = NewStringf("%s%s",qty,scanner_ccode);
|
||||
Clear(scanner_ccode);
|
||||
$$.type = T_INT;
|
||||
$$.type = T_UNKNOWN;
|
||||
Delete(qty);
|
||||
}
|
||||
;
|
||||
|
|
|
@ -109,6 +109,10 @@ SwigType *NewSwigType(int t) {
|
|||
switch (t) {
|
||||
case T_BOOL:
|
||||
return NewString("bool");
|
||||
case T_UNKNOWN:
|
||||
/* Handle like T_INT since we used to just use T_INT where we now use
|
||||
* T_UNKNOWN.
|
||||
*/
|
||||
case T_INT:
|
||||
return NewString("int");
|
||||
case T_UINT:
|
||||
|
|
|
@ -95,6 +95,7 @@ extern "C" {
|
|||
#define T_VARARGS 39
|
||||
#define T_RVALUE_REFERENCE 40
|
||||
#define T_WSTRING 41
|
||||
#define T_UNKNOWN 42
|
||||
|
||||
/* --- File interface --- */
|
||||
|
||||
|
|
Loading…
Reference in New Issue