예제 #1
0
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;
}
예제 #2
0
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;
}
예제 #3
0
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);
}
예제 #4
0
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;
}
예제 #5
0
// 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;
        }
      }
    }
  }
}
예제 #6
0
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();
}
예제 #7
0
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;
}