gron                                     Sat, 17 Dec 2011 14:26:39 +0000

Revision: http://svn.php.net/viewvc?view=revision&revision=321089

Log:
Fixed inconsistent and broken handling of private properties in traits.
# The handling of private properties in classes is now consistent with private 
properties in traits.
# Perviously, privates could cause strict warnings, are were not properly 
merged into the class when
# the parent class had a private property of the same name. Now, we introduce 
it without notice,
# since it is a new and independent property, just like in normal classes.
# This problem was diagnosed while working on Bug #60536.

Bug: https://bugs.php.net/60536 (Closed) Traits Segfault
      
Changed paths:
    U   php/php-src/branches/PHP_5_4/Zend/tests/bug60536_001.phpt
    U   php/php-src/branches/PHP_5_4/Zend/tests/bug60536_003.phpt
    U   php/php-src/branches/PHP_5_4/Zend/tests/bug60536_004.phpt
    U   php/php-src/branches/PHP_5_4/Zend/tests/traits/property005.phpt
    A   php/php-src/branches/PHP_5_4/Zend/tests/traits/property006.phpt
    A   php/php-src/branches/PHP_5_4/Zend/tests/traits/property007.phpt
    A   php/php-src/branches/PHP_5_4/Zend/tests/traits/property008.phpt
    A   php/php-src/branches/PHP_5_4/Zend/tests/traits/property009.phpt
    U   php/php-src/branches/PHP_5_4/Zend/zend_compile.c
    U   php/php-src/trunk/Zend/tests/bug60536_001.phpt
    U   php/php-src/trunk/Zend/tests/bug60536_003.phpt
    U   php/php-src/trunk/Zend/tests/bug60536_004.phpt
    U   php/php-src/trunk/Zend/tests/traits/property005.phpt
    A   php/php-src/trunk/Zend/tests/traits/property006.phpt
    A   php/php-src/trunk/Zend/tests/traits/property007.phpt
    A   php/php-src/trunk/Zend/tests/traits/property008.phpt
    A   php/php-src/trunk/Zend/tests/traits/property009.phpt
    U   php/php-src/trunk/Zend/zend_compile.c

Modified: php/php-src/branches/PHP_5_4/Zend/tests/bug60536_001.phpt
===================================================================
--- php/php-src/branches/PHP_5_4/Zend/tests/bug60536_001.phpt	2011-12-17 13:29:49 UTC (rev 321088)
+++ php/php-src/branches/PHP_5_4/Zend/tests/bug60536_001.phpt	2011-12-17 14:26:39 UTC (rev 321089)
@@ -22,5 +22,4 @@
 echo "DONE";
 ?>
 --EXPECTF--
-Strict Standards: X and T define the same property ($x) in the composition of Y. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %sbug60536_001.php on line %d
 DONE

Modified: php/php-src/branches/PHP_5_4/Zend/tests/bug60536_003.phpt
===================================================================
--- php/php-src/branches/PHP_5_4/Zend/tests/bug60536_003.phpt	2011-12-17 13:29:49 UTC (rev 321088)
+++ php/php-src/branches/PHP_5_4/Zend/tests/bug60536_003.phpt	2011-12-17 14:26:39 UTC (rev 321089)
@@ -1,5 +1,5 @@
 --TEST--
-Private (relevant to #60536)
+Properties should be initialized correctly (relevant to #60536)
 --FILE--
 <?php
 error_reporting(E_ALL | E_STRICT);
@@ -32,9 +32,6 @@

 ?>
 --EXPECTF--
-Strict Standards: BaseWithPropA and AHelloProperty define the same property ($hello) in the composition of SubclassA. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %sbug60536_003.php on line %d
-
-Strict Standards: BaseWithTPropB and AHelloProperty define the same property ($hello) in the composition of SubclassB. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %sbug60536_003.php on line %d
 object(SubclassA)#%d (2) {
   ["hello":"SubclassA":private]=>
   int(0)

Modified: php/php-src/branches/PHP_5_4/Zend/tests/bug60536_004.phpt
===================================================================
--- php/php-src/branches/PHP_5_4/Zend/tests/bug60536_004.phpt	2011-12-17 13:29:49 UTC (rev 321088)
+++ php/php-src/branches/PHP_5_4/Zend/tests/bug60536_004.phpt	2011-12-17 14:26:39 UTC (rev 321089)
@@ -31,8 +31,6 @@
 ?>
 --EXPECTF--
 PRE-CLASS-GUARD
-
-Strict Standards: Base and THello1 define the same property ($hello) in the composition of SameNameInSubClassNoNotice. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %sbug60536_004.php on line %d
 POST-CLASS-GUARD

 Strict Standards: Notice and THello1 define the same property ($hello) in the composition of Notice. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %sbug60536_004.php on line %d

Modified: php/php-src/branches/PHP_5_4/Zend/tests/traits/property005.phpt
===================================================================
--- php/php-src/branches/PHP_5_4/Zend/tests/traits/property005.phpt	2011-12-17 13:29:49 UTC (rev 321088)
+++ php/php-src/branches/PHP_5_4/Zend/tests/traits/property005.phpt	2011-12-17 14:26:39 UTC (rev 321089)
@@ -13,18 +13,11 @@
 }

 echo "PRE-CLASS-GUARD\n";
-class NoticeForBase extends Base {
-    use THello1;
-}
-echo "POST-CLASS-GUARD\n";
-
-// now the same with a class that defines the property itself
-
 class Notice extends Base {
     use THello1;
     private $hello;
 }
-echo "POST-CLASS-GUARD2\n";
+echo "POST-CLASS-GUARD\n";

 // now we do the test for a fatal error

@@ -33,7 +26,7 @@
     public $hello;
 }

-echo "POST-CLASS-GUARD\n";
+echo "POST-CLASS-GUARD2\n";

 $t = new TraitsTest;
 $t->hello = "foo";
@@ -41,10 +34,7 @@
 --EXPECTF--
 PRE-CLASS-GUARD

-Strict Standards: Base and THello1 define the same property ($hello) in the composition of NoticeForBase. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %s on line %d
+Strict Standards: Notice and THello1 define the same property ($hello) in the composition of Notice. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %s on line %d
 POST-CLASS-GUARD

-Strict Standards: Notice and THello1 define the same property ($hello) in the composition of Notice. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %s on line %d
-POST-CLASS-GUARD2
-
 Fatal error: TraitsTest and THello1 define the same property ($hello) in the composition of TraitsTest. However, the definition differs and is considered incompatible. Class was composed in %s on line %d

Added: php/php-src/branches/PHP_5_4/Zend/tests/traits/property006.phpt
===================================================================
--- php/php-src/branches/PHP_5_4/Zend/tests/traits/property006.phpt	                        (rev 0)
+++ php/php-src/branches/PHP_5_4/Zend/tests/traits/property006.phpt	2011-12-17 14:26:39 UTC (rev 321089)
@@ -0,0 +1,37 @@
+--TEST--
+Introducing new private variables of the same name in a subclass is ok, and does not lead to any output. That is consitent with normal inheritance handling.
+--FILE--
+<?php
+error_reporting(E_ALL | E_STRICT);
+
+class Base {
+  private $hello;
+}
+
+trait THello1 {
+  private $hello;
+}
+
+// Now we use the trait, which happens to introduce another private variable
+// but they are distinct, and not related to each other, so no warning.
+echo "PRE-CLASS-GUARD\n";
+class SameNameInSubClassNoNotice extends Base {
+    use THello1;
+}
+echo "POST-CLASS-GUARD\n";
+
+// now the same with a class that defines the property itself,
+// that should give the expected strict warning.
+
+class Notice extends Base {
+    use THello1;
+    private $hello;
+}
+echo "POST-CLASS-GUARD2\n";
+?>
+--EXPECTF--
+PRE-CLASS-GUARD
+POST-CLASS-GUARD
+
+Strict Standards: Notice and THello1 define the same property ($hello) in the composition of Notice. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %s on line %d
+POST-CLASS-GUARD2

Added: php/php-src/branches/PHP_5_4/Zend/tests/traits/property007.phpt
===================================================================
--- php/php-src/branches/PHP_5_4/Zend/tests/traits/property007.phpt	                        (rev 0)
+++ php/php-src/branches/PHP_5_4/Zend/tests/traits/property007.phpt	2011-12-17 14:26:39 UTC (rev 321089)
@@ -0,0 +1,38 @@
+--TEST--
+Introducing new private variables of the same name in a subclass is ok, and does not lead to any output. That is consitent with normal inheritance handling.
+--FILE--
+<?php
+error_reporting(E_ALL | E_STRICT);
+
+class Base {
+  protected $hello;
+}
+
+trait THello1 {
+  protected $hello;
+}
+
+// Protected and public are handle more strict with a warning then what is
+// expected from normal inheritance since they can have easier coliding semantics
+echo "PRE-CLASS-GUARD\n";
+class SameNameInSubClassProducesNotice extends Base {
+    use THello1;
+}
+echo "POST-CLASS-GUARD\n";
+
+// now the same with a class that defines the property itself, too.
+
+class Notice extends Base {
+    use THello1;
+    protected $hello;
+}
+echo "POST-CLASS-GUARD2\n";
+?>
+--EXPECTF--
+PRE-CLASS-GUARD
+
+Strict Standards: Base and THello1 define the same property ($hello) in the composition of SameNameInSubClassProducesNotice. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %s on line %d
+POST-CLASS-GUARD
+
+Strict Standards: Notice and THello1 define the same property ($hello) in the composition of Notice. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %s on line %d
+POST-CLASS-GUARD2

Added: php/php-src/branches/PHP_5_4/Zend/tests/traits/property008.phpt
===================================================================
--- php/php-src/branches/PHP_5_4/Zend/tests/traits/property008.phpt	                        (rev 0)
+++ php/php-src/branches/PHP_5_4/Zend/tests/traits/property008.phpt	2011-12-17 14:26:39 UTC (rev 321089)
@@ -0,0 +1,62 @@
+--TEST--
+Handling of private fields with traits needs to have same semantics as with normal inheritance.
+--FILE--
+<?php
+error_reporting(E_ALL | E_STRICT);
+
+class BaseWithPropA {
+  private $hello = 0;
+}
+
+// This is how privates are handled in normal inheritance
+class SubclassClassicInheritance extends BaseWithPropA {
+  private $hello = 0;
+}
+
+// And here, we need to make sure, that the traits behave the same
+
+trait AHelloProperty {
+  private $hello = 0;
+}
+
+class BaseWithTPropB {
+    use AHelloProperty;
+}
+
+class SubclassA extends BaseWithPropA {
+    use AHelloProperty;
+}
+
+class SubclassB extends BaseWithTPropB {
+    use AHelloProperty;
+}
+
+$classic = new SubclassClassicInheritance;
+var_dump($classic);
+
+$a = new SubclassA;
+var_dump($a);
+
+$b = new SubclassB;
+var_dump($b);
+
+?>
+--EXPECTF--
+object(SubclassClassicInheritance)#1 (2) {
+  ["hello":"SubclassClassicInheritance":private]=>
+  int(0)
+  ["hello":"BaseWithPropA":private]=>
+  int(0)
+}
+object(SubclassA)#2 (2) {
+  ["hello":"SubclassA":private]=>
+  int(0)
+  ["hello":"BaseWithPropA":private]=>
+  int(0)
+}
+object(SubclassB)#3 (2) {
+  ["hello":"SubclassB":private]=>
+  int(0)
+  ["hello":"BaseWithTPropB":private]=>
+  int(0)
+}
\ No newline at end of file

Added: php/php-src/branches/PHP_5_4/Zend/tests/traits/property009.phpt
===================================================================
--- php/php-src/branches/PHP_5_4/Zend/tests/traits/property009.phpt	                        (rev 0)
+++ php/php-src/branches/PHP_5_4/Zend/tests/traits/property009.phpt	2011-12-17 14:26:39 UTC (rev 321089)
@@ -0,0 +1,59 @@
+--TEST--
+Handling of public fields with traits needs to have same semantics as with normal inheritance, however, we do add strict warnings since it is easier to run into something unexpeted with changing traits.
+--FILE--
+<?php
+error_reporting(E_ALL | E_STRICT);
+
+class BaseWithPropA {
+  public $hello = 0;
+}
+
+// This is how publics are handled in normal inheritance
+class SubclassClassicInheritance extends BaseWithPropA {
+  public $hello = 0;
+}
+
+// And here, we need to make sure, that the traits behave the same
+
+trait AHelloProperty {
+  public $hello = 0;
+}
+
+class BaseWithTPropB {
+    use AHelloProperty;
+}
+
+class SubclassA extends BaseWithPropA {
+    use AHelloProperty;
+}
+
+class SubclassB extends BaseWithTPropB {
+    use AHelloProperty;
+}
+
+$classic = new SubclassClassicInheritance;
+var_dump($classic);
+
+$a = new SubclassA;
+var_dump($a);
+
+$b = new SubclassB;
+var_dump($b);
+
+?>
+--EXPECTF--
+Strict Standards: BaseWithPropA and AHelloProperty define the same property ($hello) in the composition of SubclassA. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %s on line %d
+
+Strict Standards: BaseWithTPropB and AHelloProperty define the same property ($hello) in the composition of SubclassB. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %s on line %d
+object(SubclassClassicInheritance)#1 (1) {
+  ["hello"]=>
+  int(0)
+}
+object(SubclassA)#2 (1) {
+  ["hello"]=>
+  int(0)
+}
+object(SubclassB)#3 (1) {
+  ["hello"]=>
+  int(0)
+}
\ No newline at end of file

Modified: php/php-src/branches/PHP_5_4/Zend/zend_compile.c
===================================================================
--- php/php-src/branches/PHP_5_4/Zend/zend_compile.c	2011-12-17 13:29:49 UTC (rev 321088)
+++ php/php-src/branches/PHP_5_4/Zend/zend_compile.c	2011-12-17 14:26:39 UTC (rev 321089)
@@ -4234,6 +4234,7 @@
 	ulong prop_hash;
 	const char* class_name_unused;
 	zend_bool prop_found;
+	zend_bool parent_prop_is_private = 0;
 	zend_bool not_compatible;
 	zval* prop_value;

@@ -4271,40 +4272,44 @@
 				if (coliding_prop->flags & ZEND_ACC_SHADOW) {
 					/* this one is inherited, lets look it up in its own class */
 					zend_hash_quick_find(&coliding_prop->ce->properties_info, prop_name, prop_name_length+1, prop_hash, (void **) &coliding_prop);
+					parent_prop_is_private = (coliding_prop->flags & ZEND_ACC_PRIVATE) == ZEND_ACC_PRIVATE;
 				}
-				if (   (coliding_prop->flags & (ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC))
-					== (property_info->flags & (ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC))) {
-					/* flags are identical, now the value needs to be checked */
-					if (property_info->flags & ZEND_ACC_STATIC) {
-						not_compatible = (FAILURE == compare_function(&compare_result,
-                                          ce->default_static_members_table[coliding_prop->offset],
-                                          ce->traits[i]->default_static_members_table[property_info->offset] TSRMLS_CC))
-                              || (Z_LVAL(compare_result) != 0);
+
+				if (!parent_prop_is_private) {
+					if (   (coliding_prop->flags & (ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC))
+						== (property_info->flags & (ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC))) {
+						/* flags are identical, now the value needs to be checked */
+						if (property_info->flags & ZEND_ACC_STATIC) {
+							not_compatible = (FAILURE == compare_function(&compare_result,
+											  ce->default_static_members_table[coliding_prop->offset],
+											  ce->traits[i]->default_static_members_table[property_info->offset] TSRMLS_CC))
+								  || (Z_LVAL(compare_result) != 0);
+						} else {
+							not_compatible = (FAILURE == compare_function(&compare_result,
+											  ce->default_properties_table[coliding_prop->offset],
+											  ce->traits[i]->default_properties_table[property_info->offset] TSRMLS_CC))
+								  || (Z_LVAL(compare_result) != 0);
+						}
 					} else {
-						not_compatible = (FAILURE == compare_function(&compare_result,
-                                          ce->default_properties_table[coliding_prop->offset],
-                                          ce->traits[i]->default_properties_table[property_info->offset] TSRMLS_CC))
-                              || (Z_LVAL(compare_result) != 0);
+						/* the flags are not identical, thus, we assume properties are not compatible */
+						not_compatible = 1;
 					}
-				} else {
-					/* the flags are not identical, thus, we assume properties are not compatible */
-					not_compatible = 1;
-				}

-				if (not_compatible) {
-					zend_error(E_COMPILE_ERROR,
-							   "%s and %s define the same property ($%s) in the composition of %s. However, the definition differs and is considered incompatible. Class was composed",
-								find_first_definition(ce, i, prop_name, prop_name_length, prop_hash, coliding_prop->ce)->name,
-								property_info->ce->name,
-								prop_name,
-								ce->name);
-				} else {
-					zend_error(E_STRICT,
-							   "%s and %s define the same property ($%s) in the composition of %s. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed",
-								find_first_definition(ce, i, prop_name, prop_name_length, prop_hash, coliding_prop->ce)->name,
-								property_info->ce->name,
-								prop_name,
-								ce->name);
+					if (not_compatible) {
+						zend_error(E_COMPILE_ERROR,
+								   "%s and %s define the same property ($%s) in the composition of %s. However, the definition differs and is considered incompatible. Class was composed",
+									find_first_definition(ce, i, prop_name, prop_name_length, prop_hash, coliding_prop->ce)->name,
+									property_info->ce->name,
+									prop_name,
+									ce->name);
+					} else {
+						zend_error(E_STRICT,
+								   "%s and %s define the same property ($%s) in the composition of %s. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed",
+									find_first_definition(ce, i, prop_name, prop_name_length, prop_hash, coliding_prop->ce)->name,
+									property_info->ce->name,
+									prop_name,
+									ce->name);
+					}
 				}
 			}


Modified: php/php-src/trunk/Zend/tests/bug60536_001.phpt
===================================================================
--- php/php-src/trunk/Zend/tests/bug60536_001.phpt	2011-12-17 13:29:49 UTC (rev 321088)
+++ php/php-src/trunk/Zend/tests/bug60536_001.phpt	2011-12-17 14:26:39 UTC (rev 321089)
@@ -22,5 +22,4 @@
 echo "DONE";
 ?>
 --EXPECTF--
-Strict Standards: X and T define the same property ($x) in the composition of Y. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %sbug60536_001.php on line %d
 DONE

Modified: php/php-src/trunk/Zend/tests/bug60536_003.phpt
===================================================================
--- php/php-src/trunk/Zend/tests/bug60536_003.phpt	2011-12-17 13:29:49 UTC (rev 321088)
+++ php/php-src/trunk/Zend/tests/bug60536_003.phpt	2011-12-17 14:26:39 UTC (rev 321089)
@@ -1,5 +1,5 @@
 --TEST--
-Private (relevant to #60536)
+Properties should be initialized correctly (relevant to #60536)
 --FILE--
 <?php
 error_reporting(E_ALL | E_STRICT);
@@ -32,9 +32,6 @@

 ?>
 --EXPECTF--
-Strict Standards: BaseWithPropA and AHelloProperty define the same property ($hello) in the composition of SubclassA. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %sbug60536_003.php on line %d
-
-Strict Standards: BaseWithTPropB and AHelloProperty define the same property ($hello) in the composition of SubclassB. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %sbug60536_003.php on line %d
 object(SubclassA)#%d (2) {
   ["hello":"SubclassA":private]=>
   int(0)

Modified: php/php-src/trunk/Zend/tests/bug60536_004.phpt
===================================================================
--- php/php-src/trunk/Zend/tests/bug60536_004.phpt	2011-12-17 13:29:49 UTC (rev 321088)
+++ php/php-src/trunk/Zend/tests/bug60536_004.phpt	2011-12-17 14:26:39 UTC (rev 321089)
@@ -31,8 +31,6 @@
 ?>
 --EXPECTF--
 PRE-CLASS-GUARD
-
-Strict Standards: Base and THello1 define the same property ($hello) in the composition of SameNameInSubClassNoNotice. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %sbug60536_004.php on line %d
 POST-CLASS-GUARD

 Strict Standards: Notice and THello1 define the same property ($hello) in the composition of Notice. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %sbug60536_004.php on line %d

Modified: php/php-src/trunk/Zend/tests/traits/property005.phpt
===================================================================
--- php/php-src/trunk/Zend/tests/traits/property005.phpt	2011-12-17 13:29:49 UTC (rev 321088)
+++ php/php-src/trunk/Zend/tests/traits/property005.phpt	2011-12-17 14:26:39 UTC (rev 321089)
@@ -13,18 +13,11 @@
 }

 echo "PRE-CLASS-GUARD\n";
-class NoticeForBase extends Base {
-    use THello1;
-}
-echo "POST-CLASS-GUARD\n";
-
-// now the same with a class that defines the property itself
-
 class Notice extends Base {
     use THello1;
     private $hello;
 }
-echo "POST-CLASS-GUARD2\n";
+echo "POST-CLASS-GUARD\n";

 // now we do the test for a fatal error

@@ -33,7 +26,7 @@
     public $hello;
 }

-echo "POST-CLASS-GUARD\n";
+echo "POST-CLASS-GUARD2\n";

 $t = new TraitsTest;
 $t->hello = "foo";
@@ -41,10 +34,7 @@
 --EXPECTF--
 PRE-CLASS-GUARD

-Strict Standards: Base and THello1 define the same property ($hello) in the composition of NoticeForBase. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %s on line %d
+Strict Standards: Notice and THello1 define the same property ($hello) in the composition of Notice. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %s on line %d
 POST-CLASS-GUARD

-Strict Standards: Notice and THello1 define the same property ($hello) in the composition of Notice. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %s on line %d
-POST-CLASS-GUARD2
-
 Fatal error: TraitsTest and THello1 define the same property ($hello) in the composition of TraitsTest. However, the definition differs and is considered incompatible. Class was composed in %s on line %d

Added: php/php-src/trunk/Zend/tests/traits/property006.phpt
===================================================================
--- php/php-src/trunk/Zend/tests/traits/property006.phpt	                        (rev 0)
+++ php/php-src/trunk/Zend/tests/traits/property006.phpt	2011-12-17 14:26:39 UTC (rev 321089)
@@ -0,0 +1,37 @@
+--TEST--
+Introducing new private variables of the same name in a subclass is ok, and does not lead to any output. That is consitent with normal inheritance handling.
+--FILE--
+<?php
+error_reporting(E_ALL | E_STRICT);
+
+class Base {
+  private $hello;
+}
+
+trait THello1 {
+  private $hello;
+}
+
+// Now we use the trait, which happens to introduce another private variable
+// but they are distinct, and not related to each other, so no warning.
+echo "PRE-CLASS-GUARD\n";
+class SameNameInSubClassNoNotice extends Base {
+    use THello1;
+}
+echo "POST-CLASS-GUARD\n";
+
+// now the same with a class that defines the property itself,
+// that should give the expected strict warning.
+
+class Notice extends Base {
+    use THello1;
+    private $hello;
+}
+echo "POST-CLASS-GUARD2\n";
+?>
+--EXPECTF--
+PRE-CLASS-GUARD
+POST-CLASS-GUARD
+
+Strict Standards: Notice and THello1 define the same property ($hello) in the composition of Notice. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %s on line %d
+POST-CLASS-GUARD2

Added: php/php-src/trunk/Zend/tests/traits/property007.phpt
===================================================================
--- php/php-src/trunk/Zend/tests/traits/property007.phpt	                        (rev 0)
+++ php/php-src/trunk/Zend/tests/traits/property007.phpt	2011-12-17 14:26:39 UTC (rev 321089)
@@ -0,0 +1,38 @@
+--TEST--
+Introducing new private variables of the same name in a subclass is ok, and does not lead to any output. That is consitent with normal inheritance handling.
+--FILE--
+<?php
+error_reporting(E_ALL | E_STRICT);
+
+class Base {
+  protected $hello;
+}
+
+trait THello1 {
+  protected $hello;
+}
+
+// Protected and public are handle more strict with a warning then what is
+// expected from normal inheritance since they can have easier coliding semantics
+echo "PRE-CLASS-GUARD\n";
+class SameNameInSubClassProducesNotice extends Base {
+    use THello1;
+}
+echo "POST-CLASS-GUARD\n";
+
+// now the same with a class that defines the property itself, too.
+
+class Notice extends Base {
+    use THello1;
+    protected $hello;
+}
+echo "POST-CLASS-GUARD2\n";
+?>
+--EXPECTF--
+PRE-CLASS-GUARD
+
+Strict Standards: Base and THello1 define the same property ($hello) in the composition of SameNameInSubClassProducesNotice. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %s on line %d
+POST-CLASS-GUARD
+
+Strict Standards: Notice and THello1 define the same property ($hello) in the composition of Notice. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %s on line %d
+POST-CLASS-GUARD2

Added: php/php-src/trunk/Zend/tests/traits/property008.phpt
===================================================================
--- php/php-src/trunk/Zend/tests/traits/property008.phpt	                        (rev 0)
+++ php/php-src/trunk/Zend/tests/traits/property008.phpt	2011-12-17 14:26:39 UTC (rev 321089)
@@ -0,0 +1,62 @@
+--TEST--
+Handling of private fields with traits needs to have same semantics as with normal inheritance.
+--FILE--
+<?php
+error_reporting(E_ALL | E_STRICT);
+
+class BaseWithPropA {
+  private $hello = 0;
+}
+
+// This is how privates are handled in normal inheritance
+class SubclassClassicInheritance extends BaseWithPropA {
+  private $hello = 0;
+}
+
+// And here, we need to make sure, that the traits behave the same
+
+trait AHelloProperty {
+  private $hello = 0;
+}
+
+class BaseWithTPropB {
+    use AHelloProperty;
+}
+
+class SubclassA extends BaseWithPropA {
+    use AHelloProperty;
+}
+
+class SubclassB extends BaseWithTPropB {
+    use AHelloProperty;
+}
+
+$classic = new SubclassClassicInheritance;
+var_dump($classic);
+
+$a = new SubclassA;
+var_dump($a);
+
+$b = new SubclassB;
+var_dump($b);
+
+?>
+--EXPECTF--
+object(SubclassClassicInheritance)#1 (2) {
+  ["hello":"SubclassClassicInheritance":private]=>
+  int(0)
+  ["hello":"BaseWithPropA":private]=>
+  int(0)
+}
+object(SubclassA)#2 (2) {
+  ["hello":"SubclassA":private]=>
+  int(0)
+  ["hello":"BaseWithPropA":private]=>
+  int(0)
+}
+object(SubclassB)#3 (2) {
+  ["hello":"SubclassB":private]=>
+  int(0)
+  ["hello":"BaseWithTPropB":private]=>
+  int(0)
+}
\ No newline at end of file

Added: php/php-src/trunk/Zend/tests/traits/property009.phpt
===================================================================
--- php/php-src/trunk/Zend/tests/traits/property009.phpt	                        (rev 0)
+++ php/php-src/trunk/Zend/tests/traits/property009.phpt	2011-12-17 14:26:39 UTC (rev 321089)
@@ -0,0 +1,59 @@
+--TEST--
+Handling of public fields with traits needs to have same semantics as with normal inheritance, however, we do add strict warnings since it is easier to run into something unexpeted with changing traits.
+--FILE--
+<?php
+error_reporting(E_ALL | E_STRICT);
+
+class BaseWithPropA {
+  public $hello = 0;
+}
+
+// This is how publics are handled in normal inheritance
+class SubclassClassicInheritance extends BaseWithPropA {
+  public $hello = 0;
+}
+
+// And here, we need to make sure, that the traits behave the same
+
+trait AHelloProperty {
+  public $hello = 0;
+}
+
+class BaseWithTPropB {
+    use AHelloProperty;
+}
+
+class SubclassA extends BaseWithPropA {
+    use AHelloProperty;
+}
+
+class SubclassB extends BaseWithTPropB {
+    use AHelloProperty;
+}
+
+$classic = new SubclassClassicInheritance;
+var_dump($classic);
+
+$a = new SubclassA;
+var_dump($a);
+
+$b = new SubclassB;
+var_dump($b);
+
+?>
+--EXPECTF--
+Strict Standards: BaseWithPropA and AHelloProperty define the same property ($hello) in the composition of SubclassA. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %s on line %d
+
+Strict Standards: BaseWithTPropB and AHelloProperty define the same property ($hello) in the composition of SubclassB. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %s on line %d
+object(SubclassClassicInheritance)#1 (1) {
+  ["hello"]=>
+  int(0)
+}
+object(SubclassA)#2 (1) {
+  ["hello"]=>
+  int(0)
+}
+object(SubclassB)#3 (1) {
+  ["hello"]=>
+  int(0)
+}
\ No newline at end of file

Modified: php/php-src/trunk/Zend/zend_compile.c
===================================================================
--- php/php-src/trunk/Zend/zend_compile.c	2011-12-17 13:29:49 UTC (rev 321088)
+++ php/php-src/trunk/Zend/zend_compile.c	2011-12-17 14:26:39 UTC (rev 321089)
@@ -4234,6 +4234,7 @@
 	ulong prop_hash;
 	const char* class_name_unused;
 	zend_bool prop_found;
+	zend_bool parent_prop_is_private = 0;
 	zend_bool not_compatible;
 	zval* prop_value;

@@ -4271,40 +4272,44 @@
 				if (coliding_prop->flags & ZEND_ACC_SHADOW) {
 					/* this one is inherited, lets look it up in its own class */
 					zend_hash_quick_find(&coliding_prop->ce->properties_info, prop_name, prop_name_length+1, prop_hash, (void **) &coliding_prop);
+					parent_prop_is_private = (coliding_prop->flags & ZEND_ACC_PRIVATE) == ZEND_ACC_PRIVATE;
 				}
-				if (   (coliding_prop->flags & (ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC))
-					== (property_info->flags & (ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC))) {
-					/* flags are identical, now the value needs to be checked */
-					if (property_info->flags & ZEND_ACC_STATIC) {
-						not_compatible = (FAILURE == compare_function(&compare_result,
-                                          ce->default_static_members_table[coliding_prop->offset],
-                                          ce->traits[i]->default_static_members_table[property_info->offset] TSRMLS_CC))
-                              || (Z_LVAL(compare_result) != 0);
+
+				if (!parent_prop_is_private) {
+					if (   (coliding_prop->flags & (ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC))
+						== (property_info->flags & (ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC))) {
+						/* flags are identical, now the value needs to be checked */
+						if (property_info->flags & ZEND_ACC_STATIC) {
+							not_compatible = (FAILURE == compare_function(&compare_result,
+											  ce->default_static_members_table[coliding_prop->offset],
+											  ce->traits[i]->default_static_members_table[property_info->offset] TSRMLS_CC))
+								  || (Z_LVAL(compare_result) != 0);
+						} else {
+							not_compatible = (FAILURE == compare_function(&compare_result,
+											  ce->default_properties_table[coliding_prop->offset],
+											  ce->traits[i]->default_properties_table[property_info->offset] TSRMLS_CC))
+								  || (Z_LVAL(compare_result) != 0);
+						}
 					} else {
-						not_compatible = (FAILURE == compare_function(&compare_result,
-                                          ce->default_properties_table[coliding_prop->offset],
-                                          ce->traits[i]->default_properties_table[property_info->offset] TSRMLS_CC))
-                              || (Z_LVAL(compare_result) != 0);
+						/* the flags are not identical, thus, we assume properties are not compatible */
+						not_compatible = 1;
 					}
-				} else {
-					/* the flags are not identical, thus, we assume properties are not compatible */
-					not_compatible = 1;
-				}

-				if (not_compatible) {
-					zend_error(E_COMPILE_ERROR,
-							   "%s and %s define the same property ($%s) in the composition of %s. However, the definition differs and is considered incompatible. Class was composed",
-								find_first_definition(ce, i, prop_name, prop_name_length, prop_hash, coliding_prop->ce)->name,
-								property_info->ce->name,
-								prop_name,
-								ce->name);
-				} else {
-					zend_error(E_STRICT,
-							   "%s and %s define the same property ($%s) in the composition of %s. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed",
-								find_first_definition(ce, i, prop_name, prop_name_length, prop_hash, coliding_prop->ce)->name,
-								property_info->ce->name,
-								prop_name,
-								ce->name);
+					if (not_compatible) {
+						zend_error(E_COMPILE_ERROR,
+								   "%s and %s define the same property ($%s) in the composition of %s. However, the definition differs and is considered incompatible. Class was composed",
+									find_first_definition(ce, i, prop_name, prop_name_length, prop_hash, coliding_prop->ce)->name,
+									property_info->ce->name,
+									prop_name,
+									ce->name);
+					} else {
+						zend_error(E_STRICT,
+								   "%s and %s define the same property ($%s) in the composition of %s. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed",
+									find_first_definition(ce, i, prop_name, prop_name_length, prop_hash, coliding_prop->ce)->name,
+									property_info->ce->name,
+									prop_name,
+									ce->name);
+					}
 				}
 			}

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to