From c7ab6a01c6582b92db9328e2f3daa67081f05f6e Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 12 Jan 2024 08:45:26 +0000 Subject: [PATCH] Fix seg fault handling friend constructor/destructor declarations Closes #2749 --- CHANGES.current | 3 ++ Examples/test-suite/friends.i | 34 +++++++++++++++++++++++ Examples/test-suite/php/friends_runme.php | 2 +- Source/CParse/parser.y | 5 +++- 4 files changed, 42 insertions(+), 2 deletions(-) #diff --git a/CHANGES.current b/CHANGES.current #index 030aa0b19..f235d9a09 100644 #--- a/CHANGES.current #+++ b/CHANGES.current #@@ -7,6 +7,9 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ # Version 4.2.1 (in progress) # =========================== # #+2024-01-12: wsfulton #+ #2749 Fix seg fault handling friend constructor/destructor declarations. #+ # 2024-01-12: olly # [Ruby,Tcl] #2751 Fix -external-runtime output to define # SWIG_snprintf (bug introduced in 4.2.0). diff --git a/Examples/test-suite/friends.i b/Examples/test-suite/friends.i index a2a5151e0..879f3b3bc 100644 --- a/Examples/test-suite/friends.i +++ b/Examples/test-suite/friends.i @@ -148,6 +148,40 @@ } } +%inline %{ + class CModelParameterSpecies; + class CModelParameterCompartment { + CModelParameterSpecies *species; + public: + int getSpeciesVal(); + CModelParameterCompartment(); + ~CModelParameterCompartment(); + }; + class CModelParameterSpecies + { + int private_val; + public: + // Friend function-declarations are silently ignored (including constructor and destructor declarations) + friend CModelParameterCompartment::~CModelParameterCompartment(); + friend CModelParameterCompartment::CModelParameterCompartment(); + friend int CModelParameterCompartment::getSpeciesVal(); + }; +%} + +%{ +CModelParameterCompartment::~CModelParameterCompartment() { + species = new CModelParameterSpecies(); + species->private_val = 1; +} +CModelParameterCompartment::CModelParameterCompartment() { + species->private_val = 0; + delete species; +} +int CModelParameterCompartment::getSpeciesVal() { + return species->private_val; +} +%} + // Use this version with extra qualifiers to test SWIG as some compilers accept this namespace ns1 { namespace ns2 { diff --git a/Examples/test-suite/php/friends_runme.php b/Examples/test-suite/php/friends_runme.php index f0ef5df58..2e5d3b1fd 100644 --- a/Examples/test-suite/php/friends_runme.php +++ b/Examples/test-suite/php/friends_runme.php @@ -3,7 +3,7 @@ require "tests.php"; check::functions(array('globalscope','mix','get_val2','get_val3','bas','baz','bar','get_val1','set')); -check::classes(array('friends','Foo','A','B','D_i','D_d')); +check::classes(array('friends','Foo','A','B','D_i','D_d','CModelParameterCompartment','CModelParameterSpecies')); // No new vars check::globals(array()); diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index e5a79f128..edf38c360 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -4732,7 +4732,10 @@ cpp_member : cpp_member_no_dox */ cpp_constructor_decl : storage_class type LPAREN parms RPAREN ctor_end { - if (inclass || extendmode) { + /* Cannot be a constructor declaration/definition if parsed as a friend destructor/constructor + or a badly declared friend function without return type */ + int isfriend = Strstr($1, "friend") != NULL; + if (!isfriend && (inclass || extendmode)) { String *name = SwigType_templateprefix($2); /* A constructor can optionally be declared with template parameters before C++20, strip these off */ SwigType *decl = NewStringEmpty(); $$ = new_node("constructor"); -- 2.43.0