void ClassScope::collectMethods(AnalysisResultPtr ar, StringToFunctionScopePtrMap &funcs, bool collectPrivate /* = true */, bool forInvoke /* = false */) { // add all functions this class has for (FunctionScopePtrVec::const_iterator iter = m_functionsVec.begin(); iter != m_functionsVec.end(); ++iter) { const FunctionScopePtr &fs = *iter; if (!collectPrivate && fs->isPrivate()) continue; FunctionScopePtr &func = funcs[fs->getName()]; if (!func) { func = fs; } else { func->setVirtual(); fs->setVirtual(); fs->setHasOverride(); if (fs->isFinal()) { std::string s__MockClass = "__MockClass"; ClassScopePtr derivedClass = func->getContainingClass(); if (derivedClass->m_userAttributes.find(s__MockClass) == derivedClass->m_userAttributes.end()) { Compiler::Error(Compiler::InvalidOverride, fs->getStmt(), func->getStmt()); } } } } int n = forInvoke ? m_parent.empty() ? 0 : 1 : m_bases.size(); // walk up for (int i = 0; i < n; i++) { const string &base = m_bases[i]; ClassScopePtr super = ar->findClass(base); if (super) { if (super->isRedeclaring()) { if (forInvoke) continue; const ClassScopePtrVec &classes = ar->findRedeclaredClasses(base); StringToFunctionScopePtrMap pristine(funcs); BOOST_FOREACH(ClassScopePtr cls, classes) { cls->m_derivedByDynamic = true; StringToFunctionScopePtrMap cur(pristine); derivedMagicMethods(cls); cls->collectMethods(ar, cur, false, forInvoke); inheritedMagicMethods(cls); funcs.insert(cur.begin(), cur.end()); cls->getVariables()-> forceVariants(ar, VariableTable::AnyNonPrivateVars); } if (base == m_parent) { m_derivesFromRedeclaring = DirectFromRedeclared; getVariables()->forceVariants(ar, VariableTable::AnyNonPrivateVars, false); getVariables()->setAttribute(VariableTable::NeedGlobalPointer); } else if (isInterface()) { m_derivesFromRedeclaring = DirectFromRedeclared; } setVolatile(); } else { derivedMagicMethods(super); super->collectMethods(ar, funcs, false, forInvoke); inheritedMagicMethods(super); if (super->derivesFromRedeclaring()) { if (base == m_parent) { m_derivesFromRedeclaring = IndirectFromRedeclared; getVariables()->forceVariants(ar, VariableTable::AnyNonPrivateVars); } else if (isInterface()) { m_derivesFromRedeclaring = IndirectFromRedeclared; } setVolatile(); } else if (super->isVolatile()) { setVolatile(); } } } else {
void ClassScope::collectMethods(AnalysisResultPtr ar, StringToFunctionScopePtrMap &funcs, bool collectPrivate) { // add all functions this class has for (FunctionScopePtrVec::const_iterator iter = m_functionsVec.begin(); iter != m_functionsVec.end(); ++iter) { const FunctionScopePtr &fs = *iter; if (!collectPrivate && fs->isPrivate()) continue; FunctionScopePtr &func = funcs[fs->getScopeName()]; if (!func) { func = fs; } else { func->setVirtual(); fs->setVirtual(); fs->setHasOverride(); if (fs->isFinal()) { std::string s__MockClass = "__MockClass"; ClassScopePtr derivedClass = func->getContainingClass(); if (derivedClass->m_userAttributes.find(s__MockClass) == derivedClass->m_userAttributes.end()) { Compiler::Error(Compiler::InvalidOverride, fs->getStmt(), func->getStmt()); } } } } int n = m_bases.size(); for (int i = 0; i < n; i++) { const string &base = m_bases[i]; ClassScopePtr super = ar->findClass(base); if (super) { if (super->isRedeclaring()) { const ClassScopePtrVec &classes = ar->findRedeclaredClasses(base); StringToFunctionScopePtrMap pristine(funcs); for (auto& cls : classes) { StringToFunctionScopePtrMap cur(pristine); derivedMagicMethods(cls); cls->collectMethods(ar, cur, false); inheritedMagicMethods(cls); funcs.insert(cur.begin(), cur.end()); } m_derivesFromRedeclaring = Derivation::Redeclaring; setVolatile(); } else { derivedMagicMethods(super); super->collectMethods(ar, funcs, false); inheritedMagicMethods(super); if (super->derivesFromRedeclaring() == Derivation::Redeclaring) { m_derivesFromRedeclaring = Derivation::Redeclaring; setVolatile(); } else if (super->isVolatile()) { setVolatile(); } } } else { Compiler::Error(Compiler::UnknownBaseClass, m_stmt, base); if (base == m_parent) { ar->declareUnknownClass(m_parent); m_derivesFromRedeclaring = Derivation::Redeclaring; setVolatile(); } else { /* * TODO(#3685260): this should not be removing interfaces from * the base list. */ if (isInterface()) { m_derivesFromRedeclaring = Derivation::Redeclaring; } m_bases.erase(m_bases.begin() + i); n--; i--; } } } }