From 0b7e8d12517432cd9f59d07979c62d25211bbde2 Mon Sep 17 00:00:00 2001 From: Mark Williams Date: Fri, 19 Apr 2013 15:46:04 -0700 Subject: [PATCH] Check accessibility before replacing static props with their value If a static property is provably not modified, and it has a literal initializer, it is optimized away at translation time. We should check that its accessible before doing that. --- .../expression/static_member_expression.cpp | 44 ++++++++++++------- hphp/test/quick/hopt_sprop_accessibility.php | 8 ++-- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/hphp/compiler/expression/static_member_expression.cpp b/hphp/compiler/expression/static_member_expression.cpp index 0818729b5..d78e8d085 100644 --- a/hphp/compiler/expression/static_member_expression.cpp +++ b/hphp/compiler/expression/static_member_expression.cpp @@ -156,25 +156,35 @@ ExpressionPtr StaticMemberExpression::preOptimize(AnalysisResultConstPtr ar) { ExpressionPtr StaticMemberExpression::postOptimize(AnalysisResultConstPtr ar) { Symbol *sym = nullptr; if (m_class) updateClassName(); - if (!m_class && m_resolvedClass && m_valid && - m_exp->is(Expression::KindOfScalarExpression)) { - ClassScopePtr cls = ar->findExactClass(shared_from_this(), m_className); - if (cls && (!cls->isVolatile() || isPresent())) { - ScalarExpressionPtr var = dynamic_pointer_cast(m_exp); - const std::string &name = var->getString(); + if (m_class || !m_resolvedClass || !m_valid || + !m_exp->is(Expression::KindOfScalarExpression)) { + return ExpressionPtr(); + } - sym = cls->findProperty(cls, name, ar); - if (sym && !sym->isIndirectAltered() && sym->isStatic()) { - ConstructPtr init = sym->getClassInitVal(); - if (init) { - ExpressionPtr rep = dynamic_pointer_cast(init); - if (rep->isScalar()) { - ExpressionPtr repClone = Clone(rep, getScope()); - if (!repClone->getActualType()) { - repClone->setActualType(getActualType()); - } - return replaceValue(repClone); + ClassScopePtr cls = ar->findExactClass(shared_from_this(), m_className); + if (!cls || (cls->isVolatile() && !isPresent())) { + return ExpressionPtr(); + } + + ScalarExpressionPtr var = dynamic_pointer_cast(m_exp); + const std::string &name = var->getString(); + + sym = cls->findProperty(cls, name, ar); + if (sym && !sym->isIndirectAltered() && sym->isStatic()) { + if (sym->isPrivate() ? cls == getClassScope() : + sym->isProtected() ? + getClassScope() && getClassScope()->derivesFrom(ar, cls->getName(), + true, false) : + true) { + ConstructPtr init = sym->getClassInitVal(); + if (init) { + ExpressionPtr rep = dynamic_pointer_cast(init); + if (rep->isScalar()) { + ExpressionPtr repClone = Clone(rep, getScope()); + if (!repClone->getActualType()) { + repClone->setActualType(getActualType()); } + return replaceValue(repClone); } } } diff --git a/hphp/test/quick/hopt_sprop_accessibility.php b/hphp/test/quick/hopt_sprop_accessibility.php index 0ccb2d17a..7318e870e 100644 --- a/hphp/test/quick/hopt_sprop_accessibility.php +++ b/hphp/test/quick/hopt_sprop_accessibility.php @@ -5,10 +5,10 @@ $nonstaticUnscoped = function () { }; class A { - private static $priv = 7; - function readVar() { - A::$priv; - } + private static $priv = 7; + function readVar() { + return A::$priv; + } } (new A())->readVar();