From 64b284d281b1bec15cb52e902620f783aa659c2a Mon Sep 17 00:00:00 2001 From: Drew Paroski Date: Thu, 25 Jul 2013 01:56:20 -0700 Subject: [PATCH] Fix silly bug when computing AttrDeepInit for a property This diff fixes a crashing bug that can happen when multiple properties are declared in a single statement and some of the properties are initialized using collection literals, for example: public $x = Set {}, $y = 1; --- hphp/compiler/analysis/emitter.cpp | 16 +++++++++++----- .../collection_classes/prop_init_literal_bug.php | 6 ++++++ .../prop_init_literal_bug.php.expect | 1 + 3 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 hphp/test/slow/collection_classes/prop_init_literal_bug.php create mode 100644 hphp/test/slow/collection_classes/prop_init_literal_bug.php.expect diff --git a/hphp/compiler/analysis/emitter.cpp b/hphp/compiler/analysis/emitter.cpp index 6fd7e9808..e91c47d79 100755 --- a/hphp/compiler/analysis/emitter.cpp +++ b/hphp/compiler/analysis/emitter.cpp @@ -6344,7 +6344,7 @@ PreClass::Hoistable EmitterVisitor::emitClass(Emitter& e, ClassScopePtr cNode, dynamic_pointer_cast((*stmts)[i])) { ModifierExpressionPtr mod(cv->getModifiers()); ExpressionListPtr el(cv->getVarList()); - Attr attrs = buildAttrs(mod); + Attr declAttrs = buildAttrs(mod); StringData* typeConstraint = StringData::GetStaticString( cv->getTypeConstraint()); int nVars = el->getCount(); @@ -6371,14 +6371,20 @@ PreClass::Hoistable EmitterVisitor::emitClass(Emitter& e, ClassScopePtr cNode, StringData* propName = StringData::GetStaticString(var->getName()); StringData* propDoc = empty_string.get(); TypedValue tvVal; + // Some properties may need to be marked with the AttrDeepInit + // attribute, while other properties should not be marked with + // this attrbiute. We copy declAttrs into propAttrs for each loop + // iteration so that we can safely add AttrDeepInit to propAttrs + // without mutating the original declAttrs. + Attr propAttrs = declAttrs; if (vNode) { if (vNode->isScalar()) { initScalar(tvVal, vNode); } else { tvWriteUninit(&tvVal); - if (!(attrs & AttrStatic)) { + if (!(declAttrs & AttrStatic)) { if (requiresDeepInit(vNode)) { - attrs = (Attr)(attrs | AttrDeepInit); + propAttrs = propAttrs | AttrDeepInit; } if (nonScalarPinitVec == nullptr) { nonScalarPinitVec = new NonScalarVec(); @@ -6395,8 +6401,8 @@ PreClass::Hoistable EmitterVisitor::emitClass(Emitter& e, ClassScopePtr cNode, tvWriteNull(&tvVal); } bool added UNUSED = - pce->addProperty(propName, attrs, typeConstraint, propDoc, &tvVal, - hphpcType); + pce->addProperty(propName, propAttrs, typeConstraint, + propDoc, &tvVal, hphpcType); assert(added); } } else if (ClassConstantPtr cc = diff --git a/hphp/test/slow/collection_classes/prop_init_literal_bug.php b/hphp/test/slow/collection_classes/prop_init_literal_bug.php new file mode 100644 index 000000000..cfd91200d --- /dev/null +++ b/hphp/test/slow/collection_classes/prop_init_literal_bug.php @@ -0,0 +1,6 @@ +