Skip to content

Commit 0a36ebe

Browse files
committed
Promote count() warning to TypeError
1 parent ddd99a7 commit 0a36ebe

File tree

11 files changed

+117
-1069
lines changed

11 files changed

+117
-1069
lines changed

Zend/tests/generators/errors/count_error.phpt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ $gen = gen();
99

1010
try {
1111
count($gen);
12-
} catch (Exception $e) {
13-
echo $e;
12+
} catch (\TypeError $e) {
13+
echo $e->getMessage(), PHP_EOL;
1414
}
1515

1616
?>
17-
--EXPECTF--
18-
Warning: count(): Argument #1 ($var) must be of type Countable|array, Generator given in %s on line %d
17+
--EXPECT--
18+
count(): Argument #1 ($var) must be of type Countable|array, Generator given

Zend/zend_vm_def.h

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8883,6 +8883,7 @@ ZEND_VM_COLD_CONST_HANDLER(190, ZEND_COUNT, CONST|TMPVAR|CV, UNUSED)
88838883

88848884
SAVE_OPLINE();
88858885
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
8886+
88868887
while (1) {
88878888
if (Z_TYPE_P(op1) == IS_ARRAY) {
88888889
count = zend_array_count(Z_ARRVAL_P(op1));
@@ -8911,20 +8912,15 @@ ZEND_VM_COLD_CONST_HANDLER(190, ZEND_COUNT, CONST|TMPVAR|CV, UNUSED)
89118912
break;
89128913
}
89138914

8914-
/* If There's no handler and it doesn't implement Countable then add a warning */
8915-
count = 1;
8915+
/* If There's no handler and it doesn't implement Countable then emit a TypeError */
89168916
} else if ((OP1_TYPE & (IS_VAR|IS_CV)) != 0 && Z_TYPE_P(op1) == IS_REFERENCE) {
89178917
op1 = Z_REFVAL_P(op1);
89188918
continue;
8919-
} else if (Z_TYPE_P(op1) <= IS_NULL) {
8920-
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
8921-
ZVAL_UNDEFINED_OP1();
8922-
}
8923-
count = 0;
8924-
} else {
8925-
count = 1;
8919+
} else if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
8920+
ZVAL_UNDEFINED_OP1();
89268921
}
8927-
zend_error(E_WARNING, "%s(): Argument #1 ($var) must be of type Countable|array, %s given", opline->extended_value ? "sizeof" : "count", zend_zval_type_name(op1));
8922+
count = 0;
8923+
zend_type_error("%s(): Argument #1 ($var) must be of type Countable|array, %s given", opline->extended_value ? "sizeof" : "count", zend_zval_type_name(op1));
89288924
break;
89298925
}
89308926

Zend/zend_vm_execute.h

Lines changed: 18 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10324,6 +10324,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CONST_
1032410324

1032510325
SAVE_OPLINE();
1032610326
op1 = RT_CONSTANT(opline, opline->op1);
10327+
1032710328
while (1) {
1032810329
if (Z_TYPE_P(op1) == IS_ARRAY) {
1032910330
count = zend_array_count(Z_ARRVAL_P(op1));
@@ -10352,20 +10353,15 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CONST_
1035210353
break;
1035310354
}
1035410355

10355-
/* If There's no handler and it doesn't implement Countable then add a warning */
10356-
count = 1;
10356+
/* If There's no handler and it doesn't implement Countable then emit a TypeError */
1035710357
} else if ((IS_CONST & (IS_VAR|IS_CV)) != 0 && Z_TYPE_P(op1) == IS_REFERENCE) {
1035810358
op1 = Z_REFVAL_P(op1);
1035910359
continue;
10360-
} else if (Z_TYPE_P(op1) <= IS_NULL) {
10361-
if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
10362-
ZVAL_UNDEFINED_OP1();
10363-
}
10364-
count = 0;
10365-
} else {
10366-
count = 1;
10360+
} else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
10361+
ZVAL_UNDEFINED_OP1();
1036710362
}
10368-
zend_error(E_WARNING, "%s(): Argument #1 ($var) must be of type Countable|array, %s given", opline->extended_value ? "sizeof" : "count", zend_zval_type_name(op1));
10363+
count = 0;
10364+
zend_type_error("%s(): Argument #1 ($var) must be of type Countable|array, %s given", opline->extended_value ? "sizeof" : "count", zend_zval_type_name(op1));
1036910365
break;
1037010366
}
1037110367

@@ -17567,6 +17563,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_TMPVAR_UNUSED_HANDL
1756717563

1756817564
SAVE_OPLINE();
1756917565
op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC);
17566+
1757017567
while (1) {
1757117568
if (Z_TYPE_P(op1) == IS_ARRAY) {
1757217569
count = zend_array_count(Z_ARRVAL_P(op1));
@@ -17595,20 +17592,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_TMPVAR_UNUSED_HANDL
1759517592
break;
1759617593
}
1759717594

17598-
/* If There's no handler and it doesn't implement Countable then add a warning */
17599-
count = 1;
17595+
/* If There's no handler and it doesn't implement Countable then emit a TypeError */
1760017596
} else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) != 0 && Z_TYPE_P(op1) == IS_REFERENCE) {
1760117597
op1 = Z_REFVAL_P(op1);
1760217598
continue;
17603-
} else if (Z_TYPE_P(op1) <= IS_NULL) {
17604-
if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
17605-
ZVAL_UNDEFINED_OP1();
17606-
}
17607-
count = 0;
17608-
} else {
17609-
count = 1;
17599+
} else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
17600+
ZVAL_UNDEFINED_OP1();
1761017601
}
17611-
zend_error(E_WARNING, "%s(): Argument #1 ($var) must be of type Countable|array, %s given", opline->extended_value ? "sizeof" : "count", zend_zval_type_name(op1));
17602+
count = 0;
17603+
zend_type_error("%s(): Argument #1 ($var) must be of type Countable|array, %s given", opline->extended_value ? "sizeof" : "count", zend_zval_type_name(op1));
1761217604
break;
1761317605
}
1761417606

@@ -47327,6 +47319,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CV_UNUSED_HANDLER(Z
4732747319

4732847320
SAVE_OPLINE();
4732947321
op1 = EX_VAR(opline->op1.var);
47322+
4733047323
while (1) {
4733147324
if (Z_TYPE_P(op1) == IS_ARRAY) {
4733247325
count = zend_array_count(Z_ARRVAL_P(op1));
@@ -47355,20 +47348,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CV_UNUSED_HANDLER(Z
4735547348
break;
4735647349
}
4735747350

47358-
/* If There's no handler and it doesn't implement Countable then add a warning */
47359-
count = 1;
47351+
/* If There's no handler and it doesn't implement Countable then emit a TypeError */
4736047352
} else if ((IS_CV & (IS_VAR|IS_CV)) != 0 && Z_TYPE_P(op1) == IS_REFERENCE) {
4736147353
op1 = Z_REFVAL_P(op1);
4736247354
continue;
47363-
} else if (Z_TYPE_P(op1) <= IS_NULL) {
47364-
if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
47365-
ZVAL_UNDEFINED_OP1();
47366-
}
47367-
count = 0;
47368-
} else {
47369-
count = 1;
47355+
} else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
47356+
ZVAL_UNDEFINED_OP1();
4737047357
}
47371-
zend_error(E_WARNING, "%s(): Argument #1 ($var) must be of type Countable|array, %s given", opline->extended_value ? "sizeof" : "count", zend_zval_type_name(op1));
47358+
count = 0;
47359+
zend_type_error("%s(): Argument #1 ($var) must be of type Countable|array, %s given", opline->extended_value ? "sizeof" : "count", zend_zval_type_name(op1));
4737247360
break;
4737347361
}
4737447362

ext/standard/array.c

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -740,11 +740,6 @@ PHP_FUNCTION(count)
740740
}
741741

742742
switch (Z_TYPE_P(array)) {
743-
case IS_NULL:
744-
/* Intentionally not converted to an exception */
745-
php_error_docref(NULL, E_WARNING, "%s(): Argument #1 ($var) must be of type Countable|array, %s given", get_active_function_name(), zend_zval_type_name(array));
746-
RETURN_LONG(0);
747-
break;
748743
case IS_ARRAY:
749744
if (mode != COUNT_RECURSIVE) {
750745
cnt = zend_array_count(Z_ARRVAL_P(array));
@@ -774,18 +769,11 @@ PHP_FUNCTION(count)
774769
}
775770
return;
776771
}
777-
778-
/* If There's no handler and it doesn't implement Countable then add a warning */
779-
/* Intentionally not converted to an exception */
780-
php_error_docref(NULL, E_WARNING, "%s(): Argument #1 ($var) must be of type Countable|array, %s given", get_active_function_name(), zend_zval_type_name(array));
781-
RETURN_LONG(1);
782-
break;
783772
}
773+
/* fallthrough */
784774
default:
785-
/* Intentionally not converted to an exception */
786-
php_error_docref(NULL, E_WARNING, "%s(): Argument #1 ($var) must be of type Countable|array, %s given", get_active_function_name(), zend_zval_type_name(array));
787-
RETURN_LONG(1);
788-
break;
775+
zend_argument_type_error(1, "must be of type Countable|array, %s given", zend_zval_type_name(array));
776+
RETURN_THROWS();
789777
}
790778
}
791779
/* }}} */

ext/standard/tests/array/count_invalid.phpt

Lines changed: 48 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,54 @@ Only arrays and countable objects can be counted
33
--FILE--
44
<?php
55

6-
$result = count(null);
7-
var_dump($result);
8-
9-
$result = count("string");
10-
var_dump($result);
11-
12-
$result = count(123);
13-
var_dump($result);
14-
15-
$result = count(true);
16-
var_dump($result);
17-
18-
$result = count(false);
19-
var_dump($result);
20-
21-
$result = count((object) []);
22-
var_dump($result);
6+
try {
7+
$result = count(null);
8+
var_dump($result);
9+
} catch (\TypeError $e) {
10+
echo $e->getMessage() . \PHP_EOL;
11+
}
12+
13+
try {
14+
$result = count("string");
15+
var_dump($result);
16+
} catch (\TypeError $e) {
17+
echo $e->getMessage() . \PHP_EOL;
18+
}
19+
20+
try {
21+
$result = count(123);
22+
var_dump($result);
23+
} catch (\TypeError $e) {
24+
echo $e->getMessage() . \PHP_EOL;
25+
}
26+
27+
try {
28+
$result = count(true);
29+
var_dump($result);
30+
} catch (\TypeError $e) {
31+
echo $e->getMessage() . \PHP_EOL;
32+
}
33+
34+
try {
35+
$result = count(false);
36+
var_dump($result);
37+
} catch (\TypeError $e) {
38+
echo $e->getMessage() . \PHP_EOL;
39+
}
40+
41+
try {
42+
$result = count((object) []);
43+
var_dump($result);
44+
} catch (\TypeError $e) {
45+
echo $e->getMessage() . \PHP_EOL;
46+
}
2347

2448
?>
25-
--EXPECTF--
26-
Warning: count(): Argument #1 ($var) must be of type Countable|array, null given in %s on line %d
27-
int(0)
28-
29-
Warning: count(): Argument #1 ($var) must be of type Countable|array, string given in %s on line %d
30-
int(1)
31-
32-
Warning: count(): Argument #1 ($var) must be of type Countable|array, int given in %s on line %d
33-
int(1)
34-
35-
Warning: count(): Argument #1 ($var) must be of type Countable|array, bool given in %s on line %d
36-
int(1)
37-
38-
Warning: count(): Argument #1 ($var) must be of type Countable|array, bool given in %s on line %d
39-
int(1)
49+
--EXPECT--
50+
count(): Argument #1 ($var) must be of type Countable|array, null given
51+
count(): Argument #1 ($var) must be of type Countable|array, string given
52+
count(): Argument #1 ($var) must be of type Countable|array, int given
53+
count(): Argument #1 ($var) must be of type Countable|array, bool given
54+
count(): Argument #1 ($var) must be of type Countable|array, bool given
55+
count(): Argument #1 ($var) must be of type Countable|array, stdClass given
4056

41-
Warning: count(): Argument #1 ($var) must be of type Countable|array, stdClass given in %s on line %d
42-
int(1)

ext/standard/tests/array/count_recursive.phpt

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@ Test count() function
33
--FILE--
44
<?php
55
echo "*** Testing basic functionality of count() function ***\n";
6-
print "-- Testing NULL --\n";
7-
$arr = NULL;
8-
print "COUNT_NORMAL: should be 0, is ".count($arr, COUNT_NORMAL)."\n";
9-
print "COUNT_RECURSIVE: should be 0, is ".count($arr, COUNT_RECURSIVE)."\n";
106

117
print "-- Testing arrays --\n";
128
$arr = array(1, array(3, 4, array(6, array(8))));
@@ -18,12 +14,7 @@ $arr = array("a" => 1, "b" => 2, array("c" => 3, array("d" => 5)));
1814
print "COUNT_NORMAL: should be 3, is ".count($arr, COUNT_NORMAL)."\n";
1915
print "COUNT_RECURSIVE: should be 6, is ".count($arr, COUNT_RECURSIVE)."\n";
2016

21-
print "-- Testing strings --\n";
22-
print "COUNT_NORMAL: should be 1, is ".count("string", COUNT_NORMAL)."\n";
23-
print "COUNT_RECURSIVE: should be 1, is ".count("string", COUNT_RECURSIVE)."\n";
24-
2517
print "-- Testing various types with no second argument --\n";
26-
print "COUNT_NORMAL: should be 1, is ".count("string")."\n";
2718
print "COUNT_NORMAL: should be 2, is ".count(array("a", array("b")))."\n";
2819

2920
$arr = array('a'=>array(NULL, NULL, NULL), 1=>array(NULL=>1, 1=>NULL),
@@ -56,18 +47,6 @@ foreach ($count_array as $count_value) {
5647
$i++;
5748
}
5849

59-
60-
/* Testing count() by passing constant with no second argument */
61-
print "\n-- Testing count() on constants with no second argument --\n";
62-
print "COUNT_NORMAL: should be 1, is ".count(100)."\n";
63-
print "COUNT_NORMAL: should be 1, is ".count(-23.45)."\n";
64-
65-
print "\n-- Testing count() on NULL and Unset variables --\n";
66-
print "COUNT_NORMAL: should be 0, is ".count(NULL)."\n";
67-
print "COUNT_NORMAL: should be 1, is ".count("")."\n";
68-
print "COUNT_NORMAL: should be 0, is ".@count($a)."\n";
69-
70-
7150
print "\n-- Testing count() on an empty sub-array --\n";
7251
$arr = array(1, array(3, 4, array()));
7352
print "COUNT_NORMAL: should be 2, is ".count($arr, COUNT_NORMAL)."\n";
@@ -111,30 +90,13 @@ closedir( $resource2 );
11190
?>
11291
--EXPECTF--
11392
*** Testing basic functionality of count() function ***
114-
-- Testing NULL --
115-
116-
Warning: count(): count(): Argument #1 ($var) must be of type Countable|array, null given in %s on line %d
117-
COUNT_NORMAL: should be 0, is 0
118-
119-
Warning: count(): count(): Argument #1 ($var) must be of type Countable|array, null given in %s on line %d
120-
COUNT_RECURSIVE: should be 0, is 0
12193
-- Testing arrays --
12294
COUNT_NORMAL: should be 2, is 2
12395
COUNT_RECURSIVE: should be 8, is 8
12496
-- Testing hashes --
12597
COUNT_NORMAL: should be 3, is 3
12698
COUNT_RECURSIVE: should be 6, is 6
127-
-- Testing strings --
128-
129-
Warning: count(): count(): Argument #1 ($var) must be of type Countable|array, string given in %s on line %d
130-
COUNT_NORMAL: should be 1, is 1
131-
132-
Warning: count(): count(): Argument #1 ($var) must be of type Countable|array, string given in %s on line %d
133-
COUNT_RECURSIVE: should be 1, is 1
13499
-- Testing various types with no second argument --
135-
136-
Warning: count(): Argument #1 ($var) must be of type Countable|array, string given in %s on line %d
137-
COUNT_NORMAL: should be 1, is 1
138100
COUNT_NORMAL: should be 2, is 2
139101
-- Testing really cool arrays --
140102
COUNT_NORMAL: should be 3, is 3
@@ -173,23 +135,6 @@ COUNT_RECURSIVE is 6
173135
COUNT_NORMAL is 4
174136
COUNT_RECURSIVE is 7
175137

176-
-- Testing count() on constants with no second argument --
177-
178-
Warning: count(): Argument #1 ($var) must be of type Countable|array, int given in %s on line %d
179-
COUNT_NORMAL: should be 1, is 1
180-
181-
Warning: count(): Argument #1 ($var) must be of type Countable|array, float given in %s on line %d
182-
COUNT_NORMAL: should be 1, is 1
183-
184-
-- Testing count() on NULL and Unset variables --
185-
186-
Warning: count(): Argument #1 ($var) must be of type Countable|array, null given in %s on line %d
187-
COUNT_NORMAL: should be 0, is 0
188-
189-
Warning: count(): Argument #1 ($var) must be of type Countable|array, string given in %s on line %d
190-
COUNT_NORMAL: should be 1, is 1
191-
COUNT_NORMAL: should be 0, is 0
192-
193138
-- Testing count() on an empty sub-array --
194139
COUNT_NORMAL: should be 2, is 2
195140
COUNT_RECURSIVE: should be 5, is 5

0 commit comments

Comments
 (0)