void ReturnStatement::analyzeProgram(AnalysisResultPtr ar) { if (m_exp) { FunctionScopePtr funcScope = getFunctionScope(); if (funcScope) { if (funcScope->isRefReturn()) { m_exp->setContext(Expression::RefValue); } } m_exp->analyzeProgram(ar); } if (ar->getPhase() == AnalysisResult::AnalyzeFinal) { if (m_exp) { TypePtr retType = m_exp->getCPPType(); bool needsCheck = !retType->isPrimitive(); if (m_exp->is(Expression::KindOfSimpleFunctionCall) || m_exp->is(Expression::KindOfDynamicFunctionCall) || m_exp->is(Expression::KindOfObjectMethodExpression)) { // return a value from another function call needsCheck = false; } ExpressionPtr tmp = m_exp; while (tmp && (tmp->is(Expression::KindOfObjectPropertyExpression) || tmp->is(Expression::KindOfArrayElementExpression))) { if (ObjectPropertyExpressionPtr opExp = dynamic_pointer_cast<ObjectPropertyExpression>(tmp)) { tmp = opExp->getObject(); } else { ArrayElementExpressionPtr aeExp = dynamic_pointer_cast<ArrayElementExpression>(tmp); ASSERT(aeExp); tmp = aeExp->getVariable(); } } if (SimpleVariablePtr svExp = dynamic_pointer_cast<SimpleVariable>(tmp)) { if (svExp->isThis()) { // returning something from $this needsCheck = false; } else { Symbol *sym = svExp->getSymbol(); if (sym && sym->isParameter() && !sym->isLvalParam()) { // returning something from non-lval parameter needsCheck = false; } } } if (needsCheck) { FunctionScopePtr funcScope = getFunctionScope(); if (funcScope) funcScope->setNeedsCheckMem(); } } } }
void ObjectPropertyExpression::analyzeProgram(AnalysisResultPtr ar) { m_object->analyzeProgram(ar); m_property->analyzeProgram(ar); if (ar->getPhase() == AnalysisResult::AnalyzeFinal) { if (!m_valid && m_context & (LValue|RefValue|DeepReference|UnsetContext)) { FunctionScopePtr func = getFunctionScope(); if (func) func->setNeedsRefTemp(); } if (getContext() & (RefValue | AssignmentLHS | OprLValue)) { FunctionScopePtr func = getFunctionScope(); if (func) func->setNeedsCheckMem(); } } }
void ParameterExpression::analyzeProgram(AnalysisResultPtr ar) { if (m_defaultValue) m_defaultValue->analyzeProgram(ar); if (ar->getPhase() == AnalysisResult::AnalyzeFinal) { if (!m_type.empty()) { addUserClass(ar, m_type); } // Have to use non const ref params for magic methods FunctionScopePtr fs = getFunctionScope(); if (fs->isMagicMethod() || fs->getName() == "offsetget") { fs->getVariables()->addLvalParam(m_name); } if (m_ref) fs->setNeedsCheckMem(); } }
void ArrayElementExpression::analyzeProgram(AnalysisResultPtr ar) { m_variable->analyzeProgram(ar); if (m_offset) m_offset->analyzeProgram(ar); if (ar->getPhase() == AnalysisResult::AnalyzeFinal) { if (!m_global && (m_context & AccessContext) && !(m_context & (LValue|RefValue|DeepReference| UnsetContext|RefParameter|InvokeArgument))) { TypePtr type = m_variable->getActualType(); if (!type || (!type->is(Type::KindOfString) && !type->is(Type::KindOfArray))) { FunctionScopePtr scope = getFunctionScope(); if (scope && !needsCSE()) scope->setNeedsRefTemp(); } } if (m_global) { if (getContext() & (LValue|RefValue|DeepReference)) { setContext(NoLValueWrapper); } else if (!m_dynamicGlobal && !(getContext() & (LValue|RefValue|RefParameter|DeepReference| UnsetContext|ExistContext))) { VariableTablePtr vars = ar->getVariables(); Symbol *sym = vars->getSymbol(m_globalName); if (!sym || sym->getDeclaration().get() == this) { Compiler::Error(Compiler::UseUndeclaredGlobalVariable, shared_from_this()); } } FunctionScopePtr scope = getFunctionScope(); if (scope) scope->setNeedsCheckMem(); } else { TypePtr at(m_variable->getActualType()); TypePtr et(m_variable->getExpectedType()); if (et && (et->is(Type::KindOfSequence) || et->is(Type::KindOfAutoSequence)) && at && at->isExactType()) { // since Sequence maps to Variant in the runtime, // using Sequence for the expected type will // never allow the necessary casts to be generated. m_variable->setExpectedType(at); } } } }
void FunctionCall::analyzeProgram(AnalysisResultPtr ar) { if (m_class) m_class->analyzeProgram(ar); if (m_nameExp) m_nameExp->analyzeProgram(ar); if (m_params) m_params->analyzeProgram(ar); if (ar->getPhase() == AnalysisResult::AnalyzeFinal) { if (m_funcScope && !m_arrayParams) { for (int i = 0, n = m_funcScope->getMaxParamCount(); i < n; ++i) { if (TypePtr specType = m_funcScope->getParamTypeSpec(i)) { const char *fmt = 0; string ptype; if (!m_params || m_params->getCount() <= i) { if (i >= m_funcScope->getMinParamCount()) break; fmt = "parameter %d of %s() requires %s, none given"; } else { ExpressionPtr param = (*m_params)[i]; if (!Type::Inferred(ar, param->getType(), specType)) { fmt = "parameter %d of %s() requires %s, called with %s"; } ptype = param->getType()->toString(); } if (fmt) { string msg; Util::string_printf (msg, fmt, i + 1, Util::escapeStringForCPP(m_funcScope->getOriginalName()).c_str(), specType->toString().c_str(), ptype.c_str()); Compiler::Error(Compiler::BadArgumentType, shared_from_this(), msg); } } } } if (getContext() & RefValue) { FunctionScopePtr fs = getFunctionScope(); if (fs) fs->setNeedsCheckMem(); } } }
void StaticStatement::analyzeProgramImpl(AnalysisResultPtr ar) { m_exp->analyzeProgram(ar); if (ar->getPhase() == AnalysisResult::AnalyzeAll) { BlockScopePtr scope = getScope(); for (int i = 0; i < m_exp->getCount(); i++) { ExpressionPtr exp = (*m_exp)[i]; ExpressionPtr variable; ExpressionPtr value; // turn static $a; into static $a = null; if (exp->is(Expression::KindOfSimpleVariable)) { variable = dynamic_pointer_cast<SimpleVariable>(exp); exp = AssignmentExpressionPtr (new AssignmentExpression(exp->getScope(), exp->getLocation(), Expression::KindOfAssignmentExpression, variable, CONSTANT("null"), false)); (*m_exp)[i] = exp; } assert(exp->is(Expression::KindOfAssignmentExpression)); AssignmentExpressionPtr assignment_exp = dynamic_pointer_cast<AssignmentExpression>(exp); variable = assignment_exp->getVariable(); value = assignment_exp->getValue(); SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(variable); // set the Declaration context here instead of all over this file - this phase // is the first to run var->setContext(Expression::Declaration); Symbol *sym = var->getSymbol(); sym->setStaticInitVal(value); } } else if (ar->getPhase() == AnalysisResult::AnalyzeFinal) { FunctionScopePtr fs = getFunctionScope(); if (fs) fs->setNeedsCheckMem(); } }
void SimpleVariable::analyzeProgram(AnalysisResultPtr ar) { m_superGlobal = BuiltinSymbols::IsSuperGlobal(m_name); m_superGlobalType = BuiltinSymbols::GetSuperGlobalType(m_name); VariableTablePtr variables = getScope()->getVariables(); if (m_superGlobal) { variables->setAttribute(VariableTable::NeedGlobalPointer); } else if (m_name == "GLOBALS") { m_globals = true; } else { m_sym = variables->addDeclaredSymbol( m_name, hhvm && Option::OutputHHBC ? shared_from_this() : ConstructPtr()); } if (ar->getPhase() == AnalysisResult::AnalyzeAll) { if (FunctionScopePtr func = getFunctionScope()) { if (m_name == "this" && (func->inPseudoMain() || getClassScope())) { func->setContainsThis(); m_this = true; if (!hasContext(ObjectContext)) { bool unset = hasAllContext(UnsetContext | LValue); func->setContainsBareThis( true, hasAnyContext(RefValue | RefAssignmentLHS) || m_sym->isRefClosureVar() || unset); if (variables->getAttribute(VariableTable::ContainsDynamicVariable)) { ClassScopePtr cls = getClassScope(); TypePtr t = !cls || cls->isRedeclaring() ? Type::Variant : Type::CreateObjectType(cls->getName()); variables->add(m_sym, t, true, ar, shared_from_this(), getScope()->getModifiers()); } } } if (m_sym && !(m_context & AssignmentLHS) && !((m_context & UnsetContext) && (m_context & LValue))) { m_sym->setUsed(); } } } else if (ar->getPhase() == AnalysisResult::AnalyzeFinal) { if (m_sym) { if (!m_sym->isSystem() && !(getContext() & (LValue|RefValue|RefParameter|UnsetContext|ExistContext)) && m_sym->getDeclaration().get() == this && !variables->getAttribute(VariableTable::ContainsLDynamicVariable) && !getScope()->is(BlockScope::ClassScope)) { if (getScope()->inPseudoMain()) { Compiler::Error(Compiler::UseUndeclaredGlobalVariable, shared_from_this()); } else if (!m_sym->isClosureVar()) { Compiler::Error(Compiler::UseUndeclaredVariable, shared_from_this()); } } // check function parameter that can occur in lval context if (m_sym->isParameter() && m_context & (LValue | RefValue | DeepReference | UnsetContext | InvokeArgument | OprLValue | DeepOprLValue)) { m_sym->setLvalParam(); } } if (m_superGlobal || m_name == "GLOBALS") { FunctionScopePtr func = getFunctionScope(); if (func) func->setNeedsCheckMem(); } } }