TypePtr FunctionCall::checkParamsAndReturn(AnalysisResultPtr ar, TypePtr type, bool coerce, FunctionScopePtr func) { ConstructPtr self = shared_from_this(); ar->getDependencyGraph()->add(DependencyGraph::KindOfFunctionCall, ar->getName(), getText(), self, func->getFullName(), func->getStmt()); TypePtr frt = func->getReturnType(); if (!frt) { m_voidReturn = true; setActualType(TypePtr()); if (!type->is(Type::KindOfAny)) { if (!m_allowVoidReturn && ar->isSecondPass() && !func->isAbstract()) { ar->getCodeError()->record(self, CodeError::UseVoidReturn, self); } m_voidWrapper = true; } } else { m_voidReturn = false; m_voidWrapper = false; type = checkTypesImpl(ar, type, frt, coerce); } m_extraArg = func->inferParamTypes(ar, self, m_params, m_valid); m_variableArgument = func->isVariableArgument(); if (m_valid) { m_implementedType.reset(); } else { m_implementedType = Type::Variant; } return type; }
TypePtr ParameterExpression::inferTypes(AnalysisResultPtr ar, TypePtr type, bool coerce) { ASSERT(type->is(Type::KindOfSome) || type->is(Type::KindOfAny)); TypePtr ret = getTypeSpec(ar, true); if (m_defaultValue && !m_ref) { ret = m_defaultValue->inferAndCheck(ar, ret, false); } // parameters are like variables, but we need to remember these are // parameters so when variable table is generated, they are not generated // as declared variables. VariableTablePtr variables = ar->getScope()->getVariables(); if (ar->isFirstPass()) { ret = variables->addParam(m_name, ret, ar, shared_from_this()); } else { // Functions that can be called dynamically have to have // variant parameters, even if they have a type hint if (ar->getFunctionScope()->isDynamic() || ar->getFunctionScope()->isRedeclaring() || ar->getFunctionScope()->isVirtual()) { variables->forceVariant(ar, m_name, VariableTable::AnyVars); } int p; ret = variables->checkVariable(m_name, ret, true, ar, shared_from_this(), p); if (ar->isSecondPass() && ret->is(Type::KindOfSome)) { // This is probably too conservative. The problem is that // a function never called will have parameter types of Any. // Functions that it calls won't be able to accept variant unless // it is forced here. variables->forceVariant(ar, m_name, VariableTable::AnyVars); ret = Type::Variant; } else if (ar->getPhase() == AnalysisResult::LastInference && !ret->getName().empty()) { addUserClass(ar, ret->getName(), true); } } return ret; }