Skip to content

Commit da58c65

Browse files
committed
gen_stub: Support fn_flags2 flags
Change zend_function_entry.flags to a uint64_t to that both ZEND_ACC_ and ZEND_ACC2_ flags can be represented. Introduce ZEND_FENTRY_FLAGS(flags, flags2) to pass ZEND_ACC2_ flags to ZEND_RAW_FENTRY(), ZEND_FENTRY(). Source-level backwards compatibility is maintained, as passing raw ZEND_ACC_ flags to ZEND_RAW_FENTRY(), ZEND_FENTRY() still works.
1 parent ee3addf commit da58c65

6 files changed

Lines changed: 43 additions & 12 deletions

File tree

Zend/zend_API.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3045,7 +3045,6 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend
30453045
internal_function->prop_info = NULL;
30463046
internal_function->attributes = NULL;
30473047
internal_function->frameless_function_infos = ptr->frameless_function_infos;
3048-
internal_function->fn_flags2 = 0;
30493048
if (EG(active)) { // at run-time: this ought to only happen if registered with dl() or somehow temporarily at runtime
30503049
ZEND_MAP_PTR_INIT(internal_function->run_time_cache, zend_arena_calloc(&CG(arena), 1, zend_internal_run_time_cache_reserved_size()));
30513050
} else {
@@ -3055,7 +3054,7 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend
30553054
ZEND_MAP_PTR_INIT(internal_function->run_time_cache, NULL);
30563055
#endif
30573056
}
3058-
if (ptr->flags) {
3057+
if (ptr->flags & UINT32_MAX) {
30593058
if (!(ptr->flags & ZEND_ACC_PPP_MASK)) {
30603059
if (ptr->flags != ZEND_ACC_DEPRECATED && scope) {
30613060
zend_error(error_type, "Invalid access level for %s::%s() - access must be exactly one of public, protected or private", ZSTR_VAL(scope->name), ptr->fname);
@@ -3067,6 +3066,7 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend
30673066
} else {
30683067
internal_function->fn_flags = ZEND_ACC_PUBLIC;
30693068
}
3069+
internal_function->fn_flags2 = ptr->flags >> 32;
30703070

30713071
if (ptr->arg_info) {
30723072
zend_internal_function_info *info = (zend_internal_function_info*)ptr->arg_info;

Zend/zend_API.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ typedef struct _zend_function_entry {
3636
zif_handler handler;
3737
const struct _zend_internal_arg_info *arg_info;
3838
uint32_t num_args;
39-
uint32_t flags;
39+
uint64_t flags;
4040
const zend_frameless_function_info *frameless_function_infos;
4141
const char *doc_comment;
4242
} zend_function_entry;
@@ -74,6 +74,8 @@ typedef struct _zend_fcall_info_cache {
7474
#define ZEND_FUNCTION(name) ZEND_NAMED_FUNCTION(zif_##name)
7575
#define ZEND_METHOD(classname, name) ZEND_NAMED_FUNCTION(zim_##classname##_##name)
7676

77+
#define ZEND_FENTRY_FLAGS(flags, flags2) (((uint64_t)flags) | ((uint64_t)flags2 << 32))
78+
7779
#define ZEND_FENTRY(zend_name, name, arg_info, flags) { #zend_name, name, arg_info, (uint32_t) (sizeof(arg_info)/sizeof(struct _zend_internal_arg_info)-1), flags, NULL, NULL },
7880

7981
#define ZEND_RAW_FENTRY(zend_name, name, arg_info, flags, frameless_function_infos, doc_comment) { zend_name, name, arg_info, (uint32_t) (sizeof(arg_info)/sizeof(struct _zend_internal_arg_info)-1), flags, frameless_function_infos, doc_comment },

build/gen_stub.php

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,6 +1184,32 @@ public function isEmpty(): bool {
11841184
);
11851185
}
11861186

1187+
/**
1188+
* If we have ZEND_ACC2_ flags, represent as 'ZEND_FENTRY_FLAGS(flags1, flags2)'.
1189+
* Otherwise, represent as just 'flags1' (backwards compatible).
1190+
*/
1191+
private function formatFlags(array $flags): string {
1192+
$flags1 = [];
1193+
$flags2 = [];
1194+
foreach ($flags as $flag) {
1195+
if (str_starts_with($flag, 'ZEND_ACC2_')) {
1196+
$flags2[] = $flag;
1197+
} else {
1198+
$flags1[] = $flag;
1199+
}
1200+
}
1201+
1202+
if ($flags2 !== []) {
1203+
return sprintf(
1204+
'ZEND_FENTRY_FLAGS(%s, %s)',
1205+
$flags1 === [] ? 0 : implode("|", $flags1),
1206+
implode("|", $flags2),
1207+
);
1208+
}
1209+
1210+
return implode("|", $flags1);
1211+
}
1212+
11871213
public function generateVersionDependentFlagCode(
11881214
string $codeTemplate,
11891215
?int $phpVersionIdMinimumCompatibility,
@@ -1199,7 +1225,7 @@ public function generateVersionDependentFlagCode(
11991225
if (empty($flagsByPhpVersions[$currentPhpVersion])) {
12001226
return '';
12011227
}
1202-
return sprintf($codeTemplate, implode("|", $flagsByPhpVersions[$currentPhpVersion]));
1228+
return sprintf($codeTemplate, $this->formatFlags($flagsByPhpVersions[$currentPhpVersion]));
12031229
}
12041230

12051231
ksort($flagsByPhpVersions);
@@ -1240,7 +1266,7 @@ public function generateVersionDependentFlagCode(
12401266
reset($flagsByPhpVersions);
12411267
$firstVersion = key($flagsByPhpVersions);
12421268
if ($firstVersion === $phpVersionIdMinimumCompatibility) {
1243-
return sprintf($codeTemplate, implode("|", reset($flagsByPhpVersions)));
1269+
return sprintf($codeTemplate, $this->formatFlags(reset($flagsByPhpVersions)));
12441270
}
12451271
}
12461272

@@ -1253,7 +1279,7 @@ public function generateVersionDependentFlagCode(
12531279

12541280
$code .= "$if (PHP_VERSION_ID >= $version)\n";
12551281

1256-
$code .= sprintf($codeTemplate, implode("|", $versionFlags));
1282+
$code .= sprintf($codeTemplate, $this->formatFlags($versionFlags));
12571283
$code .= $endif;
12581284

12591285
$i++;

ext/standard/basic_functions.stub.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1641,7 +1641,10 @@ function in_array(mixed $needle, array $haystack, bool $strict = false): bool {}
16411641
*/
16421642
function array_search(mixed $needle, array $haystack, bool $strict = false): int|string|false {}
16431643

1644-
/** @prefer-ref $array */
1644+
/**
1645+
* @prefer-ref $array
1646+
* @forbid-dynamic-calls
1647+
*/
16451648
function extract(array &$array, int $flags = EXTR_OVERWRITE, string $prefix = ""): int {}
16461649

16471650
/**

ext/standard/basic_functions_arginfo.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/standard/basic_functions_decl.h

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)