void ReturnStatement::analyzeProgram(AnalysisResultPtr ar) {
  if (m_exp) {
    FunctionScopePtr funcScope = getFunctionScope();
    if (funcScope) {
      if (funcScope->isRefReturn()) {
        m_exp->setContext(Expression::RefValue);
      }
    }
    m_exp->analyzeProgram(ar);
  }
  if (ar->getPhase() == AnalysisResult::AnalyzeFinal) {
    if (m_exp) {
      TypePtr retType = m_exp->getCPPType();
      bool needsCheck = !retType->isPrimitive();
      if (m_exp->is(Expression::KindOfSimpleFunctionCall) ||
          m_exp->is(Expression::KindOfDynamicFunctionCall) ||
          m_exp->is(Expression::KindOfObjectMethodExpression)) {
        // return a value from another function call
        needsCheck = false;
      }
      ExpressionPtr tmp = m_exp;
      while (tmp &&
             (tmp->is(Expression::KindOfObjectPropertyExpression) ||
              tmp->is(Expression::KindOfArrayElementExpression))) {
        if (ObjectPropertyExpressionPtr opExp =
            dynamic_pointer_cast<ObjectPropertyExpression>(tmp)) {
          tmp = opExp->getObject();
        } else {
          ArrayElementExpressionPtr aeExp =
            dynamic_pointer_cast<ArrayElementExpression>(tmp);
          ASSERT(aeExp);
          tmp = aeExp->getVariable();
        }
      }
      if (SimpleVariablePtr svExp = dynamic_pointer_cast<SimpleVariable>(tmp)) {
        if (svExp->isThis()) {
          // returning something from $this
          needsCheck = false;
        } else {
          Symbol *sym = svExp->getSymbol();
          if (sym && sym->isParameter() && !sym->isLvalParam()) {
            // returning something from non-lval parameter
            needsCheck = false;
          }
        }
      }
      if (needsCheck) {
        FunctionScopePtr funcScope = getFunctionScope();
        if (funcScope) funcScope->setNeedsCheckMem();
      }
    }
  }
}
void ObjectPropertyExpression::analyzeProgram(AnalysisResultPtr ar) {
    m_object->analyzeProgram(ar);
    m_property->analyzeProgram(ar);
    if (ar->getPhase() == AnalysisResult::AnalyzeFinal) {
        if (!m_valid && m_context & (LValue|RefValue|DeepReference|UnsetContext)) {
            FunctionScopePtr func = getFunctionScope();
            if (func) func->setNeedsRefTemp();
        }
        if (getContext() & (RefValue | AssignmentLHS | OprLValue)) {
            FunctionScopePtr func = getFunctionScope();
            if (func) func->setNeedsCheckMem();
        }
    }
}
Exemplo n.º 3
0
void ParameterExpression::analyzeProgram(AnalysisResultPtr ar) {
  if (m_defaultValue) m_defaultValue->analyzeProgram(ar);

  if (ar->getPhase() == AnalysisResult::AnalyzeFinal) {
    if (!m_type.empty()) {
      addUserClass(ar, m_type);
    }
    // Have to use non const ref params for magic methods
    FunctionScopePtr fs = getFunctionScope();
    if (fs->isMagicMethod() || fs->getName() == "offsetget") {
      fs->getVariables()->addLvalParam(m_name);
    }
    if (m_ref) fs->setNeedsCheckMem();
  }
}
void ArrayElementExpression::analyzeProgram(AnalysisResultPtr ar) {
  m_variable->analyzeProgram(ar);
  if (m_offset) m_offset->analyzeProgram(ar);
  if (ar->getPhase() == AnalysisResult::AnalyzeFinal) {
    if (!m_global && (m_context & AccessContext) &&
        !(m_context & (LValue|RefValue|DeepReference|
                       UnsetContext|RefParameter|InvokeArgument))) {
      TypePtr type = m_variable->getActualType();
      if (!type ||
          (!type->is(Type::KindOfString) && !type->is(Type::KindOfArray))) {
        FunctionScopePtr scope = getFunctionScope();
        if (scope && !needsCSE()) scope->setNeedsRefTemp();
      }
    }
    if (m_global) {
      if (getContext() & (LValue|RefValue|DeepReference)) {
        setContext(NoLValueWrapper);
      } else if (!m_dynamicGlobal &&
          !(getContext() &
            (LValue|RefValue|RefParameter|DeepReference|
             UnsetContext|ExistContext))) {
        VariableTablePtr vars = ar->getVariables();
        Symbol *sym = vars->getSymbol(m_globalName);
        if (!sym || sym->getDeclaration().get() == this) {
          Compiler::Error(Compiler::UseUndeclaredGlobalVariable,
                          shared_from_this());
        }
      }
      FunctionScopePtr scope = getFunctionScope();
      if (scope) scope->setNeedsCheckMem();
    } else {
      TypePtr at(m_variable->getActualType());
      TypePtr et(m_variable->getExpectedType());
      if (et &&
          (et->is(Type::KindOfSequence) ||
           et->is(Type::KindOfAutoSequence)) &&
          at && at->isExactType()) {
        // since Sequence maps to Variant in the runtime,
        // using Sequence for the expected type will
        // never allow the necessary casts to be generated.
        m_variable->setExpectedType(at);
      }
    }
  }
}
Exemplo n.º 5
0
void FunctionCall::analyzeProgram(AnalysisResultPtr ar) {
  if (m_class) m_class->analyzeProgram(ar);
  if (m_nameExp) m_nameExp->analyzeProgram(ar);
  if (m_params) m_params->analyzeProgram(ar);
  if (ar->getPhase() == AnalysisResult::AnalyzeFinal) {
    if (m_funcScope && !m_arrayParams) {
      for (int i = 0, n = m_funcScope->getMaxParamCount(); i < n; ++i) {
        if (TypePtr specType = m_funcScope->getParamTypeSpec(i)) {
          const char *fmt = 0;
          string ptype;
          if (!m_params || m_params->getCount() <= i) {
            if (i >= m_funcScope->getMinParamCount()) break;
            fmt = "parameter %d of %s() requires %s, none given";
          } else {
            ExpressionPtr param = (*m_params)[i];
            if (!Type::Inferred(ar, param->getType(), specType)) {
              fmt = "parameter %d of %s() requires %s, called with %s";
            }
            ptype = param->getType()->toString();
          }
          if (fmt) {
            string msg;
            Util::string_printf
              (msg, fmt,
               i + 1,
               Util::escapeStringForCPP(m_funcScope->getOriginalName()).c_str(),
               specType->toString().c_str(), ptype.c_str());
            Compiler::Error(Compiler::BadArgumentType,
                            shared_from_this(), msg);
          }
        }
      }
    }
    if (getContext() & RefValue) {
      FunctionScopePtr fs = getFunctionScope();
      if (fs) fs->setNeedsCheckMem();
    }
  }
}
Exemplo n.º 6
0
void StaticStatement::analyzeProgramImpl(AnalysisResultPtr ar) {
  m_exp->analyzeProgram(ar);
  if (ar->getPhase() == AnalysisResult::AnalyzeAll) {
    BlockScopePtr scope = getScope();
    for (int i = 0; i < m_exp->getCount(); i++) {
      ExpressionPtr exp = (*m_exp)[i];
      ExpressionPtr variable;
      ExpressionPtr value;
      // turn static $a; into static $a = null;
      if (exp->is(Expression::KindOfSimpleVariable)) {
        variable = dynamic_pointer_cast<SimpleVariable>(exp);
        exp = AssignmentExpressionPtr
          (new AssignmentExpression(exp->getScope(), exp->getLocation(),
                                    Expression::KindOfAssignmentExpression,
                                    variable,
                                    CONSTANT("null"),
                                    false));
        (*m_exp)[i] = exp;
      }
      assert(exp->is(Expression::KindOfAssignmentExpression));
      AssignmentExpressionPtr assignment_exp =
        dynamic_pointer_cast<AssignmentExpression>(exp);
      variable = assignment_exp->getVariable();
      value = assignment_exp->getValue();
      SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(variable);
      // set the Declaration context here instead of all over this file - this phase
      // is the first to run
      var->setContext(Expression::Declaration);
      Symbol *sym = var->getSymbol();
      sym->setStaticInitVal(value);
    }
  } else if (ar->getPhase() == AnalysisResult::AnalyzeFinal) {
    FunctionScopePtr fs = getFunctionScope();
    if (fs) fs->setNeedsCheckMem();
  }
}
void SimpleVariable::analyzeProgram(AnalysisResultPtr ar) {
  m_superGlobal = BuiltinSymbols::IsSuperGlobal(m_name);
  m_superGlobalType = BuiltinSymbols::GetSuperGlobalType(m_name);

  VariableTablePtr variables = getScope()->getVariables();
  if (m_superGlobal) {
    variables->setAttribute(VariableTable::NeedGlobalPointer);
  } else if (m_name == "GLOBALS") {
    m_globals = true;
  } else {
    m_sym = variables->addDeclaredSymbol(
      m_name, hhvm && Option::OutputHHBC ?
      shared_from_this() : ConstructPtr());
  }

  if (ar->getPhase() == AnalysisResult::AnalyzeAll) {
    if (FunctionScopePtr func = getFunctionScope()) {
      if (m_name == "this" && (func->inPseudoMain() || getClassScope())) {
        func->setContainsThis();
        m_this = true;
        if (!hasContext(ObjectContext)) {
          bool unset = hasAllContext(UnsetContext | LValue);
          func->setContainsBareThis(
            true,
            hasAnyContext(RefValue | RefAssignmentLHS) ||
            m_sym->isRefClosureVar() || unset);
          if (variables->getAttribute(VariableTable::ContainsDynamicVariable)) {
            ClassScopePtr cls = getClassScope();
            TypePtr t = !cls || cls->isRedeclaring() ?
              Type::Variant : Type::CreateObjectType(cls->getName());
            variables->add(m_sym, t, true, ar, shared_from_this(),
                           getScope()->getModifiers());
          }
        }
      }
      if (m_sym && !(m_context & AssignmentLHS) &&
          !((m_context & UnsetContext) && (m_context & LValue))) {
        m_sym->setUsed();
      }
    }
  } else if (ar->getPhase() == AnalysisResult::AnalyzeFinal) {
    if (m_sym) {
      if (!m_sym->isSystem() &&
          !(getContext() &
            (LValue|RefValue|RefParameter|UnsetContext|ExistContext)) &&
          m_sym->getDeclaration().get() == this &&
          !variables->getAttribute(VariableTable::ContainsLDynamicVariable) &&
          !getScope()->is(BlockScope::ClassScope)) {
        if (getScope()->inPseudoMain()) {
          Compiler::Error(Compiler::UseUndeclaredGlobalVariable,
                          shared_from_this());
        } else if (!m_sym->isClosureVar()) {
          Compiler::Error(Compiler::UseUndeclaredVariable, shared_from_this());
        }
      }
      // check function parameter that can occur in lval context
      if (m_sym->isParameter() &&
          m_context & (LValue | RefValue | DeepReference |
                       UnsetContext | InvokeArgument | OprLValue |
                       DeepOprLValue)) {
        m_sym->setLvalParam();
      }
    }
    if (m_superGlobal || m_name == "GLOBALS") {
      FunctionScopePtr func = getFunctionScope();
      if (func) func->setNeedsCheckMem();
    }
  }
}