clang and MSVC reject a return type-constraint combined with a trailing return type.
The constrained-return form is now covered separately via the new half_numeric.
Three new grammar rules in 'cpp_declaration' parallel the existing
'storage_class AUTO declarator cpp_const ...' alternatives, accepting
a leading 'idcolon' before AUTO so a constrained auto return type
('Numeric auto fn(...)') parses. Each new rule mirrors the action of
its plain AUTO counterpart and additionally attaches the captured
concept-id as a 'concept-id' atom on the cdecl's 'constraint' attribute:
Numeric auto half(int x) -> int { return x / 2; } // wrappable
Numeric auto cube_constrained(Sized auto x) -> int { return x*x*x; } // wrappable
Numeric auto times2(int x) { return x * 2; } // ignored with warning
Numeric auto times3(int x); // ignored with warning
When a trailing return type is present SWIG wraps the function using
that type and the constraint is metadata only; without one the
function inherits plain 'auto fn(...)' behaviour and is ignored with
a warning since SWIG cannot deduce the return type.
As a side fix, the existing 'storage_class AUTO declarator cpp_const
ARROW ...' rule now also calls promote_abbreviated_template, so a
constrained auto parameter combined with an explicit trailing return
('auto fn(Concept auto x) -> int') introduces an invented type
template parameter for the auto parameter and instantiates correctly
via %template (previously: 'X is not defined as a template' error).
cpp20_abbreviated_template.i (and matching Python/Java runmes) gain
'half', 'cube_constrained', 'twice_n_arrow', 'times2' and 'times3'
cases covering all five forms from the constrained auto return type
matrix; the two ignored with warning declarations are silenced via per name
%warnfilter(SWIGWARN_CPP14_AUTO).
Assisted-by: Claude Code (Opus 4.7)
A type constrained 'auto' parameter (e.g. 'Numeric auto') is now
accepted in parameter type position - via a new
'idcolon AUTO parameter_declarator' alternative in parm_no_dox. The
invented type template parameter generated for each such auto parm
carries the type-constraint as a 'concept-id' constraint atom on its
'constraint' attribute, matching the requires-clause infrastructure
already used by explicit templates.
int twice_numeric(Numeric auto x) { return x + x; }
%template(twice_numeric_int) twice_numeric<int>;
Each constrained auto parm gets its own invented type template parameter
and constraint, so multi parm forms work too:
double scale_mixed(Numeric auto x, Numeric auto factor);
int add_same_concept(Sized auto a, Sized auto b);
cpp20_concepts_lambda.i picks up the constrained auto lambda case
('[](Numeric auto x){}') that previously failed to parse.
Assisted-by: Claude Code (Opus 4.7)
Adds an AUTO parameter_declarator alternative to parm_no_dox. Placing
the new alternative in parm_no_dox rather than type_right scopes the
'auto' keyword to parameter context only, so it does not clash with
the dedicated 'storage_class AUTO declarator ...' rules at top level
and the existing %expect 7 conflict count is unchanged.
Functions whose parms include 'auto' are converted to a function
template - one invented type template parameter (named
"__dummy_auto_<N>__") per auto parm - via promote_abbreviated_template()
called from c_decl, so abbreviated function templates wrap through the
existing %template instantiation machinery.
Lambdas (which already route through parms) get the same fix
transparently and parse without choking, matching the C++14 generic
lambda form.
The function must declare an explicit (non-auto) return type for SWIG
to wrap it. The C++14 auto return restriction, (cpp14_auto_return_type
testcase) still applies.
// C++14 generic lambda
auto twice = [](auto x) { return x + x; };
// C++20 abbreviated function template
int twice(auto x) { return x + x; }
%template(twice_int) twice<int>;
Assisted-by: Claude Code (Opus 4.7)