void ObjectMethodExpression::outputCPPObject(CodeGenerator &cg, AnalysisResultPtr ar) { bool isThis = m_object->isThis(); if (isThis) { TypePtr thisImplType(m_object->getImplementedType()); TypePtr thisActType (m_object->getActualType()); bool close = false; if (thisImplType) { ASSERT(thisActType); ASSERT(!Type::SameType(thisActType, thisImplType)); ClassScopePtr implCls(thisImplType->getClass(ar, getScope())); if (implCls && !implCls->derivesFrom(ar, thisActType->getName(), true, false)) { // This happens in this case: // if ($this instanceof Y) { // ... $this->meth() ... // } ClassScopePtr cls(thisActType->getClass(ar, getScope())); ASSERT(cls && !cls->derivedByDynamic()); // since we don't do type // assertions for these cg_printf("static_cast<%s%s*>(", Option::ClassPrefix, cls->getId().c_str()); close = true; } } if (getFunctionScope()->isStatic()) { if (close) { cg_printf("GET_THIS_VALID()"); } else { cg_printf("GET_THIS_ARROW()"); } } else { if (close) cg_printf("this"); } if (close) { cg_printf(")->"); } } else { TypePtr t = m_object->getType(); bool ok = !t || t->is(Type::KindOfObject) || t->is(Type::KindOfVariant); if (!ok) cg_printf("Variant("); m_object->outputCPP(cg, ar); if (!ok) cg_printf(")"); } }
bool ObjectPropertyExpression::outputCPPObject(CodeGenerator &cg, AnalysisResultPtr ar, bool noEvalOnError) { if (m_object->isThis()) { TypePtr thisImplType(m_object->getImplementedType()); TypePtr thisActType (m_object->getActualType()); bool close = false; if (m_valid && thisImplType) { ASSERT(thisActType); ASSERT(!Type::SameType(thisActType, thisImplType)); ClassScopePtr implCls(thisImplType->getClass(ar, getScope())); if (implCls && !implCls->derivesFrom(ar, thisActType->getName(), true, false)) { // This happens in this case: // if ($this instanceof Y) { // ... $this->prop ... // } ClassScopePtr cls(thisActType->getClass(ar, getScope())); ASSERT(cls && !cls->derivedByDynamic()); // since we don't do type // assertions for these cg_printf("static_cast<%s%s*>(", Option::ClassPrefix, cls->getId().c_str()); close = true; } } if (m_valid) { if (!m_object->getOriginalClass()) { m_valid = false; } else { FunctionScopeRawPtr fs = m_object->getOriginalFunction(); if (!fs || fs->isStatic()) { m_valid = false; } else if (m_object->getOriginalClass() != getClassScope()) { if (m_object->getOriginalClass()->isRedeclaring()) { m_valid = false; } else { m_objectClass = getClassScope(); } } } } if (m_valid) { if (close) cg_printf("this"); } else { if (!getClassScope() || getClassScope()->derivedByDynamic() || !static_pointer_cast<SimpleVariable>(m_object)->isGuardedThis()) { if (close) { cg_printf("GET_THIS_VALID()"); } else { cg_printf("GET_THIS_ARROW()"); } } } if (close) { cg_printf(")->"); } } else if (m_valid) { TypePtr act; if (!m_object->hasCPPTemp() && m_object->getImplementedType() && !Type::SameType(m_object->getImplementedType(), m_object->getActualType())) { act = m_object->getActualType(); m_object->setActualType(m_object->getImplementedType()); ClassScopePtr cls = ar->findExactClass(shared_from_this(), act->getName()); cg_printf("((%s%s*)", Option::ClassPrefix, cls->getId().c_str()); } m_object->outputCPP(cg, ar); if (act) { if (m_object->getImplementedType()->is(Type::KindOfObject)) { cg_printf(".get())"); } else { cg_printf(".getObjectData())"); } m_object->setActualType(act); } cg_printf("->"); } else { TypePtr t = m_object->getType(); bool ok = t && (t->is(Type::KindOfObject) || t->is(Type::KindOfVariant)); if (noEvalOnError && !ok) { if (!t || !t->is(Type::KindOfArray)) { cg_printf("("); if (m_object->outputCPPUnneeded(cg, ar)) cg_printf(", "); return true; } } ok = ok || !t; if (!ok) cg_printf("Variant("); m_object->outputCPP(cg, ar); if (!ok) cg_printf(")"); cg_printf("."); } if (m_valid && m_propSym->isPrivate() && m_objectClass != getOriginalClass()) { cg_printf("%s%s::", Option::ClassPrefix, getOriginalClass()->getId().c_str()); } return false; }
void ObjectPropertyExpression::outputCPPObjProperty(CodeGenerator &cg, AnalysisResultPtr ar, int doExist) { if (m_valid) { TypePtr type = m_object->getActualType(); if (type->isSpecificObject()) { ClassScopePtr cls(type->getClass(ar, getScope())); if (cls) getFileScope()->addUsedClassFullHeader(cls); } } string func = Option::ObjectPrefix; const char *error = ", true"; std::string context = ""; bool doUnset = m_context & LValue && m_context & UnsetContext; bool needTemp = false; if (cg.getOutput() != CodeGenerator::SystemCPP) { context = originalClassName(cg, true); } if (doUnset) { func = "o_unset"; error = ""; } else if (doExist) { func = doExist > 0 ? "o_isset" : "o_empty"; error = ""; } else { if (m_context & ExistContext) { error = ", false"; } if (m_context & InvokeArgument) { if (cg.callInfoTop() != -1) { func += "argval"; } else { func += "get"; } } else if (m_context & (LValue | RefValue | DeepReference | UnsetContext)) { if (m_context & UnsetContext) { always_assert(!(m_context & LValue)); // handled by doUnset func += "unsetLval"; } else { func += "lval"; } error = ""; needTemp = true; } else { func += "get"; if (isNonPrivate(ar)) { func += "Public"; context = ""; } } } if (m_valid && !m_object->isThis() && (!m_object->is(KindOfSimpleVariable) || !static_pointer_cast<SimpleVariable>(m_object)->isGuarded())) { cg_printf("(obj_tmp = "); outputCPPValidObject(cg, ar, false); bool write_context = hasAnyContext(LValue | RefValue | DeepReference | UnsetContext | OprLValue | DeepOprLValue | DeepAssignmentLHS | AssignmentLHS) && !doUnset; cg_printf(", LIKELY(obj_tmp != 0) %s ", write_context ? "||" : "?"); always_assert(m_property->is(KindOfScalarExpression)); ScalarExpressionPtr name = static_pointer_cast<ScalarExpression>(m_property); if (doExist || doUnset) { cg_printf(doUnset ? "unset" : doExist > 0 ? "isset" : "empty"); } ClassScopePtr cls = ar->findExactClass(shared_from_this(), m_object->getActualType()->getName()); if (write_context) { cg_printf("(throw_null_object_prop(),false),"); } cg_printf("(((%s%s*)obj_tmp)->%s%s)", Option::ClassPrefix, cls->getId().c_str(), Option::PropertyPrefix, name->getString().c_str()); if (!write_context) { cg_printf(" : (raise_null_object_prop(),%s)", doUnset ? "null_variant" : doExist ? doExist > 0 ? "false" : "true" : nullName(ar, getCPPType()).c_str()); } cg_printf(")"); return; } if (m_valid && (doExist || doUnset)) { cg_printf(doUnset ? "unset(" : doExist > 0 ? "isset(" : "empty("); } bool flag = outputCPPObject(cg, ar, !m_valid && (doUnset || doExist)); if (flag) { cg_printf("id("); outputCPPProperty(cg, ar); cg_printf(")"); if (doExist) cg_printf(", %s", doExist > 0 ? "false" : "true"); cg_printf(")"); } else if (m_valid) { always_assert(m_object->getActualType() && m_object->getActualType()->isSpecificObject()); ScalarExpressionPtr name = dynamic_pointer_cast<ScalarExpression>(m_property); cg_printf("%s%s", Option::PropertyPrefix, name->getString().c_str()); if (doExist || doUnset) cg_printf(")"); } else { cg_printf("%s(", func.c_str()); if (hasContext(InvokeArgument) && cg.callInfoTop() != -1) { cg_printf("cit%d->isRef(%d), ", cg.callInfoTop(), m_argNum); } outputCPPProperty(cg, ar); if (needTemp) { const string &tmp = cg.getReferenceTemp(); context = ", " + (tmp.empty() ? "Variant()" : tmp) + context; } cg_printf("%s%s)", error, context.c_str()); } }