From 13260f95b0d35def50f2f4dc9bfe5b04f670fbdd Mon Sep 17 00:00:00 2001 From: Leo Singer Date: Thu, 2 Apr 2020 15:08:08 -0400 Subject: [PATCH 1/5] Properly handle C99 complex types even in C++ mode Use the `_Complex` keyword rather than the `complex` macro. Fixes #1487. --- Lib/javascript/jsc/ccomplex.i | 8 ++++---- Lib/javascript/v8/ccomplex.i | 8 ++++---- Lib/python/ccomplex.i | 8 ++++---- Source/CParse/cscanner.c | 4 ++++ Source/CParse/parser.y | 12 ++++++------ Source/Swig/typesys.c | 4 ++-- 6 files changed, 24 insertions(+), 20 deletions(-) diff --git a/Lib/javascript/jsc/ccomplex.i b/Lib/javascript/jsc/ccomplex.i index 50f0f95fe..64fe00ec9 100644 --- a/Lib/javascript/jsc/ccomplex.i +++ b/Lib/javascript/jsc/ccomplex.i @@ -16,11 +16,11 @@ /* C complex constructor */ #define CCplxConst(r, i) ((r) + I*(i)) -%swig_cplxflt_convn(float complex, CCplxConst, creal, cimag); -%swig_cplxdbl_convn(double complex, CCplxConst, creal, cimag); +%swig_cplxflt_convn(float _Complex, CCplxConst, creal, cimag); +%swig_cplxdbl_convn(double _Complex, CCplxConst, creal, cimag); %swig_cplxdbl_convn(complex, CCplxConst, creal, cimag); /* declaring the typemaps */ -%typemaps_primitive(SWIG_TYPECHECK_CPLXFLT, float complex); -%typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, double complex); +%typemaps_primitive(SWIG_TYPECHECK_CPLXFLT, float _Complex); +%typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, double _Complex); %typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, complex); diff --git a/Lib/javascript/v8/ccomplex.i b/Lib/javascript/v8/ccomplex.i index 8eda920bb..b1e766354 100644 --- a/Lib/javascript/v8/ccomplex.i +++ b/Lib/javascript/v8/ccomplex.i @@ -16,11 +16,11 @@ /* C complex constructor */ #define CCplxConst(r, i) ((r) + I*(i)) -%swig_cplxflt_convn(float complex, CCplxConst, creal, cimag); -%swig_cplxdbl_convn(double complex, CCplxConst, creal, cimag); +%swig_cplxflt_convn(float _Complex, CCplxConst, creal, cimag); +%swig_cplxdbl_convn(double _Complex, CCplxConst, creal, cimag); %swig_cplxdbl_convn(complex, CCplxConst, creal, cimag); /* declaring the typemaps */ -%typemaps_primitive(SWIG_TYPECHECK_CPLXFLT, float complex); -%typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, double complex); +%typemaps_primitive(SWIG_TYPECHECK_CPLXFLT, float _Complex); +%typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, double _Complex); %typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, complex); diff --git a/Lib/python/ccomplex.i b/Lib/python/ccomplex.i index 28872b985..17163506b 100644 --- a/Lib/python/ccomplex.i +++ b/Lib/python/ccomplex.i @@ -16,11 +16,11 @@ /* C complex constructor */ #define CCplxConst(r, i) ((r) + I*(i)) -%swig_cplxflt_convn(float complex, CCplxConst, creal, cimag); -%swig_cplxdbl_convn(double complex, CCplxConst, creal, cimag); +%swig_cplxflt_convn(float _Complex, CCplxConst, creal, cimag); +%swig_cplxdbl_convn(double _Complex, CCplxConst, creal, cimag); %swig_cplxdbl_convn(complex, CCplxConst, creal, cimag); /* declaring the typemaps */ -%typemaps_primitive(SWIG_TYPECHECK_CPLXFLT, float complex); -%typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, double complex); +%typemaps_primitive(SWIG_TYPECHECK_CPLXFLT, float _Complex); +%typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, double _Complex); %typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, complex); diff --git a/Source/CParse/cscanner.c b/Source/CParse/cscanner.c index 19a013803..6de66845c 100644 --- a/Source/CParse/cscanner.c +++ b/Source/CParse/cscanner.c @@ -912,6 +912,10 @@ int yylex(void) { yylval.type = NewSwigType(T_COMPLEX); return (TYPE_COMPLEX); } + if (strcmp(yytext, "_Complex") == 0) { + yylval.type = NewSwigType(T_COMPLEX); + return (TYPE_COMPLEX); + } if (strcmp(yytext, "restrict") == 0) return (yylex()); } diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 8029dee3d..682e317d4 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -6232,19 +6232,19 @@ primitive_type_list : type_specifier { } else if (Cmp($1.type,"double") == 0) { if (Cmp($2.type,"long") == 0) { $$.type = NewString("long double"); - } else if (Cmp($2.type,"complex") == 0) { - $$.type = NewString("double complex"); + } else if (Cmp($2.type,"complex") == 0 || Cmp($2.type,"_Complex") == 0) { + $$.type = NewString("double _Complex"); } else { err = 1; } } else if (Cmp($1.type,"float") == 0) { - if (Cmp($2.type,"complex") == 0) { - $$.type = NewString("float complex"); + if (Cmp($2.type,"complex") == 0 || Cmp($2.type,"_Complex") == 0) { + $$.type = NewString("float _Complex"); } else { err = 1; } - } else if (Cmp($1.type,"complex") == 0) { - $$.type = NewStringf("%s complex", $2.type); + } else if (Cmp($1.type,"complex") == 0 || Cmp($1.type,"_Complex") == 0) { + $$.type = NewStringf("%s _Complex", $2.type); } else { err = 1; } diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c index 7564db1a6..e48b80ce2 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -1453,9 +1453,9 @@ int SwigType_type(const SwigType *t) { return T_DOUBLE; if (strcmp(c, "long double") == 0) return T_LONGDOUBLE; - if (!cparse_cplusplus && (strcmp(c, "float complex") == 0)) + if (!cparse_cplusplus && (strcmp(c, "float _Complex") == 0)) return T_FLTCPLX; - if (!cparse_cplusplus && (strcmp(c, "double complex") == 0)) + if (!cparse_cplusplus && (strcmp(c, "double _Complex") == 0)) return T_DBLCPLX; if (!cparse_cplusplus && (strcmp(c, "complex") == 0)) return T_COMPLEX; From 1adc7dac5db7455264d590340573c3aff253c624 Mon Sep 17 00:00:00 2001 From: Leo Singer Date: Tue, 16 Jun 2020 19:55:50 -0400 Subject: [PATCH 2/5] Small corrections for handling C99 _Complex --- Examples/test-suite/complextest.i | 6 +++--- Lib/javascript/jsc/ccomplex.i | 2 -- Lib/javascript/v8/ccomplex.i | 2 -- Lib/python/ccomplex.i | 2 -- Source/CParse/cscanner.c | 4 ---- Source/CParse/parser.y | 6 +++--- Source/Swig/typesys.c | 2 -- 7 files changed, 6 insertions(+), 18 deletions(-) diff --git a/Examples/test-suite/complextest.i b/Examples/test-suite/complextest.i index 592512b45..57d00a946 100644 --- a/Examples/test-suite/complextest.i +++ b/Examples/test-suite/complextest.i @@ -72,15 +72,15 @@ %inline { - complex Conj(complex a) + double complex Conj(complex a) { return conj(a); } - complex float Conjf(float complex a) + float complex Conjf(float complex a) { - return conj(a); + return conjf(a); } } diff --git a/Lib/javascript/jsc/ccomplex.i b/Lib/javascript/jsc/ccomplex.i index 64fe00ec9..9c3080b60 100644 --- a/Lib/javascript/jsc/ccomplex.i +++ b/Lib/javascript/jsc/ccomplex.i @@ -18,9 +18,7 @@ %swig_cplxflt_convn(float _Complex, CCplxConst, creal, cimag); %swig_cplxdbl_convn(double _Complex, CCplxConst, creal, cimag); -%swig_cplxdbl_convn(complex, CCplxConst, creal, cimag); /* declaring the typemaps */ %typemaps_primitive(SWIG_TYPECHECK_CPLXFLT, float _Complex); %typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, double _Complex); -%typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, complex); diff --git a/Lib/javascript/v8/ccomplex.i b/Lib/javascript/v8/ccomplex.i index b1e766354..7669cb86a 100644 --- a/Lib/javascript/v8/ccomplex.i +++ b/Lib/javascript/v8/ccomplex.i @@ -18,9 +18,7 @@ %swig_cplxflt_convn(float _Complex, CCplxConst, creal, cimag); %swig_cplxdbl_convn(double _Complex, CCplxConst, creal, cimag); -%swig_cplxdbl_convn(complex, CCplxConst, creal, cimag); /* declaring the typemaps */ %typemaps_primitive(SWIG_TYPECHECK_CPLXFLT, float _Complex); %typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, double _Complex); -%typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, complex); diff --git a/Lib/python/ccomplex.i b/Lib/python/ccomplex.i index 17163506b..eba278905 100644 --- a/Lib/python/ccomplex.i +++ b/Lib/python/ccomplex.i @@ -18,9 +18,7 @@ %swig_cplxflt_convn(float _Complex, CCplxConst, creal, cimag); %swig_cplxdbl_convn(double _Complex, CCplxConst, creal, cimag); -%swig_cplxdbl_convn(complex, CCplxConst, creal, cimag); /* declaring the typemaps */ %typemaps_primitive(SWIG_TYPECHECK_CPLXFLT, float _Complex); %typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, double _Complex); -%typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, complex); diff --git a/Source/CParse/cscanner.c b/Source/CParse/cscanner.c index 6de66845c..a3702704e 100644 --- a/Source/CParse/cscanner.c +++ b/Source/CParse/cscanner.c @@ -908,10 +908,6 @@ int yylex(void) { if (strcmp(yytext, "class") == 0) { Swig_warning(WARN_PARSE_CLASS_KEYWORD, cparse_file, cparse_line, "class keyword used, but not in C++ mode.\n"); } - if (strcmp(yytext, "complex") == 0) { - yylval.type = NewSwigType(T_COMPLEX); - return (TYPE_COMPLEX); - } if (strcmp(yytext, "_Complex") == 0) { yylval.type = NewSwigType(T_COMPLEX); return (TYPE_COMPLEX); diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 682e317d4..cccd613fe 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -6232,18 +6232,18 @@ primitive_type_list : type_specifier { } else if (Cmp($1.type,"double") == 0) { if (Cmp($2.type,"long") == 0) { $$.type = NewString("long double"); - } else if (Cmp($2.type,"complex") == 0 || Cmp($2.type,"_Complex") == 0) { + } else if (Cmp($2.type,"_Complex") == 0) { $$.type = NewString("double _Complex"); } else { err = 1; } } else if (Cmp($1.type,"float") == 0) { - if (Cmp($2.type,"complex") == 0 || Cmp($2.type,"_Complex") == 0) { + if (Cmp($2.type,"_Complex") == 0) { $$.type = NewString("float _Complex"); } else { err = 1; } - } else if (Cmp($1.type,"complex") == 0 || Cmp($1.type,"_Complex") == 0) { + } else if (Cmp($1.type,"_Complex") == 0) { $$.type = NewStringf("%s _Complex", $2.type); } else { err = 1; diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c index e48b80ce2..b306c95e8 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -1457,8 +1457,6 @@ int SwigType_type(const SwigType *t) { return T_FLTCPLX; if (!cparse_cplusplus && (strcmp(c, "double _Complex") == 0)) return T_DBLCPLX; - if (!cparse_cplusplus && (strcmp(c, "complex") == 0)) - return T_COMPLEX; if (strcmp(c, "void") == 0) return T_VOID; if (strcmp(c, "bool") == 0) From 07b4b274e5048c23be73a9a85b53461d369dc2a2 Mon Sep 17 00:00:00 2001 From: Leo Singer Date: Wed, 17 Jun 2020 10:14:07 -0400 Subject: [PATCH 3/5] Restore _Complex as standalone type --- Lib/javascript/jsc/ccomplex.i | 2 ++ Lib/javascript/v8/ccomplex.i | 2 ++ Lib/python/ccomplex.i | 2 ++ Source/Swig/typesys.c | 2 ++ 4 files changed, 8 insertions(+) diff --git a/Lib/javascript/jsc/ccomplex.i b/Lib/javascript/jsc/ccomplex.i index 9c3080b60..00680d3b4 100644 --- a/Lib/javascript/jsc/ccomplex.i +++ b/Lib/javascript/jsc/ccomplex.i @@ -18,7 +18,9 @@ %swig_cplxflt_convn(float _Complex, CCplxConst, creal, cimag); %swig_cplxdbl_convn(double _Complex, CCplxConst, creal, cimag); +%swig_cplxdbl_convn(_Complex, CCplxConst, creal, cimag); /* declaring the typemaps */ %typemaps_primitive(SWIG_TYPECHECK_CPLXFLT, float _Complex); %typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, double _Complex); +%typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, _Complex); diff --git a/Lib/javascript/v8/ccomplex.i b/Lib/javascript/v8/ccomplex.i index 7669cb86a..a753ae180 100644 --- a/Lib/javascript/v8/ccomplex.i +++ b/Lib/javascript/v8/ccomplex.i @@ -18,7 +18,9 @@ %swig_cplxflt_convn(float _Complex, CCplxConst, creal, cimag); %swig_cplxdbl_convn(double _Complex, CCplxConst, creal, cimag); +%swig_cplxdbl_convn(_Complex, CCplxConst, creal, cimag); /* declaring the typemaps */ %typemaps_primitive(SWIG_TYPECHECK_CPLXFLT, float _Complex); %typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, double _Complex); +%typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, _Complex); diff --git a/Lib/python/ccomplex.i b/Lib/python/ccomplex.i index eba278905..1652816ca 100644 --- a/Lib/python/ccomplex.i +++ b/Lib/python/ccomplex.i @@ -18,7 +18,9 @@ %swig_cplxflt_convn(float _Complex, CCplxConst, creal, cimag); %swig_cplxdbl_convn(double _Complex, CCplxConst, creal, cimag); +%swig_cplxdbl_convn(_Complex, CCplxConst, creal, cimag); /* declaring the typemaps */ %typemaps_primitive(SWIG_TYPECHECK_CPLXFLT, float _Complex); %typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, double _Complex); +%typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, _Complex); diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c index b306c95e8..d6d6bcc88 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -1457,6 +1457,8 @@ int SwigType_type(const SwigType *t) { return T_FLTCPLX; if (!cparse_cplusplus && (strcmp(c, "double _Complex") == 0)) return T_DBLCPLX; + if (!cparse_cplusplus && (strcmp(c, "_Complex") == 0)) + return T_COMPLEX; if (strcmp(c, "void") == 0) return T_VOID; if (strcmp(c, "bool") == 0) From 511df0e6428ae86696ac44e381ba0c736a3742fc Mon Sep 17 00:00:00 2001 From: Leo Singer Date: Wed, 17 Jun 2020 13:03:17 -0400 Subject: [PATCH 4/5] More C99 complex fixes, plus Python tests --- Examples/test-suite/complextest.i | 53 ++++++++++++++++++- Examples/test-suite/python/Makefile.in | 1 + .../test-suite/python/complextest_runme.py | 37 +++++++++---- Lib/javascript/jsc/ccomplex.i | 1 + Lib/javascript/v8/ccomplex.i | 1 + Lib/python/ccomplex.i | 1 + Source/CParse/parser.y | 2 +- 7 files changed, 83 insertions(+), 13 deletions(-) diff --git a/Examples/test-suite/complextest.i b/Examples/test-suite/complextest.i index 57d00a946..4d40bc524 100644 --- a/Examples/test-suite/complextest.i +++ b/Examples/test-suite/complextest.i @@ -68,20 +68,69 @@ %{ +#include %} %inline { - double complex Conj(complex a) + complex double Conj(complex double a) { return conj(a); } - float complex Conjf(float complex a) + complex float Conjf(complex float a) { return conjf(a); } + + + double complex Conj1(double complex a) + { + return conj(a); + } + + + float complex Conjf1(float complex a) + { + return conjf(a); + } + + + _Complex double Conj2(_Complex double a) + { + return conj(a); + } + + + _Complex float Conjf2(_Complex float a) + { + return conjf(a); + } + + + double _Complex Conj3(double _Complex a) + { + return conj(a); + } + + + float _Complex Conjf3(float _Complex a) + { + return conjf(a); + } + + + complex Conj4(complex a) + { + return conj(a); + } + + + _Complex Conj5(_Complex a) + { + return conj(a); + } } diff --git a/Examples/test-suite/python/Makefile.in b/Examples/test-suite/python/Makefile.in index 4c0507cbb..86d5e37f2 100644 --- a/Examples/test-suite/python/Makefile.in +++ b/Examples/test-suite/python/Makefile.in @@ -92,6 +92,7 @@ CPP11_TEST_CASES = \ cpp11_std_unordered_set \ C_TEST_CASES += \ + complextest \ file_test \ li_cstring \ li_cwstring \ diff --git a/Examples/test-suite/python/complextest_runme.py b/Examples/test-suite/python/complextest_runme.py index 5cfc7ccab..2b3d6fda9 100644 --- a/Examples/test-suite/python/complextest_runme.py +++ b/Examples/test-suite/python/complextest_runme.py @@ -14,17 +14,34 @@ if complextest.Conj2(a) != a.conjugate(): if complextest.Conjf2(a) != a.conjugate(): raise RuntimeError, "bad complex mapping" +if 'Conj3' in dir(complextest): + if complextest.Conj3(a) != a.conjugate(): + raise RuntimeError, "bad complex mapping" -v = (complex(1, 2), complex(2, 3), complex(4, 3), 1) +if 'Conjf3' in dir(complextest): + if complextest.Conjf3(a) != a.conjugate(): + raise RuntimeError, "bad complex mapping" -if len(complextest.CopyHalf(v)) != 2: - raise RuntimeError("CopyHalf failed") +if 'Conj4' in dir(complextest): + if complextest.Conj4(a) != a.conjugate(): + raise RuntimeError, "bad complex mapping" -if len(complextest.CopyHalfRef(v)) != 2: - raise RuntimeError("CopyHalfRef failed") +if 'Conj5' in dir(complextest): + if complextest.Conj5(a) != a.conjugate(): + raise RuntimeError, "bad complex mapping" -p = complextest.ComplexPair() -p.z1 = complex(0, 1) -p.z2 = complex(0, -1) -if complextest.Conj(p.z2) != p.z1: - raise RuntimeError, "bad complex mapping" +if 'CopyHalf' in dir(complextest): + + v = (complex(1, 2), complex(2, 3), complex(4, 3), 1) + + if len(complextest.CopyHalf(v)) != 2: + raise RuntimeError("CopyHalf failed") + + if len(complextest.CopyHalfRef(v)) != 2: + raise RuntimeError("CopyHalfRef failed") + + p = complextest.ComplexPair() + p.z1 = complex(0, 1) + p.z2 = complex(0, -1) + if complextest.Conj(p.z2) != p.z1: + raise RuntimeError, "bad complex mapping" diff --git a/Lib/javascript/jsc/ccomplex.i b/Lib/javascript/jsc/ccomplex.i index 00680d3b4..e58dbf719 100644 --- a/Lib/javascript/jsc/ccomplex.i +++ b/Lib/javascript/jsc/ccomplex.i @@ -12,6 +12,7 @@ #include %} +#define complex _Complex /* C complex constructor */ #define CCplxConst(r, i) ((r) + I*(i)) diff --git a/Lib/javascript/v8/ccomplex.i b/Lib/javascript/v8/ccomplex.i index a753ae180..b4b925da7 100644 --- a/Lib/javascript/v8/ccomplex.i +++ b/Lib/javascript/v8/ccomplex.i @@ -12,6 +12,7 @@ #include %} +#define complex _Complex /* C complex constructor */ #define CCplxConst(r, i) ((r) + I*(i)) diff --git a/Lib/python/ccomplex.i b/Lib/python/ccomplex.i index 1652816ca..b99f96a48 100644 --- a/Lib/python/ccomplex.i +++ b/Lib/python/ccomplex.i @@ -12,6 +12,7 @@ #include %} +#define complex _Complex /* C complex constructor */ #define CCplxConst(r, i) ((r) + I*(i)) diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index cccd613fe..c48d3a6f2 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -6294,7 +6294,7 @@ type_specifier : TYPE_INT { $$.type = 0; } | TYPE_COMPLEX { - $$.type = NewString("complex"); + $$.type = NewString("_Complex"); $$.us = 0; } | TYPE_NON_ISO_INT8 { From 8245277ad3acd9308ce28c40508b999e9496b27e Mon Sep 17 00:00:00 2001 From: Leo Singer Date: Sun, 21 Jun 2020 12:29:42 -0400 Subject: [PATCH 5/5] Remove test for unsupported complex or _Complex by itself --- Examples/test-suite/complextest.i | 12 ------------ Examples/test-suite/python/complextest_runme.py | 8 -------- 2 files changed, 20 deletions(-) diff --git a/Examples/test-suite/complextest.i b/Examples/test-suite/complextest.i index 4d40bc524..622b38058 100644 --- a/Examples/test-suite/complextest.i +++ b/Examples/test-suite/complextest.i @@ -119,18 +119,6 @@ { return conjf(a); } - - - complex Conj4(complex a) - { - return conj(a); - } - - - _Complex Conj5(_Complex a) - { - return conj(a); - } } diff --git a/Examples/test-suite/python/complextest_runme.py b/Examples/test-suite/python/complextest_runme.py index 2b3d6fda9..53b2b8d6b 100644 --- a/Examples/test-suite/python/complextest_runme.py +++ b/Examples/test-suite/python/complextest_runme.py @@ -22,14 +22,6 @@ if 'Conjf3' in dir(complextest): if complextest.Conjf3(a) != a.conjugate(): raise RuntimeError, "bad complex mapping" -if 'Conj4' in dir(complextest): - if complextest.Conj4(a) != a.conjugate(): - raise RuntimeError, "bad complex mapping" - -if 'Conj5' in dir(complextest): - if complextest.Conj5(a) != a.conjugate(): - raise RuntimeError, "bad complex mapping" - if 'CopyHalf' in dir(complextest): v = (complex(1, 2), complex(2, 3), complex(4, 3), 1)