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; }
void walk_function(const FunctionScopePtr& fscope) { if (fscope->isClosure()) return; auto ms = dynamic_pointer_cast<MethodStatement>(fscope->getStmt()); ConstructPtr node(ms->getStmts()); with_scope( fscope->getVariables(), [&] { walk_ast(node); } ); }
void makeFatalMeth(FileScope& file, AnalysisResultConstPtr ar, const std::string& msg, int line, Meth meth) { auto labelScope = std::make_shared<LabelScope>(); auto r = Location::Range(line, 0, line, 0); BlockScopePtr scope; auto args = std::make_shared<ExpressionList>(scope, r); args->addElement(Expression::MakeScalarExpression(ar, scope, r, msg)); auto e = std::make_shared<SimpleFunctionCall>(scope, r, "throw_fatal", false, args, ExpressionPtr()); meth(e); auto exp = std::make_shared<ExpStatement>(scope, labelScope, r, e); auto stmts = std::make_shared<StatementList>(scope, labelScope, r); stmts->addElement(exp); FunctionScopePtr fs = file.setTree(ar, stmts); fs->setOuterScope(file.shared_from_this()); fs->getStmt()->resetScope(fs); exp->copyLocationTo(fs->getStmt()); file.setOuterScope(const_cast<AnalysisResult*>(ar.get())->shared_from_this()); }
void AnalysisResult::analyzeProgram(bool system /* = false */) { AnalysisResultPtr ar = shared_from_this(); getVariables()->forceVariants(ar, VariableTable::AnyVars); getVariables()->setAttribute(VariableTable::ContainsLDynamicVariable); getVariables()->setAttribute(VariableTable::ContainsExtract); getVariables()->setAttribute(VariableTable::ForceGlobal); // Analyze Includes Logger::Verbose("Analyzing Includes"); sort(m_fileScopes.begin(), m_fileScopes.end(), by_filename); // fixed order unsigned int i = 0; for (i = 0; i < m_fileScopes.size(); i++) { collectFunctionsAndClasses(m_fileScopes[i]); } // Keep generated code identical without randomness canonicalizeSymbolOrder(); markRedeclaringClasses(); // Analyze some special cases for (set<string>::const_iterator it = Option::VolatileClasses.begin(); it != Option::VolatileClasses.end(); ++it) { ClassScopePtr cls = findClass(toLower(*it)); if (cls && cls->isUserClass()) { cls->setVolatile(); } } checkClassDerivations(); resolveNSFallbackFuncs(); // Analyze All Logger::Verbose("Analyzing All"); setPhase(AnalysisResult::AnalyzeAll); for (i = 0; i < m_fileScopes.size(); i++) { m_fileScopes[i]->analyzeProgram(ar); } /* Note that cls->collectMethods() can add entries to m_classDecs, which can invalidate iterators. So we have to create an array and then iterate over that. The new entries added to m_classDecs are always empty, so it doesnt matter that we dont include them in the iteration */ std::vector<ClassScopePtr> classes; classes.reserve(m_classDecs.size()); for (StringToClassScopePtrVecMap::const_iterator iter = m_classDecs.begin(); iter != m_classDecs.end(); ++iter) { for (ClassScopePtr cls: iter->second) { classes.push_back(cls); } } // Collect methods for (ClassScopePtr cls: classes) { if (cls->isRedeclaring()) { cls->setStaticDynamic(ar); } StringToFunctionScopePtrMap methods; cls->collectMethods(ar, methods, true /* include privates */); bool needAbstractMethodImpl = (!cls->isAbstract() && !cls->isInterface() && cls->derivesFromRedeclaring() == Derivation::Normal && !cls->getAttribute(ClassScope::UsesUnknownTrait)); for (StringToFunctionScopePtrMap::const_iterator iterMethod = methods.begin(); iterMethod != methods.end(); ++iterMethod) { FunctionScopePtr func = iterMethod->second; if (Option::WholeProgram && !func->hasImpl() && needAbstractMethodImpl) { FunctionScopePtr tmpFunc = cls->findFunction(ar, func->getName(), true, true); always_assert(!tmpFunc || !tmpFunc->hasImpl()); Compiler::Error(Compiler::MissingAbstractMethodImpl, func->getStmt(), cls->getStmt()); } m_methodToClassDecs[iterMethod->first].push_back(cls); } } ClassScopePtr cls; string cname; for (auto& sysclass_cls: m_systemClasses) { tie(cname, cls) = sysclass_cls; StringToFunctionScopePtrMap methods; cls->collectMethods(ar, methods, true /* include privates */); for (StringToFunctionScopePtrMap::const_iterator iterMethod = methods.begin(); iterMethod != methods.end(); ++iterMethod) { m_methodToClassDecs[iterMethod->first].push_back(cls); } } }