예제 #1
0
void ClosureExpression::initializeFromUseList(ExpressionListPtr vars) {
  m_vars = ExpressionListPtr(
    new ExpressionList(vars->getScope(), vars->getRange()));

  // Because PHP is insane you can have a use variable with the same
  // name as a param name.
  // In that case, params win (which is different than zend but much easier)
  auto seenBefore = collectParamNames();

  for (int i = vars->getCount() - 1; i >= 0; i--) {
    auto param = dynamic_pointer_cast<ParameterExpression>((*vars)[i]);
    assert(param);
    if (param->getName() == "this") {
      // "this" is automatically included.
      // Once we get rid of all the callsites, make this an error
      continue;
    }
    if (seenBefore.find(param->getName().c_str()) == seenBefore.end()) {
      seenBefore.insert(param->getName().c_str());
      m_vars->insertElement(param);
    }
  }

  initializeValuesFromVars();
}
예제 #2
0
void ClosureExpression::processLambda(AnalysisResultConstRawPtr ar) {
  if (m_captureState == CaptureState::Unknown) {
    assert(m_type == ClosureType::Short);
    auto const closureFuncScope = m_func->getFunctionScope();

    auto const paramNames = collectParamNames();
    auto const& mentioned = closureFuncScope->getLocals();

    std::set<std::string> toCapture;

    for (auto& m : mentioned) {
      if (paramNames.count(m)) continue;
      if (m == "this") {
        toCapture.insert("this");
        continue;
      }
      auto scope = closureFuncScope;
      do {
        auto const prev = scope;
        scope = prev->getOuterScope()->getContainingFunction();
        always_assert(scope);
        always_assert(!FileScope::getCurrent() ||
                      scope->getContainingFile() == FileScope::getCurrent());
        if (scope->hasLocal(m)) {
          toCapture.insert(m);
          break;
        }
      } while (scope->isLambdaClosure());
    }

    if (closureFuncScope->containsThis()) {
      toCapture.insert("this");
    }

    setCaptureList(ar, toCapture);
  }
}