@@ -3319,8 +3319,12 @@ public function __construct(string $class, array $args) {
3319
3319
$ this ->args = $ args ;
3320
3320
}
3321
3321
3322
- /** @param array<string, ConstInfo> $allConstInfos */
3323
- public function generateCode (string $ invocation , string $ nameSuffix , array $ allConstInfos , ?int $ phpVersionIdMinimumCompatibility ): string {
3322
+ /**
3323
+ * @param array<string, ConstInfo> $allConstInfos
3324
+ * @param array<string, string> &$declaredStrings Map of string content to
3325
+ * the name of a zend_string already created with that content
3326
+ */
3327
+ public function generateCode (string $ invocation , string $ nameSuffix , array $ allConstInfos , ?int $ phpVersionIdMinimumCompatibility , array &$ declaredStrings = []): string {
3324
3328
$ escapedAttributeName = strtr ($ this ->class , '\\' , '_ ' );
3325
3329
[$ stringInit , $ nameCode , $ stringRelease ] = StringBuilder::getString (
3326
3330
"attribute_name_ {$ escapedAttributeName }_ $ nameSuffix " ,
@@ -3344,6 +3348,9 @@ public function generateCode(string $invocation, string $nameSuffix, array $allC
3344
3348
);
3345
3349
if ($ strInit === '' ) {
3346
3350
$ initValue = "\tZVAL_STR(&attribute_ {$ escapedAttributeName }_ {$ nameSuffix }->args[ $ i].value, $ strUse); \n" ;
3351
+ } elseif (isset ($ declaredStrings [$ strVal ])) {
3352
+ $ strUse = $ declaredStrings [$ strVal ];
3353
+ $ initValue = "\tZVAL_STR_COPY(&attribute_ {$ escapedAttributeName }_ {$ nameSuffix }->args[ $ i].value, $ strUse); \n" ;
3347
3354
}
3348
3355
}
3349
3356
if ($ initValue === '' ) {
@@ -3353,6 +3360,9 @@ public function generateCode(string $invocation, string $nameSuffix, array $allC
3353
3360
true ,
3354
3361
"attribute_ {$ escapedAttributeName }_ {$ nameSuffix }_arg {$ i }_str "
3355
3362
);
3363
+ if ($ arg ->value instanceof Node \Scalar \String_) {
3364
+ $ declaredStrings [$ arg ->value ->value ] = "attribute_ {$ escapedAttributeName }_ {$ nameSuffix }_arg {$ i }_str " ;
3365
+ }
3356
3366
} else {
3357
3367
$ code .= $ initValue ;
3358
3368
}
@@ -3603,6 +3613,8 @@ function (Name $item) {
3603
3613
$ php80CondEnd = "#endif \n" ;
3604
3614
}
3605
3615
3616
+ $ declaredStrings = [];
3617
+
3606
3618
if (!empty ($ this ->attributes )) {
3607
3619
$ code .= $ php80CondStart ;
3608
3620
@@ -3611,26 +3623,27 @@ function (Name $item) {
3611
3623
"zend_add_class_attribute(class_entry " ,
3612
3624
"class_ {$ escapedName }_ $ key " ,
3613
3625
$ allConstInfos ,
3614
- $ this ->phpVersionIdMinimumCompatibility
3626
+ $ this ->phpVersionIdMinimumCompatibility ,
3627
+ $ declaredStrings
3615
3628
);
3616
3629
}
3617
3630
3618
3631
$ code .= $ php80CondEnd ;
3619
3632
}
3620
3633
3621
- if ($ attributeInitializationCode = generateConstantAttributeInitialization ($ this ->constInfos , $ allConstInfos , $ this ->phpVersionIdMinimumCompatibility , $ this ->cond )) {
3634
+ if ($ attributeInitializationCode = generateConstantAttributeInitialization ($ this ->constInfos , $ allConstInfos , $ this ->phpVersionIdMinimumCompatibility , $ this ->cond , $ declaredStrings )) {
3622
3635
$ code .= $ php80CondStart ;
3623
3636
$ code .= "\n" . $ attributeInitializationCode ;
3624
3637
$ code .= $ php80CondEnd ;
3625
3638
}
3626
3639
3627
- if ($ attributeInitializationCode = generatePropertyAttributeInitialization ($ this ->propertyInfos , $ allConstInfos , $ this ->phpVersionIdMinimumCompatibility )) {
3640
+ if ($ attributeInitializationCode = generatePropertyAttributeInitialization ($ this ->propertyInfos , $ allConstInfos , $ this ->phpVersionIdMinimumCompatibility , $ declaredStrings )) {
3628
3641
$ code .= $ php80CondStart ;
3629
3642
$ code .= "\n" . $ attributeInitializationCode ;
3630
3643
$ code .= $ php80CondEnd ;
3631
3644
}
3632
3645
3633
- if ($ attributeInitializationCode = generateFunctionAttributeInitialization ($ this ->funcInfos , $ allConstInfos , $ this ->phpVersionIdMinimumCompatibility , $ this ->cond )) {
3646
+ if ($ attributeInitializationCode = generateFunctionAttributeInitialization ($ this ->funcInfos , $ allConstInfos , $ this ->phpVersionIdMinimumCompatibility , $ this ->cond , $ declaredStrings )) {
3634
3647
$ code .= $ php80CondStart ;
3635
3648
$ code .= "\n" . $ attributeInitializationCode ;
3636
3649
$ code .= $ php80CondEnd ;
@@ -5185,8 +5198,9 @@ static function (FuncInfo $funcInfo) use ($fileInfo, &$generatedFunctionDeclarat
5185
5198
$ php80MinimumCompatibility = $ fileInfo ->getMinimumPhpVersionIdCompatibility () === null || $ fileInfo ->getMinimumPhpVersionIdCompatibility () >= PHP_80_VERSION_ID ;
5186
5199
5187
5200
if ($ fileInfo ->generateClassEntries ) {
5188
- $ attributeInitializationCode = generateFunctionAttributeInitialization ($ fileInfo ->funcInfos , $ allConstInfos , $ fileInfo ->getMinimumPhpVersionIdCompatibility (), null );
5189
- $ attributeInitializationCode .= generateGlobalConstantAttributeInitialization ($ fileInfo ->constInfos , $ allConstInfos , $ fileInfo ->getMinimumPhpVersionIdCompatibility (), null );
5201
+ $ declaredStrings = [];
5202
+ $ attributeInitializationCode = generateFunctionAttributeInitialization ($ fileInfo ->funcInfos , $ allConstInfos , $ fileInfo ->getMinimumPhpVersionIdCompatibility (), null , $ declaredStrings );
5203
+ $ attributeInitializationCode .= generateGlobalConstantAttributeInitialization ($ fileInfo ->constInfos , $ allConstInfos , $ fileInfo ->getMinimumPhpVersionIdCompatibility (), null , $ declaredStrings );
5190
5204
if ($ attributeInitializationCode ) {
5191
5205
if (!$ php80MinimumCompatibility ) {
5192
5206
$ attributeInitializationCode = "\n#if (PHP_VERSION_ID >= " . PHP_80_VERSION_ID . ") " . $ attributeInitializationCode . "#endif \n" ;
@@ -5244,12 +5258,16 @@ function generateFunctionEntries(?Name $className, array $funcInfos, ?string $co
5244
5258
return $ code ;
5245
5259
}
5246
5260
5247
- /** @param iterable<FuncInfo> $funcInfos */
5248
- function generateFunctionAttributeInitialization (iterable $ funcInfos , array $ allConstInfos , ?int $ phpVersionIdMinimumCompatibility , ?string $ parentCond = null ): string {
5261
+ /**
5262
+ * @param iterable<FuncInfo> $funcInfos
5263
+ * @param array<string, string> &$declaredStrings Map of string content to
5264
+ * the name of a zend_string already created with that content
5265
+ */
5266
+ function generateFunctionAttributeInitialization (iterable $ funcInfos , array $ allConstInfos , ?int $ phpVersionIdMinimumCompatibility , ?string $ parentCond = null , array &$ declaredStrings = []): string {
5249
5267
return generateCodeWithConditions (
5250
5268
$ funcInfos ,
5251
5269
"" ,
5252
- static function (FuncInfo $ funcInfo ) use ($ allConstInfos , $ phpVersionIdMinimumCompatibility ) {
5270
+ static function (FuncInfo $ funcInfo ) use ($ allConstInfos , $ phpVersionIdMinimumCompatibility, & $ declaredStrings ) {
5253
5271
$ code = null ;
5254
5272
5255
5273
if ($ funcInfo ->name instanceof MethodName) {
@@ -5258,12 +5276,22 @@ static function (FuncInfo $funcInfo) use ($allConstInfos, $phpVersionIdMinimumCo
5258
5276
$ functionTable = "CG(function_table) " ;
5259
5277
}
5260
5278
5279
+ // Make sure we don't try and use strings that might only be
5280
+ // conditionally available; string reuse is only among declarations
5281
+ // that are always there
5282
+ if ($ funcInfo ->cond ) {
5283
+ $ useDeclared = [];
5284
+ } else {
5285
+ $ useDeclared = &$ declaredStrings ;
5286
+ }
5287
+
5261
5288
foreach ($ funcInfo ->attributes as $ key => $ attribute ) {
5262
5289
$ code .= $ attribute ->generateCode (
5263
5290
"zend_add_function_attribute(zend_hash_str_find_ptr( $ functionTable, \"" . $ funcInfo ->name ->getNameForAttributes () . "\", sizeof( \"" . $ funcInfo ->name ->getNameForAttributes () . "\") - 1) " ,
5264
5291
"func_ " . $ funcInfo ->name ->getNameForAttributes () . "_ $ key " ,
5265
5292
$ allConstInfos ,
5266
- $ phpVersionIdMinimumCompatibility
5293
+ $ phpVersionIdMinimumCompatibility ,
5294
+ $ useDeclared
5267
5295
);
5268
5296
}
5269
5297
@@ -5273,7 +5301,8 @@ static function (FuncInfo $funcInfo) use ($allConstInfos, $phpVersionIdMinimumCo
5273
5301
"zend_add_parameter_attribute(zend_hash_str_find_ptr( $ functionTable, \"" . $ funcInfo ->name ->getNameForAttributes () . "\", sizeof( \"" . $ funcInfo ->name ->getNameForAttributes () . "\") - 1), $ index " ,
5274
5302
"func_ {$ funcInfo ->name ->getNameForAttributes ()}_arg {$ index }_ $ key " ,
5275
5303
$ allConstInfos ,
5276
- $ phpVersionIdMinimumCompatibility
5304
+ $ phpVersionIdMinimumCompatibility ,
5305
+ $ useDeclared
5277
5306
);
5278
5307
}
5279
5308
}
@@ -5287,12 +5316,15 @@ static function (FuncInfo $funcInfo) use ($allConstInfos, $phpVersionIdMinimumCo
5287
5316
/**
5288
5317
* @param iterable<ConstInfo> $constInfos
5289
5318
* @param array<string, ConstInfo> $allConstInfos
5319
+ * @param array<string, string> &$declaredStrings Map of string content to
5320
+ * the name of a zend_string already created with that content
5290
5321
*/
5291
5322
function generateGlobalConstantAttributeInitialization (
5292
5323
iterable $ constInfos ,
5293
5324
array $ allConstInfos ,
5294
5325
?int $ phpVersionIdMinimumCompatibility ,
5295
- ?string $ parentCond = null
5326
+ ?string $ parentCond = null ,
5327
+ array &$ declaredStrings = []
5296
5328
): string {
5297
5329
$ isConditional = false ;
5298
5330
if ($ phpVersionIdMinimumCompatibility !== null && $ phpVersionIdMinimumCompatibility < PHP_85_VERSION_ID ) {
@@ -5301,12 +5333,20 @@ function generateGlobalConstantAttributeInitialization(
5301
5333
$ code = generateCodeWithConditions (
5302
5334
$ constInfos ,
5303
5335
"" ,
5304
- static function (ConstInfo $ constInfo ) use ($ allConstInfos , $ isConditional ) {
5336
+ static function (ConstInfo $ constInfo ) use ($ allConstInfos , $ isConditional, & $ declaredStrings ) {
5305
5337
$ code = "" ;
5306
5338
5307
5339
if ($ constInfo ->attributes === []) {
5308
5340
return null ;
5309
5341
}
5342
+ // Make sure we don't try and use strings that might only be
5343
+ // conditionally available; string reuse is only among declarations
5344
+ // that are always there
5345
+ if ($ constInfo ->cond ) {
5346
+ $ useDeclared = [];
5347
+ } else {
5348
+ $ useDeclared = &$ declaredStrings ;
5349
+ }
5310
5350
$ constName = str_replace ('\\' , '\\\\' , $ constInfo ->name ->__toString ());
5311
5351
$ constVarName = 'const_ ' . $ constName ;
5312
5352
@@ -5321,7 +5361,8 @@ static function (ConstInfo $constInfo) use ($allConstInfos, $isConditional) {
5321
5361
"zend_add_global_constant_attribute( $ constVarName " ,
5322
5362
$ constVarName . "_ $ key " ,
5323
5363
$ allConstInfos ,
5324
- PHP_85_VERSION_ID
5364
+ PHP_85_VERSION_ID ,
5365
+ $ useDeclared
5325
5366
);
5326
5367
}
5327
5368
@@ -5338,25 +5379,37 @@ static function (ConstInfo $constInfo) use ($allConstInfos, $isConditional) {
5338
5379
/**
5339
5380
* @param iterable<ConstInfo> $constInfos
5340
5381
* @param array<string, ConstInfo> $allConstInfos
5382
+ * @param array<string, string> &$declaredStrings Map of string content to
5383
+ * the name of a zend_string already created with that content
5341
5384
*/
5342
5385
function generateConstantAttributeInitialization (
5343
5386
iterable $ constInfos ,
5344
5387
array $ allConstInfos ,
5345
5388
?int $ phpVersionIdMinimumCompatibility ,
5346
- ?string $ parentCond = null
5389
+ ?string $ parentCond = null ,
5390
+ array &$ declaredStrings = []
5347
5391
): string {
5348
5392
return generateCodeWithConditions (
5349
5393
$ constInfos ,
5350
5394
"" ,
5351
- static function (ConstInfo $ constInfo ) use ($ allConstInfos , $ phpVersionIdMinimumCompatibility ) {
5395
+ static function (ConstInfo $ constInfo ) use ($ allConstInfos , $ phpVersionIdMinimumCompatibility, & $ declaredStrings ) {
5352
5396
$ code = null ;
5353
5397
5398
+ // Make sure we don't try and use strings that might only be
5399
+ // conditionally available; string reuse is only among declarations
5400
+ // that are always there
5401
+ if ($ constInfo ->cond ) {
5402
+ $ useDeclared = [];
5403
+ } else {
5404
+ $ useDeclared = &$ declaredStrings ;
5405
+ }
5354
5406
foreach ($ constInfo ->attributes as $ key => $ attribute ) {
5355
5407
$ code .= $ attribute ->generateCode (
5356
5408
"zend_add_class_constant_attribute(class_entry, const_ " . $ constInfo ->name ->getDeclarationName (),
5357
5409
"const_ " . $ constInfo ->name ->getDeclarationName () . "_ $ key " ,
5358
5410
$ allConstInfos ,
5359
- $ phpVersionIdMinimumCompatibility
5411
+ $ phpVersionIdMinimumCompatibility ,
5412
+ $ useDeclared
5360
5413
);
5361
5414
}
5362
5415
@@ -5369,11 +5422,14 @@ static function (ConstInfo $constInfo) use ($allConstInfos, $phpVersionIdMinimum
5369
5422
/**
5370
5423
* @param iterable<PropertyInfo> $propertyInfos
5371
5424
* @param array<string, ConstInfo> $allConstInfos
5425
+ * @param array<string, string> &$declaredStrings Map of string content to
5426
+ * the name of a zend_string already created with that content
5372
5427
*/
5373
5428
function generatePropertyAttributeInitialization (
5374
5429
iterable $ propertyInfos ,
5375
5430
array $ allConstInfos ,
5376
- ?int $ phpVersionIdMinimumCompatibility
5431
+ ?int $ phpVersionIdMinimumCompatibility ,
5432
+ array &$ declaredStrings
5377
5433
): string {
5378
5434
$ code = "" ;
5379
5435
foreach ($ propertyInfos as $ propertyInfo ) {
@@ -5382,7 +5438,8 @@ function generatePropertyAttributeInitialization(
5382
5438
"zend_add_property_attribute(class_entry, property_ " . $ propertyInfo ->name ->getDeclarationName (),
5383
5439
"property_ " . $ propertyInfo ->name ->getDeclarationName () . "_ " . $ key ,
5384
5440
$ allConstInfos ,
5385
- $ phpVersionIdMinimumCompatibility
5441
+ $ phpVersionIdMinimumCompatibility ,
5442
+ $ declaredStrings
5386
5443
);
5387
5444
}
5388
5445
}
0 commit comments