Slightly better decltype() support for expressions

decltype now accepts C++ expressions instead of just an ID, such as:

  int i,j;
  ...  decltype(i+j) ...
  ...  decltype(&i) ...

These result in a warning for non-trivial expressions which SWIG cannot evaluate:

  Warning 344: Unable to deduce decltype for 'i+j'.

See 'Type Inference' in CPlusPlus.html for workarounds.

Issue #1589
Issue #1590
This commit is contained in:
William S Fulton 2022-11-26 01:16:20 +00:00
commit 2a1711e436
8 changed files with 85 additions and 14 deletions

View file

@ -7,6 +7,20 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
Version 4.2.0 (in progress)
===========================
2022-11-26: wsfulton
#1589 #1590 Slightly better decltype() support for expressions, such as:
int i,j;
... decltype(i+j) ...
... decltype(&i) ...
These result in a warning for non-trivial expressions which SWIG cannot evaluate:
Warning 344: Unable to deduce decltype for 'i+j'.
See 'Type Inference' in CPlusPlus.html for workarounds.
2022-11-25: wsfulton
#961 Fix syntax error parsing unnamed template parameters with a default value.

View file

@ -720,18 +720,45 @@ AltStruct var2{2, 4.3}; // calls the constructor
<H3><a name="CPlusPlus11_type_inference">7.2.6 Type inference</a></H3>
<p>SWIG supports <tt>decltype()</tt> with some limitations. Single
variables are allowed, however, expressions are not supported yet. For
<p>SWIG supports <tt>decltype()</tt> with limitations. Single
variables are allowed, however, non-trivial expressions are not supported very well. For
example, the following code will work:</p>
<div class="code"><pre>
int i;
decltype(i) j;
</pre></div>
<p>However, using an expression inside the decltype results in syntax error:</p>
<p>SWIG is able to deduce that the variable, <tt>i</tt>, is type <tt>int</tt>.
</p>
<p>
Using a non-trivial expression for the decltype results in a warning:</p>
<div class="code"><pre>
int i; int j;
decltype(i+j) k; // syntax error
decltype(i+j) k; // Warning 344: Unable to deduce decltype for 'i+j'.
</pre></div>
<p>
This warning should be viewed as a prompt to add in a manual ignore of the variable/function as
in most cases the generated code will not compile.
For the example above, ignore the symbol that uses decltype and perhaps additionally
suppress the warning as follows:
</p>
<div class="code"><pre>
#pragma SWIG nowarn=SWIGWARN_CPP11_DECLTYPE
%ignore k;
</pre></div>
<p>
If an ignore is not acceptable, a workaround is to redefine the symbol with the actual type, for example:
</p>
<div class="code"><pre>
int k; // define k with the actual type
%ignore k; // ignore the real definition of k
int i; int j;
decltype(i+j) k; // Warning 344: Unable to deduce decltype for 'i+j'.
</pre></div>
<p>SWIG does not support <tt>auto</tt> as a type specifier for variables, only

View file

@ -438,6 +438,9 @@ example.i(4) : Syntax error in input(1).
<li>325. Nested <em>kind</em> not currently supported (<em>name</em> ignored).
<li>326. Deprecated %extend name used - the <em>kind</em> name '<em>name</em>' should be used instead of the typedef name '<em>name</em>'.
<li>327. Extern template ignored.
<li>340. Lambda expressions and closures are not fully supported yet.
<li>343. Only the first variadic template argument is currently supported.
<li>344. Unable to deduce decltype for '<em>expr</em>'.
<li>350. operator new ignored.
<li>351. operator delete ignored.
<li>352. operator+ ignored.

View file

@ -624,6 +624,7 @@ CPP11_TEST_CASES += \
cpp11_thread_local \
cpp11_template_double_brackets \
cpp11_template_explicit \
cpp11_template_parameters_decltype \
cpp11_template_typedefs \
cpp11_type_traits \
cpp11_type_aliasing \

View file

@ -9,7 +9,7 @@
int i;
decltype(i) j;
auto foo( decltype(i) a ) -> decltype(i) {
auto get_number(decltype(i) a) -> decltype(i) {
if (a==5)
return 10;
else
@ -17,3 +17,27 @@
}
};
%}
// These are ignored as unable to deduce decltype for (i+j)
%ignore B::k;
%ignore B::get_number_sum;
%ignore B::get_number_address;
#pragma SWIG nowarn=SWIGWARN_CPP11_DECLTYPE
%inline %{
class B {
public:
int i;
decltype(i) j;
decltype(i+j) k;
auto get_number_sum(decltype(i+j) a) -> decltype(i+j) {
return i+j;
}
auto get_number_address(decltype(&i) a) -> decltype(&i) {
return &i;
}
};
%}

View file

@ -9,10 +9,10 @@ a.j = 10
if a.j != 10:
raise RuntimeError("Assignment to a.j failed.")
b = a.foo(5)
b = a.get_int(5)
if b != 10:
raise RuntimeError("foo(5) should return 10.")
raise RuntimeError("get_int(5) should return 10.")
b = a.foo(6)
b = a.get_int(6)
if b != 0:
raise RuntimeError("foo(6) should return 0.")
raise RuntimeError("get_int(6) should return 0.")

View file

@ -6241,11 +6241,12 @@ type_right : primitive_type { $$ = $1;
}
;
decltype : DECLTYPE LPAREN idcolon RPAREN {
Node *n = Swig_symbol_clookup($3,0);
decltype : DECLTYPE LPAREN expr RPAREN {
Node *n = Swig_symbol_clookup($3.val, 0);
if (!n) {
Swig_error(cparse_file, cparse_line, "Identifier %s not defined.\n", $3);
$$ = $3;
Swig_warning(WARN_CPP11_DECLTYPE, cparse_file, cparse_line, "Unable to deduce decltype for '%s'.\n", $3.val);
$$ = NewStringf("decltype(%s)", $3.val);
} else {
$$ = Getattr(n, "type");
}

View file

@ -99,6 +99,7 @@
#define WARN_CPP11_ALIAS_DECLARATION 341 /* redundant now */
#define WARN_CPP11_ALIAS_TEMPLATE 342 /* redundant now */
#define WARN_CPP11_VARIADIC_TEMPLATE 343
#define WARN_CPP11_DECLTYPE 344
#define WARN_IGNORE_OPERATOR_NEW 350 /* new */
#define WARN_IGNORE_OPERATOR_DELETE 351 /* delete */