TypePtr SimpleFunctionCall::inferAndCheck(AnalysisResultPtr ar, TypePtr type, bool coerce) { reset(); ConstructPtr self = shared_from_this(); // handling define("CONSTANT", ...); if (m_className.empty()) { if (m_type == DefineFunction && m_params && m_params->getCount() >= 2) { ScalarExpressionPtr name = dynamic_pointer_cast<ScalarExpression>((*m_params)[0]); string varName; if (name) { varName = name->getIdentifier(); if (!varName.empty()) { ExpressionPtr value = (*m_params)[1]; TypePtr varType = value->inferAndCheck(ar, NEW_TYPE(Some), false); ar->getDependencyGraph()-> addParent(DependencyGraph::KindOfConstant, ar->getName(), varName, self); ConstantTablePtr constants = ar->findConstantDeclarer(varName)->getConstants(); if (constants != ar->getConstants()) { if (value && !value->isScalar()) { constants->setDynamic(ar, varName); varType = Type::Variant; } if (constants->isDynamic(varName)) { m_dynamicConstant = true; ar->getScope()->getVariables()-> setAttribute(VariableTable::NeedGlobalPointer); } else { constants->setType(ar, varName, varType, true); } // in case the old 'value' has been optimized constants->setValue(ar, varName, value); } return checkTypesImpl(ar, type, Type::Boolean, coerce); } } if (varName.empty() && ar->isFirstPass()) { ar->getCodeError()->record(self, CodeError::BadDefine, self); } } else if (m_type == ExtractFunction) { ar->getScope()->getVariables()->forceVariants(ar); } } FunctionScopePtr func; // avoid raising both MissingObjectContext and UnknownFunction bool errorFlagged = false; if (m_className.empty()) { func = ar->findFunction(m_name); } else { ClassScopePtr cls = ar->resolveClass(m_className); if (cls && cls->isVolatile()) { ar->getScope()->getVariables() ->setAttribute(VariableTable::NeedGlobalPointer); } if (!cls || cls->isRedeclaring()) { if (cls) { m_redeclaredClass = true; } if (!cls && ar->isFirstPass()) { ar->getCodeError()->record(self, CodeError::UnknownClass, self); } if (m_params) { m_params->inferAndCheck(ar, NEW_TYPE(Some), false); } return checkTypesImpl(ar, type, Type::Variant, coerce); } m_derivedFromRedeclaring = cls->derivesFromRedeclaring(); m_validClass = true; if (m_name == "__construct") { // if the class is known, php will try to identify class-name ctor func = cls->findConstructor(ar, true); } else { func = cls->findFunction(ar, m_name, true, true); } if (func && !func->isStatic()) { ClassScopePtr clsThis = ar->getClassScope(); FunctionScopePtr funcThis = ar->getFunctionScope(); if (!clsThis || (clsThis->getName() != m_className && !clsThis->derivesFrom(ar, m_className)) || funcThis->isStatic()) { // set the method static to avoid "unknown method" runtime exception if (Option::StaticMethodAutoFix && !func->containsThis()) { func->setStatic(); } if (ar->isFirstPass()) { ar->getCodeError()->record(self, CodeError::MissingObjectContext, self); errorFlagged = true; } func.reset(); } } } if (!func || func->isRedeclaring()) { if (func) { m_redeclared = true; ar->getScope()->getVariables()-> setAttribute(VariableTable::NeedGlobalPointer); } if (!func && !errorFlagged && ar->isFirstPass()) { ar->getCodeError()->record(self, CodeError::UnknownFunction, self); } if (m_params) { if (func) { FunctionScope::RefParamInfoPtr info = FunctionScope::GetRefParamInfo(m_name); ASSERT(info); for (int i = m_params->getCount(); i--; ) { if (info->isRefParam(i)) { m_params->markParam(i, canInvokeFewArgs()); } } } m_params->inferAndCheck(ar, NEW_TYPE(Some), false); } return checkTypesImpl(ar, type, Type::Variant, coerce); } m_builtinFunction = !func->isUserFunction(); if (m_redeclared) { if (m_params) { m_params->inferAndCheck(ar, NEW_TYPE(Some), false); } return checkTypesImpl(ar, type, type, coerce); } CHECK_HOOK(beforeSimpleFunctionCallCheck); m_valid = true; type = checkParamsAndReturn(ar, type, coerce, func); if (!m_valid && m_params) { m_params->markParams(false); } CHECK_HOOK(afterSimpleFunctionCallCheck); return type; }