void ClassScope::checkDerivation(AnalysisResultPtr ar, hphp_string_iset &seen) { seen.insert(m_name); hphp_string_iset bases; for (int i = m_bases.size() - 1; i >= 0; i--) { const string &base = m_bases[i]; if (seen.find(base) != seen.end() || bases.find(base) != bases.end()) { Compiler::Error( Compiler::InvalidDerivation, m_stmt, "The class hierarchy contains a circular reference involving " + base); if (i == 0 && !m_parent.empty()) { assert(base == m_parent); m_parent.clear(); } m_bases.erase(m_bases.begin() + i); continue; } bases.insert(base); ClassScopePtrVec parents = ar->findClasses(toLower(base)); for (unsigned int j = 0; j < parents.size(); j++) { parents[j]->checkDerivation(ar, seen); } } seen.erase(m_name); }
int ClassScope::implementsArrayAccess(AnalysisResultPtr ar) { hphp_const_char_imap<int>::iterator it = m_implemented.find("arrayaccess"); if (it != m_implemented.end()) { return it->second; } int ret = 0; unsigned s = m_parent.empty() ? 0 : 1; for (unsigned i = s; i < m_bases.size(); i++) { if (strcasecmp(m_bases[i].c_str(), "arrayaccess")) { ret = 1; break; } } if (s && !ret) { int yes = 0, no = 0; const ClassScopePtrVec &classes = ar->findClasses(m_parent); BOOST_FOREACH(ClassScopePtr cls, classes) { int a = cls->implementsArrayAccess(ar); if (a < 0) { yes = no = 1; break; } if (a > 0) { yes++; } else { no++; } }