diff options
author | Olly Betts <olly@survex.com> | 2023-05-08 15:39:53 +1200 |
---|---|---|
committer | Olly Betts <olly@survex.com> | 2023-05-08 15:44:24 +1200 |
commit | 15b739d60e9586025b665c19a85a09280d4ff9ad (patch) | |
tree | 0d7458e7afd14699fc0e3146cb0e46c8452cc0d0 /Source | |
parent | 281af00437752e4340bfb6c8ca6bb97434bea5a4 (diff) | |
download | swig-15b739d60e9586025b665c19a85a09280d4ff9ad.tar.gz |
[PHP] Wrap method with both static and non-static overloads
We now wrap this as a non-static method in PHP, which means the static
form only callable via an object.
Previously this case could end up wrapped as static or non-static
in PHP. If it was wrapped as static, attempting to call non-static
overloaded forms would crash with a segmentation fault.
See #2544
Diffstat (limited to 'Source')
-rw-r--r-- | Source/Modules/php.cxx | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index b272aab81..c2b19367d 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -239,6 +239,15 @@ class PHPTypes { // Does the node for this have directorNode set? bool has_director_node; + // Track if all the overloads of a method are static. + // + // We should only flag a dispatch method as ACC_STATIC if all the dispatched + // to methods are static. If we have both static and non-static methods in + // the overloaded set we omit ACC_STATIC, and then all the methods are + // callable (though the static ones only via an object). If we set + // ACC_STATIC we get a crash on an attempt to call a non-static method. + bool all_overloads_static; + // Used to clamp the required number of parameters in the arginfo to be // compatible with any parent class version of the method. int num_required; @@ -332,6 +341,7 @@ public: } arginfo_id = Copy(Getattr(n, "sym:name")); has_director_node = (Getattr(n, "directorNode") != NULL); + all_overloads_static = true; } ~PHPTypes() { @@ -339,6 +349,10 @@ public: Delete(byref); } + void not_all_static() { all_overloads_static = false; } + + bool get_all_static() const { return all_overloads_static; } + void adjust(int num_required_, bool php_constructor) { num_required = std::min(num_required, num_required_); if (php_constructor) { @@ -1021,7 +1035,7 @@ public: if (constructorRenameOverload) { Append(modes, " | ZEND_ACC_STATIC"); } - } else if (wrapperType == staticmemberfn || Cmp(Getattr(n, "storage"), "static") == 0) { + } else if (phptypes->get_all_static()) { modes = NewString("ZEND_ACC_PUBLIC | ZEND_ACC_STATIC"); } else { modes = NewString("ZEND_ACC_PUBLIC"); @@ -1365,6 +1379,9 @@ public: phptypes = new PHPTypes(n); SetVoid(all_phptypes, key, phptypes); } + if (!(wrapperType == staticmemberfn || Cmp(Getattr(n, "storage"), "static") == 0)) { + phptypes->not_all_static(); + } } f = NewWrapper(); |