dmitry                                   Fri, 20 Jan 2012 12:30:57 +0000

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

Log:
Fixed Bug #60809 (TRAITS - PHPDoc Comment Style Bug)
Fixed some other traits related bugs (uninitialized variable, return => 
continue)
Removed some trait related redundant code and variables

Bug: https://bugs.php.net/60809 (Critical) TRAITS - PHPDoc Comment Style Bug
      
Changed paths:
    U   php/php-src/branches/PHP_5_4/NEWS
    A   php/php-src/branches/PHP_5_4/Zend/tests/traits/bug60809.phpt
    U   php/php-src/branches/PHP_5_4/Zend/zend_compile.c
    A   php/php-src/trunk/Zend/tests/traits/bug60809.phpt
    U   php/php-src/trunk/Zend/zend_compile.c

Modified: php/php-src/branches/PHP_5_4/NEWS
===================================================================
--- php/php-src/branches/PHP_5_4/NEWS	2012-01-20 12:28:37 UTC (rev 322494)
+++ php/php-src/branches/PHP_5_4/NEWS	2012-01-20 12:30:57 UTC (rev 322495)
@@ -7,6 +7,7 @@
 - Core:
   . Restoring $_SERVER['REQUEST_TIME'] as a long and introducing
     $_SERVER['REQUEST_TIME_FLOAT'] to include microsecond precision. (Patrick)
+  . Fixed bug #60809 (TRAITS - PHPDoc Comment Style Bug). (Dmitry)
   . Fixed bug #60768 (Output buffer not discarded) (Mike)

 - Hash

Added: php/php-src/branches/PHP_5_4/Zend/tests/traits/bug60809.phpt
===================================================================
--- php/php-src/branches/PHP_5_4/Zend/tests/traits/bug60809.phpt	                        (rev 0)
+++ php/php-src/branches/PHP_5_4/Zend/tests/traits/bug60809.phpt	2012-01-20 12:30:57 UTC (rev 322495)
@@ -0,0 +1,36 @@
+--TEST--
+Bug #60809 (TRAITS - PHPDoc Comment Style Bug)
+--FILE--
+<?php
+class ExampleParent {
+	private $hello_world = "hello foo\n";
+	public function foo() {
+	       echo $this->hello_world;
+	}
+}
+
+class Example extends ExampleParent {
+	use ExampleTrait;
+}
+
+trait ExampleTrait {
+	/**
+	 *
+	 */
+	private $hello_world = "hello bar\n";
+	/**
+	 *
+	 */
+	public $prop = "ops";
+	public function bar() {
+		echo $this->hello_world;
+	}
+}
+
+$x = new Example();
+$x->foo();
+$x->bar();
+?>
+--EXPECT--
+hello foo
+hello bar

Modified: php/php-src/branches/PHP_5_4/Zend/zend_compile.c
===================================================================
--- php/php-src/branches/PHP_5_4/Zend/zend_compile.c	2012-01-20 12:28:37 UTC (rev 322494)
+++ php/php-src/branches/PHP_5_4/Zend/zend_compile.c	2012-01-20 12:30:57 UTC (rev 322495)
@@ -3714,19 +3714,15 @@
 static int zend_traits_merge_functions_to_class(zend_function *fn TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
 {
 	zend_class_entry *ce = va_arg(args, zend_class_entry*);
-	int add = 0;
 	zend_function* existing_fn = NULL;
 	zend_function fn_copy, *fn_copy_p;
 	zend_function* prototype = NULL;  /* is used to determine the prototype according to the inheritance chain */

-	if (zend_hash_quick_find(&ce->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void**) &existing_fn) == FAILURE) {
-		add = 1; /* not found */
-	} else if (existing_fn->common.scope != ce) {
-		add = 1; /* or inherited from other class or interface */
-	}
-
-	if (add) {
+	if (zend_hash_quick_find(&ce->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void**) &existing_fn) == FAILURE ||
+	    existing_fn->common.scope != ce) {
+		/* not found or inherited from other class or interface */
 		zend_function* parent_function;
+
 		if (ce->parent && zend_hash_quick_find(&ce->parent->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void**) &parent_function) != FAILURE) {
 			prototype = parent_function; /* ->common.fn_flags |= ZEND_ACC_ABSTRACT; */

@@ -3800,7 +3796,6 @@
 static int zend_traits_copy_functions(zend_function *fn TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
 {
 	HashTable* target;
-	zend_class_entry *target_ce;
 	zend_trait_alias** aliases;
 	HashTable* exclude_table;
 	char* lcname;
@@ -3810,7 +3805,6 @@
 	size_t i = 0;

 	target        = va_arg(args, HashTable*);
-	target_ce     = va_arg(args, zend_class_entry*);
 	aliases       = va_arg(args, zend_trait_alias**);
 	exclude_table = va_arg(args, HashTable*);

@@ -3901,9 +3895,9 @@
 /* }}} */

 /* Copies function table entries to target function table with applied aliasing */
-static void zend_traits_copy_trait_function_table(HashTable *target, zend_class_entry *target_ce, HashTable *source, zend_trait_alias** aliases, HashTable* exclude_table TSRMLS_DC) /* {{{ */
+static void zend_traits_copy_trait_function_table(HashTable *target, HashTable *source, zend_trait_alias** aliases, HashTable* exclude_table TSRMLS_DC) /* {{{ */
 {
-	zend_hash_apply_with_arguments(source TSRMLS_CC, (apply_func_args_t)zend_traits_copy_functions, 4, target, target_ce, aliases, exclude_table);
+	zend_hash_apply_with_arguments(source TSRMLS_CC, (apply_func_args_t)zend_traits_copy_functions, 3, target, aliases, exclude_table);
 }
 /* }}} */

@@ -4035,10 +4029,10 @@
 			zend_traits_compile_exclude_table(&exclude_table, ce->trait_precedences, ce->traits[i]);

 			/* copies functions, applies defined aliasing, and excludes unused trait methods */
-			zend_traits_copy_trait_function_table(function_tables[i], ce, &ce->traits[i]->function_table, ce->trait_aliases, &exclude_table TSRMLS_CC);
-			zend_hash_graceful_destroy(&exclude_table);
+			zend_traits_copy_trait_function_table(function_tables[i], &ce->traits[i]->function_table, ce->trait_aliases, &exclude_table TSRMLS_CC);
+			zend_hash_destroy(&exclude_table);
 		} else {
-			zend_traits_copy_trait_function_table(function_tables[i], ce, &ce->traits[i]->function_table, ce->trait_aliases, NULL TSRMLS_CC);
+			zend_traits_copy_trait_function_table(function_tables[i], &ce->traits[i]->function_table, ce->trait_aliases, NULL TSRMLS_CC);
 		}
 	}

@@ -4123,6 +4117,10 @@

 	property_info.ce = ce;

+	if (property_info.doc_comment) {
+		property_info.doc_comment = estrndup(property_info.doc_comment, property_info.doc_comment_len);
+	}
+
 	zend_hash_quick_update(&ce->properties_info, name, name_len+1, h, &property_info, sizeof(zend_property_info), NULL);
 }
 /* }}} */
@@ -4137,12 +4135,10 @@
 	int   prop_name_length;
 	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;
+	char* doc_comment;

-
 	/* In the following steps the properties are inserted into the property table
 	 * for that, a very strict approach is applied:
 	 * - check for compatibility, if not compatible with any property in class -> fatal
@@ -4159,72 +4155,66 @@
 				prop_hash = property_info->h;
 				prop_name = property_info->name;
 				prop_name_length = property_info->name_length;
-				prop_found = zend_hash_quick_find(&ce->properties_info,
-												  property_info->name, property_info->name_length+1,
-												  property_info->h, (void **) &coliding_prop) == SUCCESS;
 			} else {
 				/* for private and protected we need to unmangle the names */
 				zend_unmangle_property_name(property_info->name, property_info->name_length,
 											&class_name_unused, &prop_name);
 				prop_name_length = strlen(prop_name);
 				prop_hash = zend_get_hash_value(prop_name, prop_name_length + 1);
-				prop_found = zend_hash_quick_find(&ce->properties_info, prop_name, prop_name_length+1, prop_hash, (void **) &coliding_prop) == SUCCESS;
 			}

 			/* next: check for conflicts with current class */
-			if (prop_found) {
+			if (zend_hash_quick_find(&ce->properties_info, prop_name, prop_name_length+1, prop_hash, (void **) &coliding_prop) == SUCCESS) {
 				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 (!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 (coliding_prop->flags & ZEND_ACC_PRIVATE) {
+						/* private property, make the property_info.offset indenpended */
 						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);
+							prop_value = ce->traits[i]->default_static_members_table[property_info->offset];
 						} 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);
+							prop_value = ce->traits[i]->default_properties_table[property_info->offset];
 						}
-					} else {
-						/* the flags are not identical, thus, we assume properties are not compatible */
-						not_compatible = 1;
-					}
+						Z_ADDREF_P(prop_value);

-					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);
+						zend_traits_register_private_property(ce, prop_name, prop_name_length, property_info, prop_value TSRMLS_CC);
+						continue;
 					}
-				} else {
-					/* private property, make the property_info.offset indenpended */
+				}
+
+				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) {
-						prop_value = ce->traits[i]->default_static_members_table[property_info->offset];
+						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 {
-						prop_value = ce->traits[i]->default_properties_table[property_info->offset];
+						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);
 					}
-					Z_ADDREF_P(prop_value);
+				} else {
+					/* the flags are not identical, thus, we assume properties are not compatible */
+					not_compatible = 1;
+				}

-					zend_traits_register_private_property(ce, prop_name, prop_name_length, property_info, prop_value TSRMLS_CC);
-					return;
+				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);
 				}
 			}

@@ -4236,9 +4226,10 @@
 			}
 			Z_ADDREF_P(prop_value);

+			doc_comment = property_info->doc_comment ? estrndup(property_info->doc_comment, property_info->doc_comment_len) : NULL;
 			zend_declare_property_ex(ce, prop_name, prop_name_length,
 									 prop_value, property_info->flags,
-								     property_info->doc_comment, property_info->doc_comment_len TSRMLS_CC);
+								     doc_comment, property_info->doc_comment_len TSRMLS_CC);
 		}
 	}
 }

Added: php/php-src/trunk/Zend/tests/traits/bug60809.phpt
===================================================================
--- php/php-src/trunk/Zend/tests/traits/bug60809.phpt	                        (rev 0)
+++ php/php-src/trunk/Zend/tests/traits/bug60809.phpt	2012-01-20 12:30:57 UTC (rev 322495)
@@ -0,0 +1,36 @@
+--TEST--
+Bug #60809 (TRAITS - PHPDoc Comment Style Bug)
+--FILE--
+<?php
+class ExampleParent {
+	private $hello_world = "hello foo\n";
+	public function foo() {
+	       echo $this->hello_world;
+	}
+}
+
+class Example extends ExampleParent {
+	use ExampleTrait;
+}
+
+trait ExampleTrait {
+	/**
+	 *
+	 */
+	private $hello_world = "hello bar\n";
+	/**
+	 *
+	 */
+	public $prop = "ops";
+	public function bar() {
+		echo $this->hello_world;
+	}
+}
+
+$x = new Example();
+$x->foo();
+$x->bar();
+?>
+--EXPECT--
+hello foo
+hello bar

Modified: php/php-src/trunk/Zend/zend_compile.c
===================================================================
--- php/php-src/trunk/Zend/zend_compile.c	2012-01-20 12:28:37 UTC (rev 322494)
+++ php/php-src/trunk/Zend/zend_compile.c	2012-01-20 12:30:57 UTC (rev 322495)
@@ -3753,19 +3753,15 @@
 static int zend_traits_merge_functions_to_class(zend_function *fn TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
 {
 	zend_class_entry *ce = va_arg(args, zend_class_entry*);
-	int add = 0;
 	zend_function* existing_fn = NULL;
 	zend_function fn_copy, *fn_copy_p;
 	zend_function* prototype = NULL;  /* is used to determine the prototype according to the inheritance chain */

-	if (zend_hash_quick_find(&ce->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void**) &existing_fn) == FAILURE) {
-		add = 1; /* not found */
-	} else if (existing_fn->common.scope != ce) {
-		add = 1; /* or inherited from other class or interface */
-	}
-
-	if (add) {
+	if (zend_hash_quick_find(&ce->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void**) &existing_fn) == FAILURE ||
+	    existing_fn->common.scope != ce) {
+		/* not found or inherited from other class or interface */
 		zend_function* parent_function;
+
 		if (ce->parent && zend_hash_quick_find(&ce->parent->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void**) &parent_function) != FAILURE) {
 			prototype = parent_function; /* ->common.fn_flags |= ZEND_ACC_ABSTRACT; */

@@ -3839,7 +3835,6 @@
 static int zend_traits_copy_functions(zend_function *fn TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
 {
 	HashTable* target;
-	zend_class_entry *target_ce;
 	zend_trait_alias** aliases;
 	HashTable* exclude_table;
 	char* lcname;
@@ -3849,7 +3844,6 @@
 	size_t i = 0;

 	target        = va_arg(args, HashTable*);
-	target_ce     = va_arg(args, zend_class_entry*);
 	aliases       = va_arg(args, zend_trait_alias**);
 	exclude_table = va_arg(args, HashTable*);

@@ -3940,9 +3934,9 @@
 /* }}} */

 /* Copies function table entries to target function table with applied aliasing */
-static void zend_traits_copy_trait_function_table(HashTable *target, zend_class_entry *target_ce, HashTable *source, zend_trait_alias** aliases, HashTable* exclude_table TSRMLS_DC) /* {{{ */
+static void zend_traits_copy_trait_function_table(HashTable *target, HashTable *source, zend_trait_alias** aliases, HashTable* exclude_table TSRMLS_DC) /* {{{ */
 {
-	zend_hash_apply_with_arguments(source TSRMLS_CC, (apply_func_args_t)zend_traits_copy_functions, 4, target, target_ce, aliases, exclude_table);
+	zend_hash_apply_with_arguments(source TSRMLS_CC, (apply_func_args_t)zend_traits_copy_functions, 3, target, aliases, exclude_table);
 }
 /* }}} */

@@ -4074,10 +4068,10 @@
 			zend_traits_compile_exclude_table(&exclude_table, ce->trait_precedences, ce->traits[i]);

 			/* copies functions, applies defined aliasing, and excludes unused trait methods */
-			zend_traits_copy_trait_function_table(function_tables[i], ce, &ce->traits[i]->function_table, ce->trait_aliases, &exclude_table TSRMLS_CC);
-			zend_hash_graceful_destroy(&exclude_table);
+			zend_traits_copy_trait_function_table(function_tables[i], &ce->traits[i]->function_table, ce->trait_aliases, &exclude_table TSRMLS_CC);
+			zend_hash_destroy(&exclude_table);
 		} else {
-			zend_traits_copy_trait_function_table(function_tables[i], ce, &ce->traits[i]->function_table, ce->trait_aliases, NULL TSRMLS_CC);
+			zend_traits_copy_trait_function_table(function_tables[i], &ce->traits[i]->function_table, ce->trait_aliases, NULL TSRMLS_CC);
 		}
 	}

@@ -4162,6 +4156,10 @@

 	property_info.ce = ce;

+	if (property_info.doc_comment) {
+		property_info.doc_comment = estrndup(property_info.doc_comment, property_info.doc_comment_len);
+	}
+
 	zend_hash_quick_update(&ce->properties_info, name, name_len+1, h, &property_info, sizeof(zend_property_info), NULL);
 }
 /* }}} */
@@ -4176,12 +4174,10 @@
 	int   prop_name_length;
 	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;
+	char* doc_comment;

-
 	/* In the following steps the properties are inserted into the property table
 	 * for that, a very strict approach is applied:
 	 * - check for compatibility, if not compatible with any property in class -> fatal
@@ -4198,72 +4194,66 @@
 				prop_hash = property_info->h;
 				prop_name = property_info->name;
 				prop_name_length = property_info->name_length;
-				prop_found = zend_hash_quick_find(&ce->properties_info,
-												  property_info->name, property_info->name_length+1,
-												  property_info->h, (void **) &coliding_prop) == SUCCESS;
 			} else {
 				/* for private and protected we need to unmangle the names */
 				zend_unmangle_property_name(property_info->name, property_info->name_length,
 											&class_name_unused, &prop_name);
 				prop_name_length = strlen(prop_name);
 				prop_hash = zend_get_hash_value(prop_name, prop_name_length + 1);
-				prop_found = zend_hash_quick_find(&ce->properties_info, prop_name, prop_name_length+1, prop_hash, (void **) &coliding_prop) == SUCCESS;
 			}

 			/* next: check for conflicts with current class */
-			if (prop_found) {
+			if (zend_hash_quick_find(&ce->properties_info, prop_name, prop_name_length+1, prop_hash, (void **) &coliding_prop) == SUCCESS) {
 				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 (!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 (coliding_prop->flags & ZEND_ACC_PRIVATE) {
+						/* private property, make the property_info.offset indenpended */
 						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);
+							prop_value = ce->traits[i]->default_static_members_table[property_info->offset];
 						} 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);
+							prop_value = ce->traits[i]->default_properties_table[property_info->offset];
 						}
-					} else {
-						/* the flags are not identical, thus, we assume properties are not compatible */
-						not_compatible = 1;
-					}
+						Z_ADDREF_P(prop_value);

-					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);
+						zend_traits_register_private_property(ce, prop_name, prop_name_length, property_info, prop_value TSRMLS_CC);
+						continue;
 					}
-				} else {
-					/* private property, make the property_info.offset indenpended */
+				}
+
+				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) {
-						prop_value = ce->traits[i]->default_static_members_table[property_info->offset];
+						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 {
-						prop_value = ce->traits[i]->default_properties_table[property_info->offset];
+						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);
 					}
-					Z_ADDREF_P(prop_value);
+				} else {
+					/* the flags are not identical, thus, we assume properties are not compatible */
+					not_compatible = 1;
+				}

-					zend_traits_register_private_property(ce, prop_name, prop_name_length, property_info, prop_value TSRMLS_CC);
-					return;
+				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);
 				}
 			}

@@ -4275,9 +4265,10 @@
 			}
 			Z_ADDREF_P(prop_value);

+			doc_comment = property_info->doc_comment ? estrndup(property_info->doc_comment, property_info->doc_comment_len) : NULL;
 			zend_declare_property_ex(ce, prop_name, prop_name_length,
 									 prop_value, property_info->flags,
-								     property_info->doc_comment, property_info->doc_comment_len TSRMLS_CC);
+								     doc_comment, property_info->doc_comment_len TSRMLS_CC);
 		}
 	}
 }
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to