void InterfaceStatement::checkArgumentsToPromote( FileScopeRawPtr scope, ExpressionListPtr promotedParams, int type) { if (!m_stmt) { return; } for (int i = 0; i < m_stmt->getCount(); i++) { MethodStatementPtr meth = dynamic_pointer_cast<MethodStatement>((*m_stmt)[i]); if (meth && meth->isNamed("__construct")) { ExpressionListPtr params = meth->getParams(); if (params) { for (int i = 0; i < params->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*params)[i]); if (param->getModifier() != 0) { if (type == T_TRAIT || type == T_INTERFACE) { param->parseTimeFatal(scope, Compiler::InvalidAttribute, "Constructor parameter promotion " "not allowed on traits or interfaces"); } if (promotedParams) { promotedParams->addElement(param); } } } } return; // nothing else to look at } } }
void FunctionScope::setParamCounts(AnalysisResultPtr ar, int minParam, int maxParam) { m_minParam = minParam; m_maxParam = maxParam; ASSERT(m_minParam >= 0 && m_maxParam >= m_minParam); if (m_maxParam > 0) { m_paramNames.resize(m_maxParam); m_paramTypes.resize(m_maxParam); m_paramTypeSpecs.resize(m_maxParam); m_refs.resize(m_maxParam); if (m_stmt) { MethodStatementPtr stmt = dynamic_pointer_cast<MethodStatement>(m_stmt); ExpressionListPtr params = stmt->getParams(); for (int i = 0; i < m_maxParam; i++) { if (stmt->isRef(i)) m_refs[i] = true; ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*params)[i]); m_paramNames[i] = param->getName(); m_paramTypeSpecs[i] = param->getTypeSpec(ar); } } } }
void FunctionScope::setParamCounts(AnalysisResultConstPtr ar, int minParam, int numDeclParam) { if (minParam >= 0) { m_minParam = minParam; m_numDeclParams = numDeclParam; } else { assert(numDeclParam == minParam); } assert(m_minParam >= 0 && m_numDeclParams >= m_minParam); assert(IMPLIES(hasVariadicParam(), m_numDeclParams > 0)); if (m_numDeclParams > 0) { m_paramNames.resize(m_numDeclParams); m_refs.resize(m_numDeclParams); if (m_stmt) { MethodStatementPtr stmt = dynamic_pointer_cast<MethodStatement>(m_stmt); ExpressionListPtr params = stmt->getParams(); for (int i = 0; i < m_numDeclParams; i++) { if (stmt->isRef(i)) m_refs[i] = true; ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*params)[i]); m_paramNames[i] = param->getName(); } assert(m_paramNames.size() == m_numDeclParams); } } }
void FunctionScope::outputCPPParamsImpl(CodeGenerator &cg, AnalysisResultPtr ar) { int paramcount = getMaxParamCount(); if (isUserFunction()) { MethodStatementPtr m = dynamic_pointer_cast<MethodStatement>(getStmt()); outputCPPParamsDecl(cg, ar, m->getParams(), false); return; } bool first = true; if (isVariableArgument()) { cg.printf("int num_args"); first = false; } for (int i = 0; i < paramcount; i++) { if (first) { first = false; } else { cg.printf(", "); } TypePtr type = getParamType(i); type->outputCPPDecl(cg, ar); cg.printf(" a%d", i); } if (isVariableArgument()) { cg.printf(", Array args /* = Array() */"); } }
bool AliasManager::optimize(AnalysisResultPtr ar, MethodStatementPtr m) { m_arp = ar; m_variables = ar->getScope()->getVariables(); if (!m_variables->isPseudoMainTable()) { m_variables->clearUsed(); } if (ExpressionListPtr pPtr = m->getParams()) { ExpressionList ¶ms = *pPtr; for (int i = params.getCount(); i--; ) { ParameterExpressionPtr p = spc(ParameterExpression, params[i]); AliasInfo &ai = m_aliasInfo[p->getName()]; if (p->isRef()) { ai.setIsRefTo(); } } } collectAliasInfoRecur(m->getStmts()); for (AliasInfoMap::iterator it = m_aliasInfo.begin(), end = m_aliasInfo.end(); it != end; ++it) { if (m_variables->isGlobal(it->first) || m_variables->isStatic(it->first)) { it->second.setIsGlobal(); } } canonicalizeRecur(m->getStmts()); return m_changed; }
void FunctionScope::outputCPPParamsCall(CodeGenerator &cg, AnalysisResultPtr ar, bool aggregateParams) { if (isVariableArgument()) { cg.printf("num_args, "); } bool userFunc = isUserFunction(); ExpressionListPtr params; if (userFunc) { MethodStatementPtr stmt = dynamic_pointer_cast<MethodStatement>(m_stmt); params = stmt->getParams(); } if (aggregateParams) { cg.printf("Array("); if (m_maxParam) { // param arrays are always vectors cg.printf("ArrayInit(%d, true).", m_maxParam); } } for (int i = 0; i < m_maxParam; i++) { if (i > 0) cg.printf(aggregateParams ? "." : ", "); bool isRef; if (userFunc) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*params)[i]); isRef = param->isRef(); if (aggregateParams) { cg.printf("set%s(%d, v_%s", isRef ? "Ref" : "", i, param->getName().c_str()); } else { cg.printf("%sv_%s%s", isRef ? "ref(" : "", param->getName().c_str(), isRef ? ")" : ""); } } else { isRef = isRefParam(i); if (aggregateParams) { cg.printf("set%s(%d, a%d", isRef ? "Ref" : "", i, i); } else { cg.printf("%sa%d%s", isRef ? "ref(" : "", i, isRef ? ")" : ""); } } if (aggregateParams) cg.printf(")"); } if (aggregateParams) { if (m_maxParam) cg.printf(".create()"); cg.printf(")"); } if (isVariableArgument()) { if (aggregateParams || m_maxParam > 0) cg.printf(","); cg.printf("args"); } }
void FunctionScope::setParamSpecs(AnalysisResultPtr ar) { if (m_maxParam > 0 && m_stmt) { MethodStatementPtr stmt = dynamic_pointer_cast<MethodStatement>(m_stmt); ExpressionListPtr params = stmt->getParams(); for (int i = 0; i < m_maxParam; i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*params)[i]); TypePtr specType = param->getTypeSpec(ar, false); if (specType && !specType->is(Type::KindOfSome) && !specType->is(Type::KindOfVariant)) { m_paramTypeSpecs[i] = specType; } ExpressionPtr exp = param->defaultValue(); if (exp) { m_paramDefaults[i] = exp->getText(false, false, ar); } } } }
ExpressionPtr FunctionCall::inliner(AnalysisResultConstPtr ar, ExpressionPtr obj, std::string localThis) { FunctionScopePtr fs = getFunctionScope(); if (m_noInline || !fs || fs == m_funcScope || !m_funcScope->getStmt()) { return ExpressionPtr(); } BlockScope::s_jobStateMutex.lock(); if (m_funcScope->getMark() == BlockScope::MarkProcessing) { fs->setForceRerun(true); BlockScope::s_jobStateMutex.unlock(); return ExpressionPtr(); } ReadLock lock(m_funcScope->getInlineMutex()); BlockScope::s_jobStateMutex.unlock(); if (!m_funcScope->getInlineAsExpr()) { return ExpressionPtr(); } if (m_funcScope->getInlineSameContext() && m_funcScope->getContainingClass() && m_funcScope->getContainingClass() != getClassScope()) { /* The function contains a context sensitive construct such as call_user_func (context sensitive because it could call array('parent', 'foo')) so its not safe to inline it into a different context. */ return ExpressionPtr(); } MethodStatementPtr m (dynamic_pointer_cast<MethodStatement>(m_funcScope->getStmt())); VariableTablePtr vt = fs->getVariables(); int nAct = m_params ? m_params->getCount() : 0; int nMax = m_funcScope->getMaxParamCount(); if (nAct < m_funcScope->getMinParamCount() || !m->getStmts()) { return ExpressionPtr(); } InlineCloneInfo info(m_funcScope); info.elist = ExpressionListPtr(new ExpressionList( getScope(), getLocation(), ExpressionList::ListKindWrapped)); std::ostringstream oss; oss << fs->nextInlineIndex() << "_" << m_name << "_"; std::string prefix = oss.str(); if (obj) { info.callWithThis = true; if (!obj->isThis()) { SimpleVariablePtr var (new SimpleVariable(getScope(), obj->getLocation(), prefix + "this")); var->updateSymbol(SimpleVariablePtr()); var->getSymbol()->setHidden(); var->getSymbol()->setUsed(); var->getSymbol()->setReferenced(); AssignmentExpressionPtr ae (new AssignmentExpression(getScope(), obj->getLocation(), var, obj, false)); info.elist->addElement(ae); info.sepm[var->getName()] = var; info.localThis = var->getName(); } } else { if (m_classScope) { if (!m_funcScope->isStatic()) { ClassScopeRawPtr oCls = getOriginalClass(); FunctionScopeRawPtr oFunc = getOriginalFunction(); if (oCls && !oFunc->isStatic() && (oCls == m_classScope || oCls->derivesFrom(ar, m_className, true, false))) { info.callWithThis = true; info.localThis = localThis; } } if (!isSelf() && !isParent() && !isStatic()) { info.staticClass = m_className; } } } ExpressionListPtr plist = m->getParams(); int i; for (i = 0; i < nMax || i < nAct; i++) { ParameterExpressionPtr param (i < nMax ? dynamic_pointer_cast<ParameterExpression>((*plist)[i]) : ParameterExpressionPtr()); ExpressionPtr arg = i < nAct ? (*m_params)[i] : Clone(param->defaultValue(), getScope()); SimpleVariablePtr var (new SimpleVariable(getScope(), (i < nAct ? arg.get() : this)->getLocation(), prefix + (param ? param->getName() : lexical_cast<string>(i)))); var->updateSymbol(SimpleVariablePtr()); var->getSymbol()->setHidden(); var->getSymbol()->setUsed(); var->getSymbol()->setReferenced(); bool ref = (i < nMax && m_funcScope->isRefParam(i)) || arg->hasContext(RefParameter); arg->clearContext(RefParameter); AssignmentExpressionPtr ae (new AssignmentExpression(getScope(), arg->getLocation(), var, arg, ref)); info.elist->addElement(ae); if (i < nAct && (ref || !arg->isScalar())) { info.sepm[var->getName()] = var; } } if (cloneStmtsForInline(info, m->getStmts(), prefix, ar, getFunctionScope()) <= 0) { info.elist->addElement(makeConstant(ar, "null")); } if (info.sepm.size()) { ExpressionListPtr unset_list (new ExpressionList(getScope(), getLocation())); for (StringToExpressionPtrMap::iterator it = info.sepm.begin(), end = info.sepm.end(); it != end; ++it) { ExpressionPtr var = it->second->clone(); var->clearContext((Context)(unsigned)-1); unset_list->addElement(var); } ExpressionPtr unset( new UnaryOpExpression(getScope(), getLocation(), unset_list, T_UNSET, true)); i = info.elist->getCount(); ExpressionPtr ret = (*info.elist)[--i]; if (ret->isScalar()) { info.elist->insertElement(unset, i); } else { ExpressionListPtr result_list (new ExpressionList(getScope(), getLocation(), ExpressionList::ListKindLeft)); if (ret->hasContext(LValue)) { result_list->setContext(LValue); result_list->setContext(ReturnContext); } result_list->addElement(ret); result_list->addElement(unset); (*info.elist)[i] = result_list; } } recomputeEffects(); return replaceValue(info.elist); }
void FunctionScope::outputCPPClassMap(CodeGenerator &cg, AnalysisResultPtr ar) { int attribute = ClassInfo::IsNothing; if (!isUserFunction()) attribute |= ClassInfo::IsSystem; if (isRedeclaring()) attribute |= ClassInfo::IsRedeclared; if (isVolatile()) attribute |= ClassInfo::IsVolatile; if (isRefReturn()) attribute |= ClassInfo::IsReference; if (isProtected()) { attribute |= ClassInfo::IsProtected; } else if (isPrivate()) { attribute |= ClassInfo::IsPrivate; } else { attribute |= ClassInfo::IsPublic; } if (isAbstract()) attribute |= ClassInfo::IsAbstract; if (isStatic() && !isStaticMethodAutoFixed()) { attribute |= ClassInfo::IsStatic; } if (isFinal()) attribute |= ClassInfo::IsFinal; if (!m_docComment.empty()) attribute |= ClassInfo::HasDocComment; // Use the original cased name, for reflection to work correctly. cg.printf("(const char *)0x%04X, \"%s\", NULL, NULL,\n", attribute, getOriginalName().c_str()); if (!m_docComment.empty()) { char *dc = string_cplus_escape(m_docComment.c_str()); cg.printf("\"%s\",\n", dc); free(dc); } Variant defArg; for (int i = 0; i < m_maxParam; i++) { int attr = ClassInfo::IsNothing; if (i >= m_minParam) attr |= ClassInfo::IsOptional; if (isRefParam(i)) attr |= ClassInfo::IsReference; cg.printf("(const char *)0x%04X, \"%s\", \"%s\", ", attr, m_paramNames[i].c_str(), Util::toLower(m_paramTypes[i]->getPHPName()).c_str()); if (i >= m_minParam) { MethodStatementPtr m = dynamic_pointer_cast<MethodStatement>(getStmt()); if (m) { ExpressionListPtr params = m->getParams(); assert(i < params->getCount()); ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*params)[i]); assert(param); ExpressionPtr def = param->defaultValue(); if (!def->isScalar() || !def->getScalarValue(defArg)) { defArg = "1"; } } else { defArg = "1"; } char *s = string_cplus_escape(f_serialize(defArg).data()); cg.printf("\"%s\",\n", s); free(s); } else { cg.printf("\"\",\n"); } } cg.printf("NULL,\n"); m_variables->outputCPPStaticVariables(cg, ar); }
void FunctionScope::outputCPPParamsCall(CodeGenerator &cg, AnalysisResultPtr ar, bool aggregateParams) { if (isVariableArgument()) { cg_printf("num_args, "); } bool userFunc = isUserFunction(); MethodStatementPtr stmt; ExpressionListPtr params; if (userFunc) { stmt = dynamic_pointer_cast<MethodStatement>(m_stmt); params = stmt->getParams(); } bool arrayCreated = false; if (Option::GenArrayCreate && cg.getOutput() != CodeGenerator::SystemCPP && aggregateParams && m_maxParam > 0) { if (stmt && !stmt->hasRefParam()) { cg_printf("Array("); stmt->outputParamArrayInit(cg); cg_printf(")"); arrayCreated = true; } else if (!userFunc && !hasRefParam(m_maxParam)) { cg_printf("Array("); for (int i = 0; i < m_maxParam; i++) { if (isRefParam(i)) { cg_printf("%d, ref(a%d)", i, i); } else { cg_printf("%d, a%d", i, i); } if (i < m_maxParam - 1) { cg_printf(", "); } else { cg_printf(")"); } } cg_printf(")"); arrayCreated = true; } } if (arrayCreated && isVariableArgument()) { cg_printf(","); cg_printf("args"); return; } if (aggregateParams) { cg_printf("Array("); if (m_maxParam) { // param arrays are always vectors cg_printf("ArrayInit(%d, true).", m_maxParam); } } for (int i = 0; i < m_maxParam; i++) { if (i > 0) cg_printf(aggregateParams ? "." : ", "); bool isRef; if (userFunc) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*params)[i]); isRef = param->isRef(); if (aggregateParams) { cg_printf("set%s(v_%s", isRef ? "Ref" : "", param->getName().c_str()); } else { cg_printf("%sv_%s%s", isRef ? "ref(" : "", param->getName().c_str(), isRef ? ")" : ""); } } else { isRef = isRefParam(i); if (aggregateParams) { cg_printf("set%s(a%d", isRef ? "Ref" : "", i); } else { cg_printf("%sa%d%s", isRef ? "ref(" : "", i, isRef ? ")" : ""); } } if (aggregateParams) cg_printf(")"); } if (aggregateParams) { if (m_maxParam) cg_printf(".create()"); cg_printf(")"); } if (isVariableArgument()) { if (aggregateParams || m_maxParam > 0) cg_printf(","); cg_printf("args"); } }
void FunctionScope::outputCPPClassMap(CodeGenerator &cg, AnalysisResultPtr ar) { int attribute = ClassInfo::IsNothing; if (!isUserFunction()) attribute |= ClassInfo::IsSystem; if (isRedeclaring()) attribute |= ClassInfo::IsRedeclared; if (isVolatile()) attribute |= ClassInfo::IsVolatile; if (isRefReturn()) attribute |= ClassInfo::IsReference; if (isProtected()) { attribute |= ClassInfo::IsProtected; } else if (isPrivate()) { attribute |= ClassInfo::IsPrivate; } else { attribute |= ClassInfo::IsPublic; } if (isAbstract()) attribute |= ClassInfo::IsAbstract; if (isStatic()) { attribute |= ClassInfo::IsStatic; } if (isFinal()) attribute |= ClassInfo::IsFinal; if (isVariableArgument()) { attribute |= ClassInfo::VariableArguments; } if (isReferenceVariableArgument()) { attribute |= ClassInfo::RefVariableArguments; } if (isMixedVariableArgument()) { attribute |= ClassInfo::MixedVariableArguments; } attribute |= m_attributeClassInfo; if (!m_docComment.empty() && Option::GenerateDocComments) { attribute |= ClassInfo::HasDocComment; } else { attribute &= ~ClassInfo::HasDocComment; } // Use the original cased name, for reflection to work correctly. cg_printf("(const char *)0x%04X, \"%s\", \"%s\", (const char *)%d, " "(const char *)%d, NULL, NULL,\n", attribute, getOriginalName().c_str(), m_stmt ? m_stmt->getLocation()->file : "", m_stmt ? m_stmt->getLocation()->line0 : 0, m_stmt ? m_stmt->getLocation()->line1 : 0); if (!m_docComment.empty() && Option::GenerateDocComments) { char *dc = string_cplus_escape(m_docComment.c_str(), m_docComment.size()); cg_printf("\"%s\",\n", dc); free(dc); } Variant defArg; for (int i = 0; i < m_maxParam; i++) { int attr = ClassInfo::IsNothing; if (i >= m_minParam) attr |= ClassInfo::IsOptional; if (isRefParam(i)) attr |= ClassInfo::IsReference; const std::string &tname = m_paramTypeSpecs[i] ? m_paramTypeSpecs[i]->getPHPName() : ""; cg_printf("(const char *)0x%04X, \"%s\", \"%s\", ", attr, m_paramNames[i].c_str(), Util::toLower(tname).c_str()); if (i >= m_minParam) { MethodStatementPtr m = dynamic_pointer_cast<MethodStatement>(getStmt()); if (m) { ExpressionListPtr params = m->getParams(); assert(i < params->getCount()); ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*params)[i]); assert(param); ExpressionPtr def = param->defaultValue(); string sdef = def->getText(); char *esdef = string_cplus_escape(sdef.data(), sdef.size()); if (!def->isScalar() || !def->getScalarValue(defArg)) { /** * Special value runtime/ext/ext_reflection.cpp can check and throw. * If we want to avoid seeing this so to make getDefaultValue() * work better for reflections, we will have to implement * getScalarValue() to greater extent under compiler/expressions. */ cg_printf("\"\x01\", \"%s\",\n", esdef); } else { String str = f_serialize(defArg); char *s = string_cplus_escape(str.data(), str.size()); cg_printf("\"%s\", \"%s\",\n", s, esdef); free(s); } free(esdef); } else { char *def = string_cplus_escape(m_paramDefaults[i].data(), m_paramDefaults[i].size()); char *defText = string_cplus_escape(m_paramDefaultTexts[i].data(), m_paramDefaultTexts[i].size()); cg_printf("\"%s\", \"%s\",\n", def, defText); free(def); free(defText); } } else { cg_printf("\"\", \"\",\n"); } } cg_printf("NULL,\n"); m_variables->outputCPPStaticVariables(cg, ar); }