void FunctionScope::RecordFunctionInfo(std::string fname, FunctionScopePtr func) { VariableTablePtr variables = func->getVariables(); if (Option::WholeProgram) { Lock lock(s_refParamInfoLock); FunctionInfoPtr &info = s_refParamInfo[fname]; if (!info) { info = std::make_shared<FunctionInfo>(); } if (func->isStatic()) { info->setMaybeStatic(); } if (func->isRefReturn()) { info->setMaybeRefReturn(); } if (func->isReferenceVariableArgument()) { info->setRefVarArg(func->getMaxParamCount()); } for (int i = 0; i < func->getMaxParamCount(); i++) { if (func->isRefParam(i)) info->setRefParam(i); } } auto limit = func->getDeclParamCount(); for (int i = 0; i < limit; i++) { variables->addParam(func->getParamName(i), AnalysisResultPtr(), ConstructPtr()); } }
void MethodStatement::outputCPPArgInjections(CodeGenerator &cg, AnalysisResultPtr ar, const char *name, ClassScopePtr cls, FunctionScopePtr funcScope) { if (cg.getOutput() != CodeGenerator::SystemCPP) { if (m_params) { int n = m_params->getCount(); cg_printf("INTERCEPT_INJECTION(\"%s\", ", name); if (Option::GenArrayCreate && !hasRefParam()) { ar->m_arrayIntegerKeySizes.insert(n); outputParamArrayCreate(cg, true); cg_printf(", %s);\n", funcScope->isRefReturn() ? "ref(r)" : "r"); } else { cg_printf("(Array(ArrayInit(%d, true)", n); for (int i = 0; i < n; i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_params)[i]); const string ¶mName = param->getName(); cg_printf(".set%s(%d, %s%s)", param->isRef() ? "Ref" : "", i, Option::VariablePrefix, paramName.c_str()); } cg_printf(".create())), %s);\n", funcScope->isRefReturn() ? "ref(r)" : "r"); } } else { cg_printf("INTERCEPT_INJECTION(\"%s\", null_array, %s);\n", name, funcScope->isRefReturn() ? "ref(r)" : "r"); } } if (Option::GenRTTIProfileData && m_params) { for (int i = 0; i < m_params->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_params)[i]); if (param->hasRTTI()) { const string ¶mName = param->getName(); int id = ar->getParamRTTIEntryId(cls, funcScope, paramName); if (id != -1) { cg_printf("RTTI_INJECTION(%s%s, %d);\n", Option::VariablePrefix, paramName.c_str(), id); } } } } }
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); } }
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(); } } } }
static bool checkCopyElision(FunctionScopePtr func, ExpressionPtr exp) { if (!exp->getType()->is(Type::KindOfVariant) || func->isRefReturn()) { return false; } TypePtr imp = exp->getImplementedType(); if (!imp) imp = exp->getActualType(); if (!imp || !imp->is(Type::KindOfVariant)) return false; if (func->getNRVOFix() && exp->is(Expression::KindOfSimpleVariable)) { return true; } if (FunctionCallPtr fc = dynamic_pointer_cast<FunctionCall>(exp)) { FunctionScopePtr fs = fc->getFuncScope(); if (!fs || fs->isRefReturn()) { return true; } } return false; }