diff --git a/CHANGES.current b/CHANGES.current
index e240ca3bc..9de2a3e72 100644
--- a/CHANGES.current
+++ b/CHANGES.current
@@ -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.
diff --git a/Doc/Manual/CPlusPlus11.html b/Doc/Manual/CPlusPlus11.html
index db47ee9dc..50402cefd 100644
--- a/Doc/Manual/CPlusPlus11.html
+++ b/Doc/Manual/CPlusPlus11.html
@@ -720,18 +720,45 @@ AltStruct var2{2, 4.3}; // calls the constructor
-SWIG supports decltype() with some limitations. Single
-variables are allowed, however, expressions are not supported yet. For
+
SWIG supports decltype() with limitations. Single
+variables are allowed, however, non-trivial expressions are not supported very well. For
example, the following code will work:
-However, using an expression inside the decltype results in syntax error:
+SWIG is able to deduce that the variable, i, is type int.
+
+
+
+Using a non-trivial expression for the decltype results in a warning:
int i; int j;
-decltype(i+j) k; // syntax error
+decltype(i+j) k; // Warning 344: Unable to deduce decltype for 'i+j'.
+
+
+
+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:
+
+
+
+#pragma SWIG nowarn=SWIGWARN_CPP11_DECLTYPE
+%ignore k;
+
+
+
+If an ignore is not acceptable, a workaround is to redefine the symbol with the actual type, for example:
+
+
+
+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'.
SWIG does not support auto as a type specifier for variables, only
diff --git a/Doc/Manual/Warnings.html b/Doc/Manual/Warnings.html
index 9d5361dae..1cdf37ec2 100644
--- a/Doc/Manual/Warnings.html
+++ b/Doc/Manual/Warnings.html
@@ -438,6 +438,9 @@ example.i(4) : Syntax error in input(1).
325. Nested kind not currently supported (name ignored).
326. Deprecated %extend name used - the kind name 'name' should be used instead of the typedef name 'name'.
327. Extern template ignored.
+340. Lambda expressions and closures are not fully supported yet.
+343. Only the first variadic template argument is currently supported.
+344. Unable to deduce decltype for 'expr'.
350. operator new ignored.
351. operator delete ignored.
352. operator+ ignored.
diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk
index 2539a65ba..cd634081c 100644
--- a/Examples/test-suite/common.mk
+++ b/Examples/test-suite/common.mk
@@ -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 \
diff --git a/Examples/test-suite/cpp11_decltype.i b/Examples/test-suite/cpp11_decltype.i
index deedd5953..ec2772d0c 100644
--- a/Examples/test-suite/cpp11_decltype.i
+++ b/Examples/test-suite/cpp11_decltype.i
@@ -9,11 +9,35 @@
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
return 0;
}
};
- %}
+%}
+
+
+// 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;
+ }
+ };
+%}
diff --git a/Examples/test-suite/python/cpp11_decltype_runme.py b/Examples/test-suite/python/cpp11_decltype_runme.py
index a18f334dc..436443988 100644
--- a/Examples/test-suite/python/cpp11_decltype_runme.py
+++ b/Examples/test-suite/python/cpp11_decltype_runme.py
@@ -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.")
diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y
index 04e6e9809..526d65ff6 100644
--- a/Source/CParse/parser.y
+++ b/Source/CParse/parser.y
@@ -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");
}
diff --git a/Source/Include/swigwarn.h b/Source/Include/swigwarn.h
index f38607f92..cc8192d29 100644
--- a/Source/Include/swigwarn.h
+++ b/Source/Include/swigwarn.h
@@ -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 */