void ClosureExpression::analyzeVars(AnalysisResultPtr ar) { m_values->analyzeProgram(ar); if (ar->getPhase() == AnalysisResult::AnalyzeAll) { getFunctionScope()->addUse(m_func->getFunctionScope(), BlockScope::UseKindClosure); m_func->getFunctionScope()->setClosureVars(m_vars); // closure function's variable table (not containing function's) VariableTablePtr variables = m_func->getFunctionScope()->getVariables(); VariableTablePtr containing = getFunctionScope()->getVariables(); for (int i = 0; i < m_vars->getCount(); i++) { auto param = dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]); auto const& name = param->getName(); { Symbol *containingSym = containing->addDeclaredSymbol(name, param); containingSym->setPassClosureVar(); Symbol *sym = variables->addDeclaredSymbol(name, param); sym->setClosureVar(); sym->setDeclaration(ConstructPtr()); if (param->isRef()) { sym->setRefClosureVar(); } else { sym->clearRefClosureVar(); } } } return; } }
void ClosureExpression::analyzeProgram(AnalysisResultPtr ar) { m_func->analyzeProgram(ar); if (m_vars) { m_values->analyzeProgram(ar); if (ar->getPhase() == AnalysisResult::AnalyzeAll) { getFunctionScope()->addUse(m_func->getFunctionScope(), BlockScope::UseKindClosure); m_func->getFunctionScope()->setClosureVars(m_vars); // closure function's variable table (not containing function's) VariableTablePtr variables = m_func->getFunctionScope()->getVariables(); VariableTablePtr containing = getFunctionScope()->getVariables(); for (int i = 0; i < m_vars->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]); const string &name = param->getName(); { Symbol *containingSym = containing->addDeclaredSymbol(name, param); containingSym->setPassClosureVar(); Symbol *sym = variables->addDeclaredSymbol(name, param); sym->setClosureVar(); sym->setDeclaration(ConstructPtr()); if (param->isRef()) { sym->setRefClosureVar(); sym->setUsed(); } else { sym->clearRefClosureVar(); sym->clearUsed(); } } } return; } if (ar->getPhase() == AnalysisResult::AnalyzeFinal) { // closure function's variable table (not containing function's) VariableTablePtr variables = m_func->getFunctionScope()->getVariables(); for (int i = 0; i < m_vars->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]); const string &name = param->getName(); // so we can assign values to them, instead of seeing CVarRef Symbol *sym = variables->getSymbol(name); if (sym && sym->isParameter()) { sym->setLvalParam(); } } } } FunctionScopeRawPtr container = getFunctionScope()->getContainingNonClosureFunction(); if (container && container->isStatic()) { m_func->getModifiers()->add(T_STATIC); } }
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, shared_from_this()); } if (ar->getPhase() == AnalysisResult::AnalyzeAll) { if (FunctionScopePtr func = getFunctionScope()) { if (m_name == "this" && func->mayContainThis()) { 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 && !m_this) { if (!m_sym->isSystem() && !(getContext() & (LValue|RefValue|RefParameter|UnsetContext|ExistContext)) && m_sym->getDeclaration().get() == this) { assert(!m_sym->isParameter()); if (!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(); } } } }
void MethodStatement::analyzeProgram(AnalysisResultPtr ar) { FunctionScopeRawPtr funcScope = getFunctionScope(); if (m_params) { m_params->analyzeProgram(ar); } if (m_stmt) m_stmt->analyzeProgram(ar); if (ar->getPhase() == AnalysisResult::AnalyzeAll) { funcScope->setParamSpecs(ar); if (funcScope->isGenerator()) { MethodStatementRawPtr orig = getOrigGeneratorFunc(); VariableTablePtr variables = funcScope->getVariables(); orig->getFunctionScope()->addUse(funcScope, BlockScope::UseKindClosure); orig->getFunctionScope()->setContainsBareThis( funcScope->containsBareThis(), funcScope->containsRefThis()); orig->getFunctionScope()->setContainsThis(funcScope->containsThis()); if (ExpressionListPtr params = orig->getParams()) { for (int i = 0; i < params->getCount(); ++i) { auto param = dynamic_pointer_cast<ParameterExpression>((*params)[i]); Symbol *gp = variables->addDeclaredSymbol(param->getName(), param); gp->setGeneratorParameter(); if (param->isRef()) { gp->setRefGeneratorParameter(); gp->setReferenced(); } } } if (ClosureExpressionRawPtr closure = orig->getContainingClosure()) { if (ExpressionListPtr cvars = closure->getClosureVariables()) { for (int i = 0; i < cvars->getCount(); ++i) { auto param = dynamic_pointer_cast<ParameterExpression>((*cvars)[i]); Symbol *gp = variables->addDeclaredSymbol( param->getName(), ConstructPtr()); gp->setGeneratorParameter(); if (param->isRef()) { gp->setRefGeneratorParameter(); gp->setReferenced(); } } } } } if (Option::IsDynamicFunction(m_method, m_name) || Option::AllDynamic) { funcScope->setDynamic(); } // TODO: this may have to expand to a concept of "virtual" functions... if (m_method) { funcScope->disableInline(); if (m_name.length() > 2 && m_name.substr(0,2) == "__") { bool magic = true; int paramCount = 0; if (m_name == "__destruct") { funcScope->setOverriding(Type::Variant); } else if (m_name == "__call") { funcScope->setOverriding(Type::Variant, Type::String, Type::Array); paramCount = 2; } else if (m_name == "__set") { funcScope->setOverriding(Type::Variant, Type::String, Type::Variant); paramCount = 2; } else if (m_name == "__get") { funcScope->setOverriding(Type::Variant, Type::String); paramCount = 1; } else if (m_name == "__isset") { funcScope->setOverriding(Type::Boolean, Type::String); paramCount = 1; } else if (m_name == "__unset") { funcScope->setOverriding(Type::Variant, Type::String); paramCount = 1; } else if (m_name == "__sleep") { funcScope->setOverriding(Type::Variant); } else if (m_name == "__wakeup") { funcScope->setOverriding(Type::Variant); } else if (m_name == "__set_state") { funcScope->setOverriding(Type::Variant, Type::Variant); paramCount = 1; } else if (m_name == "__tostring") { funcScope->setOverriding(Type::String); } else if (m_name == "__clone") { funcScope->setOverriding(Type::Variant); } else { paramCount = -1; if (m_name != "__construct") { magic = false; } } if (paramCount >= 0 && paramCount != funcScope->getMaxParamCount()) { Compiler::Error(Compiler::InvalidMagicMethod, shared_from_this()); magic = false; } if (magic) funcScope->setMagicMethod(); } // ArrayAccess methods else if (m_name.length() > 6 && m_name.substr(0, 6) == "offset") { if (m_name == "offsetexists") { funcScope->setOverriding(Type::Boolean, Type::Variant); } else if (m_name == "offsetget") { funcScope->setOverriding(Type::Variant, Type::Variant); } else if (m_name == "offsetset") { funcScope->setOverriding(Type::Variant, Type::Variant, Type::Variant); } else if (m_name == "offsetunset") { funcScope->setOverriding(Type::Variant, Type::Variant); } } } } else if (ar->getPhase() == AnalysisResult::AnalyzeFinal) { TypePtr ret = funcScope->getReturnType(); if (ret && ret->isSpecificObject()) { FileScopePtr fs = getFileScope(); if (fs) fs->addClassDependency(ar, ret->getName()); } if (!getFunctionScope()->usesLSB()) { if (StatementPtr orig = getOrigGeneratorFunc()) { orig->getFunctionScope()->clearUsesLSB(); } } } }