Skip to content

Commit 5f33d80

Browse files
committed
Fix constant generation
1 parent 928df50 commit 5f33d80

8 files changed

+88
-31
lines changed

Zend/zend_constants.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "zend_operators.h"
2626
#include "zend_globals.h"
2727
#include "zend_API.h"
28+
#include "zend_constants_arginfo.h"
2829

2930
/* Protection from recursive self-referencing class constants */
3031
#define IS_CONSTANT_VISITED_MARK 0x80
@@ -108,10 +109,9 @@ void zend_startup_constants(void)
108109

109110
void zend_register_standard_constants(void)
110111
{
111-
REGISTER_MAIN_LONG_CONSTANT("E_ERROR", E_ERROR, CONST_PERSISTENT | CONST_CS);
112+
register_zend_constants_consts(0);
113+
112114
REGISTER_MAIN_LONG_CONSTANT("E_RECOVERABLE_ERROR", E_RECOVERABLE_ERROR, CONST_PERSISTENT | CONST_CS);
113-
REGISTER_MAIN_LONG_CONSTANT("E_WARNING", E_WARNING, CONST_PERSISTENT | CONST_CS);
114-
REGISTER_MAIN_LONG_CONSTANT("E_PARSE", E_PARSE, CONST_PERSISTENT | CONST_CS);
115115
REGISTER_MAIN_LONG_CONSTANT("E_NOTICE", E_NOTICE, CONST_PERSISTENT | CONST_CS);
116116
REGISTER_MAIN_LONG_CONSTANT("E_STRICT", E_STRICT, CONST_PERSISTENT | CONST_CS);
117117
REGISTER_MAIN_LONG_CONSTANT("E_DEPRECATED", E_DEPRECATED, CONST_PERSISTENT | CONST_CS);

Zend/zend_constants.stub.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
/** @generate-class-entries */
4+
5+
/** @cname E_ERROR */
6+
const E_ERROR = 1;
7+
/** @cname E_WARNING */
8+
const E_WARNING = 2;
9+
/** @cname E_PARSE */
10+
const E_PARSE = 4;
11+
const E_NOTICE = UNKNOWN;
12+
const E_CORE_ERROR = UNKNOWN;
13+
const E_CORE_WARNING = UNKNOWN;
14+
const E_COMPILE_ERROR = UNKNOWN;
15+
const E_COMPILE_WARNING = UNKNOWN;
16+
const E_USER_ERROR = UNKNOWN;
17+
const E_USER_WARNING = UNKNOWN;
18+
const E_USER_NOTICE = UNKNOWN;
19+
const E_STRICT = UNKNOWNN;
20+
const E_RECOVERABLE_ERROR = UNKNOWN;
21+
const E_DEPRECATED = UNKNOWN;
22+
const E_USER_DEPRECATED = UNKNOWN;

Zend/zend_constants_arginfo.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/* This is a generated file, edit the .stub.php file instead.
2+
* Stub hash: 77f39014422633b26c62049152878f0df242b896 */
3+
4+
#include "zend_constants_consts.h"
5+
6+
7+
8+
static void register_zend_constants_consts(int module_number)
9+
{
10+
REGISTER_LONG_CONSTANT("E_ERROR", E_ERROR, CONST_CS | CONST_PERSISTENT);
11+
REGISTER_LONG_CONSTANT("E_WARNING", E_WARNING, CONST_CS | CONST_PERSISTENT);
12+
REGISTER_LONG_CONSTANT("E_PARSE", E_PARSE, CONST_CS | CONST_PERSISTENT);
13+
}

Zend/zend_constants_consts.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/* This is a generated file, edit the .stub.php file instead.
2+
* Stub hash: 77f39014422633b26c62049152878f0df242b896 */
3+
4+
#define E_ERROR 1
5+
#define E_WARNING 2
6+
#define E_PARSE 4

Zend/zend_errors.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,8 @@
2020
#ifndef ZEND_ERRORS_H
2121
#define ZEND_ERRORS_H
2222

23-
#define E_ERROR (1<<0L)
24-
#define E_WARNING (1<<1L)
25-
#define E_PARSE (1<<2L)
23+
#include "zend_constants_consts.h"
24+
2625
#define E_NOTICE (1<<3L)
2726
#define E_CORE_ERROR (1<<4L)
2827
#define E_CORE_WARNING (1<<5L)

Zend/zend_exceptions.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -753,11 +753,6 @@ void zend_register_default_exception(void) /* {{{ */
753753
zend_ce_error_exception = register_class_ErrorException(zend_ce_exception);
754754
zend_ce_error_exception->create_object = zend_error_exception_new;
755755

756-
/* Declared manually because it uses constant E_ERROR. */
757-
zval severity_default_value;
758-
ZVAL_LONG(&severity_default_value, E_ERROR);
759-
zend_declare_typed_property(zend_ce_error_exception, ZSTR_KNOWN(ZEND_STR_SEVERITY), &severity_default_value, ZEND_ACC_PROTECTED, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
760-
761756
zend_ce_error = register_class_Error(zend_ce_throwable);
762757
zend_ce_error->create_object = zend_default_exception_new;
763758

Zend/zend_exceptions_arginfo.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,12 @@ static zend_class_entry *register_class_ErrorException(zend_class_entry *class_e
259259
INIT_CLASS_ENTRY(ce, "ErrorException", class_ErrorException_methods);
260260
class_entry = zend_register_internal_class_ex(&ce, class_entry_Exception);
261261

262+
zval property_severity_default_value;
263+
ZVAL_LONG(&property_severity_default_value, E_ERROR);
264+
zend_string *property_severity_name = zend_string_init("severity", sizeof("severity") - 1, 1);
265+
zend_declare_typed_property(class_entry, property_severity_name, &property_severity_default_value, ZEND_ACC_PROTECTED, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG));
266+
zend_string_release(property_severity_name);
267+
262268
return class_entry;
263269
}
264270

build/gen_stub.php

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,11 @@ function processStubFile(string $stubFile, Context $context): ?FileInfo {
6666

6767
initPhpParser();
6868
$fileInfo = parseStubFile($stubCode);
69-
$allConstInfos = $fileInfo->getAllConstInfos();
69+
$constInfos = $fileInfo->getAllConstInfos();
70+
$context->allConstInfos = array_merge($context->allConstInfos, $constInfos);
7071

7172
$generatedConstCode = false;
72-
$constCode = generateConstCode($allConstInfos, $stubHash);
73+
$constCode = generateConstCode($constInfos, $stubHash);
7374
if (($context->forceRegeneration || $stubHash !== $oldStubHash) && $constCode !== "" && file_put_contents($constFile, $constCode)) {
7475
echo "Saved $constFile\n";
7576
$generatedConstCode = true;
@@ -78,7 +79,7 @@ function processStubFile(string $stubFile, Context $context): ?FileInfo {
7879
$arginfoCode = generateArgInfoCode(
7980
basename($stubFilenameWithoutExtension),
8081
$fileInfo,
81-
$allConstInfos,
82+
$context->allConstInfos,
8283
$generatedConstCode ? basename($constFile) : null,
8384
$stubHash
8485
);
@@ -99,7 +100,7 @@ function processStubFile(string $stubFile, Context $context): ?FileInfo {
99100
$arginfoCode = generateArgInfoCode(
100101
basename($stubFilenameWithoutExtension),
101102
$legacyFileInfo,
102-
$allConstInfos,
103+
$context->allConstInfos,
103104
$generatedConstCode ? basename($constFile) : null,
104105
$stubHash
105106
);
@@ -137,6 +138,8 @@ class Context {
137138
public $forceParse = false;
138139
/** @var bool */
139140
public $forceRegeneration = false;
141+
/** @var iterable<ConstInfo> */
142+
public iterable $allConstInfos = [];
140143
}
141144

142145
class ArrayType extends SimpleType {
@@ -1486,6 +1489,17 @@ function (Expr $expr) use ($allConstInfos, &$cConstName, &$originatingConst, &$i
14861489
);
14871490
}
14881491

1492+
public static function createFromExpressionRecursively(Expr $expr, ?string $cConstName, iterable $allConstInfos): EvaluatedValue
1493+
{
1494+
$result = self::createFromExpression($expr, $cConstName, $allConstInfos);
1495+
1496+
if ($result->originatingConst !== null) {
1497+
$result = self::createFromExpressionRecursively($result->originatingConst->value, $result->cConstName, $allConstInfos);
1498+
}
1499+
1500+
return $result;
1501+
}
1502+
14891503
public static function null(): EvaluatedValue
14901504
{
14911505
return new self(null, null, null, false);
@@ -1748,8 +1762,7 @@ public function getCDeclaration(iterable $allConstInfos): ?string
17481762
$code .= $value->cConstName;
17491763
} else {
17501764
if ($value->isUnknownConstValue) {
1751-
echo "Skipping C declaration generation for constant $this->name, because it has an unknown constant value\n";
1752-
return "";
1765+
throw new Exception("Cannot generate C declaration for constant $this->name, because it has an unknown constant value");
17531766
}
17541767

17551768
switch ($value->type) {
@@ -1781,7 +1794,6 @@ public function getDeclaration(iterable $allConstInfos): string
17811794
{
17821795
$value = EvaluatedValue::createFromExpression($this->value, $this->cname, $allConstInfos);
17831796
if ($value->isUnknownConstValue) {
1784-
echo "Skipping code generation for constant $this->name, because it has an unknown constant default value\n";
17851797
return "";
17861798
}
17871799

@@ -1810,24 +1822,29 @@ private function getConstDeclaration(string $code, EvaluatedValue $value): strin
18101822
$constName = str_replace('\\', '\\\\', $this->name->__toString());
18111823
$constValue = $value->value;
18121824

1825+
$flags = "CONST_CS | CONST_PERSISTENT";
1826+
if ($this->isDeprecated) {
1827+
$flags .= " | CONST_DEPRECATED";
1828+
}
1829+
18131830
switch ($value->type) {
18141831
case "NULL":
1815-
$code .= " REGISTER_NULL_CONSTANT(\"$constName\", CONST_CS | CONST_PERSISTENT);\n";
1832+
$code .= " REGISTER_NULL_CONSTANT(\"$constName\", $flags);\n";
18161833
break;
18171834
case "boolean":
1818-
$code .= " REGISTER_BOOL_CONSTANT(\"$constName\", " . ($cConstName ?: ($constValue ? "true" : "false")) . ", CONST_CS | CONST_PERSISTENT);\n";
1835+
$code .= " REGISTER_BOOL_CONSTANT(\"$constName\", " . ($cConstName ?: ($constValue ? "true" : "false")) . ", $flags);\n";
18191836
break;
18201837
case "integer":
1821-
$code .= " REGISTER_LONG_CONSTANT(\"$constName\", " . ($cConstName ?: (int) $constValue) . ", CONST_CS | CONST_PERSISTENT);\n";
1838+
$code .= " REGISTER_LONG_CONSTANT(\"$constName\", " . ($cConstName ?: (int) $constValue) . ", $flags);\n";
18221839
break;
18231840
case "double":
1824-
$code .= " REGISTER_DOUBLE_CONSTANT(\"$constName\", " . ($cConstName ?: (int) $constValue) . ", CONST_CS | CONST_PERSISTENT);\n";
1841+
$code .= " REGISTER_DOUBLE_CONSTANT(\"$constName\", " . ($cConstName ?: (int) $constValue) . ", $flags);\n";
18251842
break;
18261843
case "string":
1827-
$code .= " REGISTER_STRING_CONSTANT(\"$constName\", " . ($cConstName ?: '"' . addslashes($constValue) . '"') . ", CONST_CS | CONST_PERSISTENT);\n";
1844+
$code .= " REGISTER_STRING_CONSTANT(\"$constName\", " . ($cConstName ?: '"' . addslashes($constValue) . '"') . ", $flags);\n";
18281845
break;
18291846
default:
1830-
throw new Exception("Not implemented constant type");
1847+
throw new Exception("Unimplemented constant type");
18311848
}
18321849

18331850
return $code;
@@ -1959,13 +1976,16 @@ public function getDeclaration(iterable $allConstInfos): string {
19591976

19601977
$propertyName = $this->name->property;
19611978

1979+
$isUnknownConstValue = false;
19621980
if ($this->defaultValue === null) {
19631981
$defaultValue = EvaluatedValue::null();
19641982
} else {
19651983
$defaultValue = EvaluatedValue::createFromExpression($this->defaultValue, null, $allConstInfos);
1984+
$recursiveDefaultValue = EvaluatedValue::createFromExpressionRecursively($this->defaultValue, null, $allConstInfos);
1985+
$isUnknownConstValue = $recursiveDefaultValue->isUnknownConstValue;
19661986
}
19671987

1968-
if ($defaultValue->isUnknownConstValue) {
1988+
if ($isUnknownConstValue) {
19691989
echo "Skipping code generation for property $this->name, because it has an unknown constant default value\n";
19701990
return "";
19711991
}
@@ -4082,8 +4102,6 @@ function initPhpParser() {
40824102
$funcMap = [];
40834103
/** @var array<string, FuncInfo> $aliasMap */
40844104
$aliasMap = [];
4085-
/** @var iterable<ConstInfo> $constInfo */
4086-
$constInfos = [];
40874105

40884106
foreach ($fileInfos as $fileInfo) {
40894107
foreach ($fileInfo->getAllFuncInfos() as $funcInfo) {
@@ -4099,8 +4117,6 @@ function initPhpParser() {
40994117
foreach ($fileInfo->classInfos as $classInfo) {
41004118
$classMap[$classInfo->name->__toString()] = $classInfo;
41014119
}
4102-
4103-
$constInfos = array_merge($constInfos, $fileInfo->getAllConstInfos());
41044120
}
41054121

41064122
if ($verify) {
@@ -4191,7 +4207,7 @@ function(?ArgInfo $aliasArg, ?ArgInfo $aliasedArg) use ($aliasFunc, $aliasedFunc
41914207
if ($generateClassSynopses) {
41924208
$classSynopsesDirectory = getcwd() . "/classsynopses";
41934209

4194-
$classSynopses = generateClassSynopses($classMap, $constInfos);
4210+
$classSynopses = generateClassSynopses($classMap, $context->allConstInfos);
41954211
if (!empty($classSynopses)) {
41964212
if (!file_exists($classSynopsesDirectory)) {
41974213
mkdir($classSynopsesDirectory);
@@ -4206,7 +4222,7 @@ function(?ArgInfo $aliasArg, ?ArgInfo $aliasedArg) use ($aliasFunc, $aliasedFunc
42064222
}
42074223

42084224
if ($replaceClassSynopses) {
4209-
$classSynopses = replaceClassSynopses($targetSynopses, $classMap, $constInfos);
4225+
$classSynopses = replaceClassSynopses($targetSynopses, $classMap, $context->allConstInfos);
42104226

42114227
foreach ($classSynopses as $filename => $content) {
42124228
if (file_put_contents($filename, $content)) {

0 commit comments

Comments
 (0)