auto without return type cleanup

- Fix undefined behaviour
- Document and test workaround for class methods
- More informative WARN_CPP14_AUTO warning message

See issue #2446
This commit is contained in:
William S Fulton 2023-06-09 19:14:47 +01:00
parent cf668ff738
commit 0893aa34ca
5 changed files with 43 additions and 13 deletions

View File

@ -54,13 +54,13 @@ int b = 0b101011;
</pre>
</div>
<H3><a href="CPlusPlus14_return_type_deduction">8.2.2 Return type deduction</a></H3>
<H3><a name="CPlusPlus14_return_type_deduction">8.2.2 Return type deduction</a></H3>
<p>
C++14 added the ability to specify <tt>auto</tt> for the return type of a function
and have the compiler deduce it from the body of the function (in C++11 you had
to explicitly specify a trailing return type if you used <tt>auto</tt> for the
return type.
return type).
</p>
<p>
@ -79,20 +79,36 @@ an actual example:
</p>
<div class="code"><pre>
std::tuple<int, int> va_static_cast();
std::tuple&lt;int, int&gt; va_static_cast();
%ignore va_static_cast();
#pragma SWIG nowarn=SWIGWARN_CPP14_AUTO
%inline %{
#include <tuple>
#include &lt;tuple&gt;
auto va_static_cast()
{
auto va_static_cast() {
return std::make_tuple(0, 0);
}
%}
</pre></div>
<p>
For member methods the trick is to use <tt>%extend</tt> to redeclare the method and call it as follows:
</p>
<div class="code"><pre>
%extend X {
const char * a() const { return $self-&gt;a(); }
}
%inline %{
struct X {
auto a() const {
return "a string";
}
};
%}
</pre></div>
<p>
<b>Compatibility note:</b> SWIG-4.2.0 first introduced support for functions declared with an auto return without a trailing return type.
</p>

View File

@ -440,7 +440,7 @@ example.i(4) : Syntax error in input(1).
<li>327. Extern template ignored.
<li>340. Lambda expressions and closures are not fully supported yet.
<li>344. Unable to deduce decltype for '<em>expr</em>'.
<li>345. Unable to deduce return type for '<em>name</em>'.
<li>345. Unable to deduce return type for auto in '<em>name</em>' (ignored).
<li>346. Unable to deduce type for variable '<em>name</em>'.
<li>350. operator new ignored.
<li>351. operator delete ignored.

View File

@ -7,14 +7,17 @@
// declaration with an explicit return type in the interface file.
namespace teca_variant_array_util {
// Workaround to wrap a global function containing an auto return type with no trailing return type
int va_static_cast();
%ignore va_static_cast();
// Not seeing a way to supply a declaration for a class method that makes
// these work, but they can be ignored at least.
// TODO: %ignore does not work as the declaration is not added to the parse tree
%ignore X::a();
%ignore X::b();
%ignore X::s();
// Workaround to wrap a class method containing an auto return type with no trailing return type
%extend X {
const char * a() const { return $self->a(); }
}
}
#pragma SWIG nowarn=SWIGWARN_CPP14_AUTO
@ -27,8 +30,8 @@ auto va_static_cast()
return 42;
}
struct X {
auto a() {
return "a";
auto a() const {
return "a string";
}
auto e() const {
return 2.71828;

View File

@ -0,0 +1,10 @@
from cpp14_auto_return_type import *
sc = va_static_cast()
if sc != 42:
raise RuntimeError("va_static_cast fail {}".format(sc))
x = X()
a = x.a()
if a != "a string":
raise RuntimeError("x.a fail {}".format(a))

View File

@ -3360,7 +3360,8 @@ c_decl : storage_class type declarator cpp_const initializer c_decl_tail {
* to wrap.
*/
| storage_class AUTO declarator cpp_const LBRACE {
Swig_warning(WARN_CPP14_AUTO, cparse_file, cparse_line, "Unable to deduce return type for '%s'.\n", $3.id);
Swig_warning(WARN_CPP14_AUTO, cparse_file, cparse_line, "Unable to deduce return type for auto in '%s' (ignored).\n", $3.id);
$$ = 0;
if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
}
/* C++11 auto variable declaration. */