TypePtr VariableTable::add(Symbol *sym, TypePtr type, bool implicit, AnalysisResultConstPtr ar, ConstructPtr construct, ModifierExpressionPtr modifiers) { if (getAttribute(InsideStaticStatement)) { addStaticVariable(sym, ar); if (ClassScope::NeedStaticArray(getClassScope(), getFunctionScope())) { forceVariant(ar, sym->getName(), AnyVars); } } else if (getAttribute(InsideGlobalStatement)) { sym->setGlobal(); m_hasGlobal = true; AnalysisResult::Locker lock(ar); if (!isGlobalTable(ar)) { lock->getVariables()->add(sym->getName(), type, implicit, ar, construct, modifiers); } assert(type->is(Type::KindOfSome) || type->is(Type::KindOfAny)); TypePtr varType = ar->getVariables()->getFinalType(sym->getName()); if (varType) { type = varType; } else { lock->getVariables()->setType(ar, sym->getName(), type, true); } } else if (!sym->isHidden() && isPseudoMainTable()) { // A variable used in a pseudomain // only need to do this once... should mark the sym. ar->lock()->getVariables()->add(sym->getName(), type, implicit, ar, construct, modifiers); } if (modifiers) { if (modifiers->isProtected()) { sym->setProtected(); } else if (modifiers->isPrivate()) { sym->setPrivate(); m_hasPrivate = true; if (!sym->isStatic() && !modifiers->isStatic()) { m_hasNonStaticPrivate = true; } } if (modifiers->isStatic()) { addStaticVariable(sym, ar); } } type = setType(ar, sym, type, true); sym->setDeclaration(construct); if (!implicit && m_blockScope.isFirstPass()) { if (!sym->getValue()) { sym->setValue(construct); } } return type; }
void Parser::onMemberModifier(Token *out, Token *modifiers, Token *modifier) { ModifierExpressionPtr expList; if (modifiers) { expList = dynamic_pointer_cast<ModifierExpression>(modifiers->exp); } else { expList = NEW_EXP0(ModifierExpression); } expList->add(modifier->num); out->exp = expList; }
static bool isEquivRedecl(const std::string &name, ExpressionPtr exp, ModifierExpressionPtr modif, Symbol * symbol) { ASSERT(exp); ASSERT(modif); ASSERT(symbol); if (symbol->getName() != name || symbol->isProtected() != modif->isProtected() || symbol->isPrivate() != modif->isPrivate() || symbol->isPublic() != modif->isPublic() || symbol->isStatic() != modif->isStatic()) return false; ExpressionPtr symDeclExp = dynamic_pointer_cast<Expression>(symbol->getDeclaration()); if (!exp) return !symDeclExp; return exp->equals(symDeclExp); }
MethodStatementPtr ClassScope::importTraitMethod(const TraitMethod& traitMethod, AnalysisResultPtr ar, std::string methName) { MethodStatementPtr meth = traitMethod.method; std::string origMethName = traitMethod.originalName; ModifierExpressionPtr modifiers = traitMethod.modifiers; auto cloneMeth = dynamic_pointer_cast<MethodStatement>( dynamic_pointer_cast<ClassStatement>(m_stmt)->addClone(meth)); cloneMeth->setOriginalName(origMethName); // Note: keep previous modifiers if none specified when importing the trait if (modifiers && modifiers->getCount()) { cloneMeth->setModifiers(modifiers); } FunctionScopePtr funcScope = meth->getFunctionScope(); // Trait method typehints, self and parent, need to be converted auto cScope = dynamic_pointer_cast<ClassScope>(shared_from_this()); cloneMeth->fixupSelfAndParentTypehints( cScope ); auto cloneFuncScope = std::make_shared<HPHP::FunctionScope>( funcScope, ar, origMethName, cloneMeth, cloneMeth->getModifiers(), cScope->isUserClass()); cloneMeth->resetScope(cloneFuncScope); cloneFuncScope->setOuterScope(shared_from_this()); cloneFuncScope->setFromTrait(true); informClosuresAboutScopeClone(cloneMeth, cloneFuncScope, ar); cloneMeth->addTraitMethodToScope(ar, dynamic_pointer_cast<ClassScope>(shared_from_this())); // Preserve original filename (as this varies per-function and not per-unit // in the case of methods imported from flattened traits) auto const& name = meth->getOriginalFilename().empty() ? meth->getFileScope()->getName() : meth->getOriginalFilename(); cloneMeth->setOriginalFilename(name); return cloneMeth; }
// This method removes trait abstract methods that are either: // 1) implemented by other traits // 2) duplicate void ClassScope::removeSpareTraitAbstractMethods(AnalysisResultPtr ar) { assert(Option::WholeProgram); for (MethodToTraitListMap::iterator iter = m_importMethToTraitMap.begin(); iter != m_importMethToTraitMap.end(); iter++) { TraitMethodList& tMethList = iter->second; bool hasNonAbstractMeth = false; unsigned countAbstractMeths = 0; for (TraitMethodList::const_iterator traitMethIter = tMethList.begin(); traitMethIter != tMethList.end(); traitMethIter++) { ModifierExpressionPtr modifiers = traitMethIter->m_modifiers ? traitMethIter->m_modifiers : traitMethIter->m_method->getModifiers(); if (!(modifiers->isAbstract())) { hasNonAbstractMeth = true; } else { countAbstractMeths++; } } if (hasNonAbstractMeth || countAbstractMeths > 1) { // Erase spare abstract declarations bool firstAbstractMeth = true; for (TraitMethodList::iterator nextTraitIter = tMethList.begin(); nextTraitIter != tMethList.end(); ) { TraitMethodList::iterator traitIter = nextTraitIter++; ModifierExpressionPtr modifiers = traitIter->m_modifiers ? traitIter->m_modifiers : traitIter->m_method->getModifiers(); if (modifiers->isAbstract()) { if (hasNonAbstractMeth || !firstAbstractMeth) { tMethList.erase(traitIter); } firstAbstractMeth = false; } } } } }
static bool isEquivRedecl(const std::string &name, ExpressionPtr exp, ModifierExpressionPtr modif, Symbol * symbol) { assert(exp); assert(modif); assert(symbol); if (symbol->getName() != name || symbol->isProtected() != modif->isProtected() || symbol->isPrivate() != modif->isPrivate() || symbol->isPublic() != modif->isPublic() || symbol->isStatic() != modif->isStatic()) return false; auto symDeclExp = dynamic_pointer_cast<Expression>(symbol->getDeclaration()); if (!exp) return !symDeclExp; Variant v1, v2; auto s1 = exp->getScalarValue(v1); auto s2 = symDeclExp->getScalarValue(v2); if (s1 != s2) return false; if (s1) return same(v1, v2); return exp->getText() == symDeclExp->getText(); }
FunctionScope::FunctionScope(AnalysisResultPtr ar, bool method, const std::string &name, StatementPtr stmt, bool reference, int minParam, int maxParam, ModifierExpressionPtr modifiers, int attribute, const std::string &docComment, FileScopePtr file, bool inPseudoMain /* = false */) : BlockScope(name, docComment, stmt, BlockScope::FunctionScope), m_method(method), m_file(file), m_minParam(0), m_maxParam(0), m_attribute(attribute), m_refReturn(reference), m_modifiers(modifiers), m_virtual(false), m_overriding(false), m_redeclaring(-1), m_volatile(false), m_ignored(false), m_pseudoMain(inPseudoMain), m_magicMethod(false), m_system(false), m_inlineable(false), m_sep(false), m_containsThis(false), m_staticMethodAutoFixed(false), m_callTempCountMax(0), m_callTempCountCurrent(0) { bool canInline = true; if (inPseudoMain) { canInline = false; m_variables->forceVariants(ar); setReturnType(ar, Type::Variant); } setParamCounts(ar, minParam, maxParam); if (m_refReturn) { m_returnType = Type::Variant; } // FileScope's flags are from parser, but VariableTable has more flags // coming from type inference phase. So we are tranferring these two // flags just for better modularization between FileScope and VariableTable. if (m_attribute & FileScope::ContainsDynamicVariable) { m_variables->setAttribute(VariableTable::ContainsDynamicVariable); } if (m_attribute & FileScope::ContainsLDynamicVariable) { m_variables->setAttribute(VariableTable::ContainsLDynamicVariable); } if (m_attribute & FileScope::ContainsExtract) { m_variables->setAttribute(VariableTable::ContainsExtract); } if (m_attribute & FileScope::ContainsCompact) { m_variables->setAttribute(VariableTable::ContainsCompact); } if (m_attribute & FileScope::ContainsUnset) { m_variables->setAttribute(VariableTable::ContainsUnset); } if (m_attribute & FileScope::ContainsGetDefinedVars) { m_variables->setAttribute(VariableTable::ContainsGetDefinedVars); } if (m_stmt && Option::AllVolatile) { m_volatile = true; } m_dynamic = Option::IsDynamicFunction(method, m_name) || Option::EnableEval == Option::FullEval; if (modifiers) { m_virtual = modifiers->isAbstract(); } if (m_stmt) { MethodStatementPtr stmt = dynamic_pointer_cast<MethodStatement>(m_stmt); StatementListPtr stmts = stmt->getStmts(); if (stmts) { if (stmts->getRecursiveCount() > Option::InlineFunctionThreshold) canInline = false; for (int i = 0; i < stmts->getCount(); i++) { StatementPtr stmt = (*stmts)[i]; stmt->setFileLevel(); if (stmt->is(Statement::KindOfExpStatement)) { ExpStatementPtr expStmt = dynamic_pointer_cast<ExpStatement>(stmt); ExpressionPtr exp = expStmt->getExpression(); exp->setTopLevel(); } } } } else { canInline = false; } m_inlineable = canInline; }