[php] Adjust #required params for subclass methods

If the same method name is implemented in a parent class then the
subclass can't have more required parameters than that or else we
get a compatibility error when the module is loaded.

The testsuite wasn't catching this problem because it was no longer
trying to load the modules for testcases without _runme.php, because
the mechanism to do that relied on there being a generated .php
wrapper, which we no longer have by default.  Fix that to provide a
regression test for this fix.

See #2151
This commit is contained in:
Olly Betts 2022-06-12 10:12:02 +12:00
commit 9cdf46e8c8
5 changed files with 29 additions and 15 deletions

View file

@ -218,17 +218,31 @@ class PHPTypes {
// the dispatch function. If NULL, no parameters are passed by reference.
List *byref;
// Used to clamp the required number of parameters in the arginfo to be
// compatible with any parent class version of the method.
int required_clamp;
public:
PHPTypes() : merged_types(NewList()), byref(NULL) { }
PHPTypes(int num_required)
: merged_types(NewList()),
byref(NULL),
required_clamp(num_required) { }
PHPTypes(const PHPTypes *o)
: merged_types(Copy(o->merged_types)), byref(Copy(o->byref)) { }
: merged_types(Copy(o->merged_types)),
byref(Copy(o->byref)),
required_clamp(o->required_clamp) { }
~PHPTypes() {
Delete(merged_types);
Delete(byref);
}
int adjust_num_required(int num_required) {
required_clamp = std::min(num_required, required_clamp);
return required_clamp;
}
// key is 0 for return type, or >= 1 for parameters numbered from 1
void process_phptype(Node *n, int key, const String_or_char *attribute_name);
@ -712,7 +726,7 @@ public:
}
}
int num_required = emit_num_required(l);
int num_required = phptypes->adjust_num_required(emit_num_required(l));
// We want to only emit each different arginfo once, as that reduces the
// size of both the generated source code and the compiled extension
@ -1214,7 +1228,7 @@ public:
}
}
if (!phptypes) {
phptypes = new PHPTypes();
phptypes = new PHPTypes(emit_num_required(l));
}
if (class_name) {
SetVoid(all_phptypes, NewStringf("%s:%s", class_name, wname), phptypes);