From 4a6f6283aa7e0b15427c60988b0940dc0349f14a Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 8 Mar 2023 19:43:26 +0000 Subject: [PATCH] Fix duplicate const in generated code wrapping templates Fix duplicate const in generated code when template instantiation type is const and use of template parameter is also explicitly const, such as: template struct Conster { void cccc1(T const& t) {} }; %template(ConsterInt) Conster; Above previously led to generated code: (arg1)->cccc1((int const const &)*arg2); instead of (arg1)->cccc1((int const &)*arg2); --- CHANGES.current | 14 ++++++++++ Examples/test-suite/common.mk | 1 + .../java/template_type_collapse_runme.java | 26 +++++++++++++++++++ .../template_partial_specialization_typedef.i | 2 +- Examples/test-suite/template_type_collapse.i | 23 ++++++++++++++++ Source/Swig/stype.c | 15 ++++++++++- 6 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 Examples/test-suite/java/template_type_collapse_runme.java create mode 100644 Examples/test-suite/template_type_collapse.i diff --git a/CHANGES.current b/CHANGES.current index f0b916be0..ea3e81022 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) =========================== +2023-03-08: wsfulton + Fix duplicate const in generated code when template instantiation type is const + and use of template parameter is also explicitly const, such as: + + template struct Conster { + void cccc1(T const& t) {} + }; + %template(ConsterInt) Conster; + + Above previously led to generated code: + (arg1)->cccc1((int const const &)*arg2); + instead of + (arg1)->cccc1((int const &)*arg2); + 2023-03-01: wsfulton Partial template specialization fixes to support default arguments from the primary template's parameter list. diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index ff9b8538f..eb80977f7 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -501,6 +501,7 @@ CPP_TEST_CASES += \ template_tbase_template \ template_template_parameters \ template_template_template_parameters \ + template_type_collapse \ template_typedef \ template_typedef_class_template \ template_typedef_cplx \ diff --git a/Examples/test-suite/java/template_type_collapse_runme.java b/Examples/test-suite/java/template_type_collapse_runme.java new file mode 100644 index 000000000..11c6c8c5e --- /dev/null +++ b/Examples/test-suite/java/template_type_collapse_runme.java @@ -0,0 +1,26 @@ +import template_type_collapse.*; + +public class template_type_collapse_runme { + + static { + try { + System.loadLibrary("template_type_collapse"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) { + int i = 1234; + ConsterInt ci = new DerivedConsterInt(); + ci.cccc1(i); + ci.cccc2(i); + ci.cccc3(i); + ci.cccc4(i); + + DerivedConsterInt dci = new DerivedConsterInt(); + dci.dddd(i); + } +} + diff --git a/Examples/test-suite/template_partial_specialization_typedef.i b/Examples/test-suite/template_partial_specialization_typedef.i index 04475da1a..ad3457afe 100644 --- a/Examples/test-suite/template_partial_specialization_typedef.i +++ b/Examples/test-suite/template_partial_specialization_typedef.i @@ -93,7 +93,7 @@ namespace Two { template struct TwoParm { void b() {} void bbb(const T2 &t) {} }; template struct TwoParm { void c() {} void ccc(const T2 &t) {} }; template struct TwoParm { void d() {} void ddd(const T2 &t) {} }; - template struct TwoParm { void e() {} /*void eee(const T1 &t) {} TODO */}; + template struct TwoParm { void e() {} void eee(const T1 &t) {} }; template struct TwoParm { void f() {} }; template <> struct TwoParm { void g() {} }; } diff --git a/Examples/test-suite/template_type_collapse.i b/Examples/test-suite/template_type_collapse.i new file mode 100644 index 000000000..f6459db36 --- /dev/null +++ b/Examples/test-suite/template_type_collapse.i @@ -0,0 +1,23 @@ +%module template_type_collapse + +// Not attempted yet: reference collapsing + +// Tests merging multiple const when instantiating template types +%inline %{ +template struct Conster { + const T *constptr; + Conster() : constptr() {} + void cccc1(T const& t) {} + void cccc2(const T& t) {} + void cccc3(const T t) {} + void cccc4(T const t) {} +}; +template struct DerivedConster : Conster { + const T& dddd(const T& t) { + return t; + } +}; +%} +%template(ConsterInt) Conster; +%template(DerivedConsterInt) DerivedConster; + diff --git a/Source/Swig/stype.c b/Source/Swig/stype.c index e9cbf7b43..7a7b727a2 100644 --- a/Source/Swig/stype.c +++ b/Source/Swig/stype.c @@ -1275,6 +1275,11 @@ String *SwigType_manglestr(const SwigType *s) { * SwigType_typename_replace() * * Replaces a typename in a type with something else. Needed for templates. + * Collapses duplicate const into a single const. + * Reference collapsing probably should be implemented here. + * Example: + * t=r.q(const).T pat=T rep=int => r.q(const).int + * t=r.q(const).T pat=T rep=q(const).int => r.q(const).int (duplicate const removed) * ----------------------------------------------------------------------------- */ void SwigType_typename_replace(SwigType *t, String *pat, String *rep) { @@ -1297,7 +1302,15 @@ void SwigType_typename_replace(SwigType *t, String *pat, String *rep) { if (SwigType_issimple(e)) { if (Equal(e, pat)) { /* Replaces a type of the form 'pat' with 'rep' */ - Replace(e, pat, rep, DOH_REPLACE_ANY); + if (SwigType_isconst(rep) && i > 0 && SwigType_isconst(Getitem(elem, i - 1))) { + /* Collapse duplicate const into a single const */ + SwigType *rep_without_const = Copy(rep); + Delete(SwigType_pop(rep_without_const)); + Replace(e, pat, rep_without_const, DOH_REPLACE_ANY); + Delete(rep_without_const); + } else { + Replace(e, pat, rep, DOH_REPLACE_ANY); + } } else if (SwigType_istemplate(e)) { /* Replaces a type of the form 'pat' with 'rep' */ {