remove assert for ::class and make it fatal instead

If you do `parent::class` in a pseudomain you end up in this case. Zend gives this message in that case

Reviewed By: @elgenie

Differential Revision: D1140116
Esse commit está contido em:
Paul Tarjan
2014-01-23 08:04:36 -08:00
commit de Sara Golemon
commit b873e69600
15 arquivos alterados com 3008 adições e 2903 exclusões
+19 -6
Ver Arquivo
@@ -3935,6 +3935,10 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
ClassConstantExpressionPtr cc(
static_pointer_cast<ClassConstantExpression>(node));
StringData* nName = makeStaticString(cc->getConName());
auto const getOriginalClassName = [&] {
const std::string& clsName = cc->getOriginalClassName();
return makeStaticString(clsName);
};
if (cc->isStatic()) {
// static::Constant
e.LateBoundCls();
@@ -3948,9 +3952,12 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
} else if (cc->getOriginalClass() &&
!cc->getOriginalClass()->isTrait()) {
// C::Constant inside a class
const std::string& clsName = cc->getOriginalClassName();
StringData* nCls = makeStaticString(clsName);
e.ClsCnsD(nName, nCls);
auto nCls = getOriginalClassName();
if (cc->isColonColonClass()) {
e.String(nCls);
} else {
e.ClsCnsD(nName, nCls);
}
} else if (cc->isSelf()) {
// self::Constant inside trait or pseudomain
e.Self();
@@ -3966,9 +3973,15 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
// will set cc->originalClassName to the trait's name for
// the isSelf and isParent cases, but self and parent must
// be resolved dynamically when used inside of traits.
const std::string& clsName = cc->getOriginalClassName();
StringData* nCls = makeStaticString(clsName);
e.ClsCnsD(nName, nCls);
auto nCls = getOriginalClassName();
if (cc->isColonColonClass()) {
std::ostringstream s;
s << "Cannont access " << nCls->data() << "::" << nName->data() <<
" when no class scope is active";
throw IncludeTimeFatalException(e.getNode(), s.str().c_str());
} else {
e.ClsCnsD(nName, nCls);
}
}
return true;
}
@@ -46,6 +46,7 @@ public:
bool isValid() const { return m_valid; }
bool isDynamic() const;
bool hasClass() const { return m_defScope != 0; }
bool isColonColonClass() const { return m_varName == "class"; }
private:
std::string m_varName;
BlockScope *m_defScope;
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+24
Ver Arquivo
@@ -797,6 +797,30 @@ void Parser::onClassConst(Token &out, Token &cls, Token &name, bool text) {
out->exp = con;
}
void Parser::onClassClass(Token &out, Token &cls, Token &name,
bool inStaticContext) {
if (inStaticContext) {
if (cls->same("parent") || cls->same("static")) {
PARSE_ERROR(
"%s::class cannot be used for compile-time class name resolution",
cls->text().c_str()
);
return;
}
}
if (cls->same("self") || cls->same("parent") || cls->same("static")) {
if (cls->same("self") && m_inTrait) {
// Sooo... self:: works dynamically for everything in a trait except
// for self::CLASS where it returns the trait name. Great...
onScalar(out, T_TRAIT_C, cls);
} else {
onClassConst(out, cls, name, inStaticContext);
}
} else {
onScalar(out, T_STRING, cls);
}
}
///////////////////////////////////////////////////////////////////////////////
// function/method declaration
+1
Ver Arquivo
@@ -190,6 +190,7 @@ public:
void onCollectionPair(Token &out, Token *pairs, Token *name, Token &value);
void onUserAttribute(Token &out, Token *attrList, Token &name, Token &value);
void onClassConst(Token &out, Token &cls, Token &name, bool text);
void onClassClass(Token &out, Token &cls, Token &name, bool text);
void fixStaticVars();
void onFunctionStart(Token &name, bool doPushComment = true);
void onFunction(Token &out, Token *modifier, Token &ret, Token &ref,
Arquivo executável → Arquivo normal
+7 -2
Ver Arquivo
@@ -2179,6 +2179,9 @@ static_class_constant:
| T_XHP_LABEL T_DOUBLE_COLON
ident { $1.xhpLabel();
_p->onClassConst($$, $1, $3, 1);}
| class_namespace_string_typeargs
T_DOUBLE_COLON
T_CLASS { _p->onClassClass($$, $1, $3, 1);}
;
scalar:
@@ -2571,8 +2574,10 @@ variable_list:
;
class_constant:
static_class_name
T_DOUBLE_COLON ident { _p->onClassConst($$, $1, $3, 0);}
static_class_name
T_DOUBLE_COLON ident { _p->onClassConst($$, $1, $3, 0);}
| static_class_name
T_DOUBLE_COLON T_CLASS { _p->onClassClass($$, $1, $3, 0);}
;
/* hack productions -- these allow some extra stuff in hack
+4
Ver Arquivo
@@ -639,6 +639,10 @@ struct Parser : ParserBase {
.setExtra(new OnClassConstEI(text));
}
void onClassClass(Token &out, Token &cls, Token &name, bool text) {
onClassConst(out, cls, name, text);
}
void fixStaticVars() { /* TODO */}
void onFunctionStart(Token& name, bool doPushComment = true) {
+8
Ver Arquivo
@@ -3724,6 +3724,14 @@ OPTBLD_INLINE void VMExecutionContext::iopClsCns(IOP_ARGS) {
assert(tv->m_type == KindOfClass);
Class* class_ = tv->m_data.pcls;
assert(class_ != nullptr);
if (clsCnsName->isame(s_class.get())) {
// Doesn't decref tv since Classes aren't refcounted
auto name = const_cast<StringData*>(class_->name());
assert(name->isStatic());
tv->m_type = KindOfStaticString;
tv->m_data.pstr = name;
return;
}
auto const clsCns = class_->clsCnsGet(clsCnsName);
if (clsCns.m_type == KindOfUninit) {
raise_error("Couldn't find constant %s::%s",
+38
Ver Arquivo
@@ -0,0 +1,38 @@
<?php
namespace NS;
function main() {
class B {}
class A extends B {
public function b() {
var_dump(self::class);
var_dump(static::class);
var_dump(parent::class);
}
}
var_dump(A::class);
A::b();
function c($c = A::class) {
var_dump($c);
}
c();
var_dump(Vector::class);
trait C {
public function c() {
var_dump(self::class);
var_dump(static::class);
var_dump(parent::class);
}
}
class D extends B {
use C;
}
D::c();
var_dump(C::class);
interface E {}
var_dump(E::class);
}
main();
@@ -0,0 +1,11 @@
string(4) "NS\A"
string(4) "NS\A"
string(4) "NS\A"
string(4) "NS\B"
string(4) "NS\A"
string(9) "NS\Vector"
string(4) "NS\C"
string(4) "NS\D"
string(4) "NS\B"
string(4) "NS\C"
string(4) "NS\E"
@@ -0,0 +1,2 @@
<?php
echo parent::class;
@@ -0,0 +1,6 @@
<?php
class C {
function foo() { include 'colon_colon_class_include_parent.inc'; }
}
C::foo();
@@ -0,0 +1 @@
HipHop Fatal error: Cannont access parent::class when no class scope is active in %s/test/slow/parser/colon_colon_class_include_parent.inc on line 2