Exemplo n.º 1
0
const Func* lookupImmutableMethod(const Class* cls, const StringData* name,
                                  bool& magicCall, bool staticLookup,
                                  const Func* ctxFunc,
                                  bool exactClass) {
  if (!cls) return nullptr;
  if (cls->attrs() & AttrInterface) return nullptr;
  auto ctx = ctxFunc->cls();
  const Func* func;
  LookupResult res = staticLookup ?
    lookupClsMethod(func, cls, name, nullptr, ctx, false) :
    lookupObjMethod(func, cls, name, ctx, false);

  if (res == LookupResult::MethodNotFound) return nullptr;

  if (func->isAbstract() && exactClass) return nullptr;

  assertx(res == LookupResult::MethodFoundWithThis ||
          res == LookupResult::MethodFoundNoThis ||
          (staticLookup ?
           res == LookupResult::MagicCallStaticFound :
           res == LookupResult::MagicCallFound));

  magicCall =
    res == LookupResult::MagicCallStaticFound ||
    res == LookupResult::MagicCallFound;

  if (staticLookup) {
    if (magicCall) {
      if (ctx && !ctxFunc->isStatic() &&
          (ctx->classof(cls) || cls->classof(ctx))) {
        // we might need to call __call instead
        return nullptr;
      }
      if (!exactClass && !(cls->attrs() & AttrNoOverride)) {
        // there might be a derived class which defines the method
        return nullptr;
      }
    }
  } else if (!exactClass && !(func->attrs() & AttrPrivate)) {
    if (magicCall) {
      if (!(cls->attrs() & AttrNoOverride)) {
        return nullptr;
      }
    }
  }
  return func;
}
Exemplo n.º 2
0
void lookupClsMethodHelper(Class* cls, StringData* meth,
                           ActRec* ar, ActRec* fp) {
  try {
    const Func* f;
    auto const ctx = fp->m_func->cls();
    auto const obj = ctx && fp->hasThis() ? fp->getThis() : nullptr;
    auto const res = lookupClsMethod(f, cls, meth, obj, ctx, true);

    ar->m_func = f;

    if (res == LookupResult::MethodFoundNoThis ||
        res == LookupResult::MagicCallStaticFound) {
      if (!f->isStaticInPrologue()) {
        raise_missing_this(f);
      }
      if (forward && ctx) {
        if (fp->hasThis()) {
          cls = fp->getThis()->getVMClass();
        } else {
          cls = fp->getClass();
        }
      }
      ar->setClass(cls);
    } else {
      assertx(obj);
      assertx(res == LookupResult::MethodFoundWithThis ||
              res == LookupResult::MagicCallFound);
      obj->incRefCount();
      ar->setThis(obj);
    }

    if (res == LookupResult::MagicCallFound ||
        res == LookupResult::MagicCallStaticFound) {
      ar->setMagicDispatch(meth);
      meth->incRefCount();
    }
  } catch (...) {
    *arPreliveOverwriteCells(ar) = make_tv<KindOfString>(meth);
    throw;
  }
}