Currently, disabling a function only replaces the internal
function handler with one that throws a warning, and a few
places in the engine special-case such functions, such as
function_exists. This leaves us with a Schrödinger's function,
which both does not exist (function_exists returns false) and
does exist (you cannot define a function with the same name).
In particular, this prevents the implementation of robust
polyfills, as reported in https://bugs.php.net/bug.php?id=79382:
if (!function_exists('getallheaders')) {
function getallheaders(...) { ... }
}
If getallheaders() is a disabled function, this code will break.
This patch changes disable_functions to remove the functions from
the function table completely. For all intents and purposes, it
will look like the function does not exist.
This also renders two bits of PHP functionality obsolete and thus
deprecated:
* ReflectionFunction::isDisabled(), as it will no longer be
possible to construct the ReflectionFunction of a disabled
function in the first place.
* get_defined_functions() with $exclude_disabled=false, as
get_defined_functions() now never returns disabled functions.
Fixed bug #79382.
Closes GH-5473.
Make sure explicitly specified func_info is a subset of
automatically computed info. This will at least prevent
cases where a type is removed from stubs, but not removed
from func_info.
Closes GH-5471.
Mark "throw" used in expression context with a flag, and don't
treat it as a BB terminator in that case. This prevents us from
optimizing away the following opcodes as unreachable, which may
result in live ranges being dropped incorrectly.
Close GH-5450.
`func_get_args()` may return `zend_empty_array`, which has refcount 2
to enforce separation. We have to cater to that during type inference
so that the optimization in the JIT macro `SEPARATE_ARRAY` doesn't
prevent the separation.
This may produce different behavior if operator overloading is
involved, and may change the error message.
If there's strong interest, this could be done in the DFA pass
with available type information. It does not look particularly
practically useful to me though.
After thinking about this a bit more, the code here was too
conservative. We know that everything but an object is going to
throw, so it's sufficient to restrict the type to MAY_BE_OBJECT.
The change in the test is weird but not incorrect, because it
operates on empty inferred types, in which case the code must be
dead (which it is). We should probably add a more explicit removal
of code working on empty types.