diff --git a/src/Generator/CallArgumentGenerator.php b/src/Generator/CallArgumentGenerator.php index f7d68649..19876b35 100644 --- a/src/Generator/CallArgumentGenerator.php +++ b/src/Generator/CallArgumentGenerator.php @@ -314,6 +314,19 @@ protected function parseNativeCallArgs( // iteration instead of accumulating arguments. $variadicVar = $this->addTmpVar(Type::ARRAY); $this->context->beforeStmtLines[] = $variadicVar . '.unset();'; + if ($argInfo->byRef) { + // The aggregation array owns the second reference to + // every caller slot, so queue its release before the + // per-argument RefWrap::commit() lines are appended: + // committing while the second reference is alive + // trips the typed-reference escape check. The guard + // also releases during C++ exception unwinding into + // a PHP catch block. + $cleanupGuard = $this->genTmpVarName(); + $this->context->beforeStmtLines[] = 'php::ArrayCleanupGuard ' . $cleanupGuard + . '{' . $variadicVar . '};'; + $this->context->afterStmtLines[] = $cleanupGuard . '.cleanup();'; + } } if ($arg->unpack) { $method = $argInfo->byRef ? 'mergeReferences' : 'merge'; @@ -338,15 +351,6 @@ protected function parseNativeCallArgs( } if ($variadicVar !== null) { $resolvedArgs[$variadicArgIndex] = $variadicVar; - if ($functionDef->argInfoList[$variadicArgIndex]->byRef) { - // The aggregation array owns the second reference to every - // caller slot. Release it after the full PHP statement and - // also during C++ exception unwinding into a PHP catch block. - $cleanupGuard = $this->genTmpVarName(); - $this->context->beforeStmtLines[] = 'php::ArrayCleanupGuard ' . $cleanupGuard - . '{' . $variadicVar . '};'; - $this->context->afterStmtLines[] = $cleanupGuard . '.cleanup();'; - } } ksort($resolvedArgs); return implode(', ', $resolvedArgs); diff --git a/tests/compiler/variadic/by-reference-variadic-local.phpt b/tests/compiler/variadic/by-reference-variadic-local.phpt new file mode 100644 index 00000000..27200f94 --- /dev/null +++ b/tests/compiler/variadic/by-reference-variadic-local.phpt @@ -0,0 +1,45 @@ +--TEST-- +by-ref variadic writes back to local variable arguments +--FILE-- +bump($b->p); + var_dump($b->p); + $arr = [7]; + bump($arr[0]); + var_dump($arr[0]); +} +?> +--EXPECT-- +int(11) +int(41) +int(12) +int(51) +int(15) +int(17)