From 2a1711e4364afe0250282e032650e3ac543e73a3 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 26 Nov 2022 01:16:20 +0000 Subject: [PATCH] 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 --- CHANGES.current | 14 ++++++++ Doc/Manual/CPlusPlus11.html | 35 ++++++++++++++++--- Doc/Manual/Warnings.html | 3 ++ Examples/test-suite/common.mk | 1 + Examples/test-suite/cpp11_decltype.i | 28 +++++++++++++-- .../test-suite/python/cpp11_decltype_runme.py | 8 ++--- Source/CParse/parser.y | 9 ++--- Source/Include/swigwarn.h | 1 + 8 files changed, 85 insertions(+), 14 deletions(-) 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

7.2.6 Type inference

-

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:

 int i;
 decltype(i) j;
 
-

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 */