Example #1
0
void GlobalStatement::outputCPP(CodeGenerator &cg, AnalysisResultPtr ar) {
  if (m_dynamicGlobal) {
    cg.printf("throw_fatal(\"dynamic global\");\n");
  } else if (!ar->getScope()->inPseudoMain() || !isTopLevel()) {
    BlockScopePtr scope = ar->getScope();
    if (m_exp->getCount() > 1) cg.indentBegin("{\n");
    for (int i = 0; i < m_exp->getCount(); i++) {
      ExpressionPtr exp = (*m_exp)[i];
      if (exp->is(Expression::KindOfSimpleVariable)) {
        SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(exp);
        const string &name = var->getName();
        VariableTablePtr variables = scope->getVariables();
        if (variables->needLocalCopy(name)) {
          cg.printf("%s%s = ref(g->%s);\n",
                    Option::VariablePrefix, name.c_str(),
                    variables->getGlobalVariableName(ar, name).c_str());
        }
      }
      else {
        // type inference should have set m_dynamicGlobal to true.
        ASSERT(false);
      }
    }
    if (m_exp->getCount() > 1) cg.indentEnd("}\n");
  }
}
void ArrayElementExpression::setContext(Context context) {
  m_context |= context;
  switch (context) {
    case Expression::LValue:
      if (!hasContext(Expression::UnsetContext)) {
        m_variable->setContext(Expression::LValue);
      }
      if (m_variable->is(Expression::KindOfObjectPropertyExpression)) {
        m_variable->clearContext(Expression::NoLValueWrapper);
      }
      // special case for $GLOBALS[], see the if (m_global) check in
      // ArrayElementExpression::outputCPPImpl, we do not need lvalue wrapper
      if (m_variable->is(Expression::KindOfSimpleVariable)) {
        SimpleVariablePtr var =
          dynamic_pointer_cast<SimpleVariable>(m_variable);
        if (var->getName() == "GLOBALS") {
          m_context |= Expression::NoLValueWrapper;
        }
      }
      break;
    case Expression::DeepAssignmentLHS:
    case Expression::DeepOprLValue:
    case Expression::ExistContext:
    case Expression::UnsetContext:
    case Expression::DeepReference:
      m_variable->setContext(context);
      break;
    case Expression::RefValue:
    case Expression::RefParameter:
      m_variable->setContext(DeepReference);
      break;
    default:
      break;
  }
}
void GlobalStatement::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) {
  BlockScopePtr scope = getScope();
  if (m_exp->getCount() > 1) cg_indentBegin("{\n");
  for (int i = 0; i < m_exp->getCount(); i++) {
    ExpressionPtr exp = (*m_exp)[i];
    if (exp->is(Expression::KindOfSimpleVariable)) {
      SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(exp);
      const string &name = var->getName();
      VariableTablePtr variables = scope->getVariables();
      if (variables->needLocalCopy(name)) {
        cg_printf("%s%s = ref(g->%s);\n",
                  Option::VariablePrefix, name.c_str(),
                  variables->getGlobalVariableName(cg, ar, name).c_str());
      }
    } else if (exp->is(Expression::KindOfDynamicVariable)) {
      DynamicVariablePtr var = dynamic_pointer_cast<DynamicVariable>(exp);
      ExpressionPtr exp = var->getSubExpression();
      exp->outputCPPBegin(cg, ar);
      int id = cg.createNewLocalId(shared_from_this());
      cg_printf("CStrRef dgv_%d((", id);
      exp->outputCPP(cg, ar);
      cg_printf("));\n");
      cg_printf("variables->get(dgv_%d) = ref(g->get(dgv_%d));\n", id, id);
      exp->outputCPPEnd(cg, ar);
    } else {
      assert(false);
    }
  }
  if (m_exp->getCount() > 1) cg_indentEnd("}\n");
}
void SwitchStatement::analyzeProgramImpl(AnalysisResultPtr ar) {
  m_exp->analyzeProgram(ar);
  if (m_cases) m_cases->analyzeProgram(ar);

  if (ar->getPhase() == AnalysisResult::AnalyzeAll &&
      m_exp->is(Expression::KindOfSimpleVariable)) {
    SimpleVariablePtr exp = dynamic_pointer_cast<SimpleVariable>(m_exp);
    if (exp && exp->getSymbol() && exp->getSymbol()->isClassName()) {
      // Mark some classes as volitle since the name is used in switch
      for (int i = 0; i < m_cases->getCount(); i++) {
        CaseStatementPtr stmt =
          dynamic_pointer_cast<CaseStatement>((*m_cases)[i]);
        ASSERT(stmt);
        ExpressionPtr caseCond = stmt->getCondition();
        if (caseCond && caseCond->isScalar()) {
          ScalarExpressionPtr name =
            dynamic_pointer_cast<ScalarExpression>(caseCond);
          if (name && name->isLiteralString()) {
            string className = name->getLiteralString();
            ClassScopePtr cls = ar->findClass(Util::toLower(className));
            if (cls && cls->isUserClass()) {
              cls->setVolatile();
            }
          }
        }
      }
      // Also note this down as code error
      ConstructPtr self = shared_from_this();
      Compiler::Error(Compiler::ConditionalClassLoading, self);
    }
  }
}
ArrayElementExpression::ArrayElementExpression
(EXPRESSION_CONSTRUCTOR_PARAMETERS,
 ExpressionPtr variable, ExpressionPtr offset)
  : Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES),
    m_variable(variable), m_offset(offset), m_global(false),
    m_dynamicGlobal(false), m_localEffects(AccessorEffect) {
  m_variable->setContext(Expression::AccessContext);

  if (m_variable->is(Expression::KindOfSimpleVariable)) {
    SimpleVariablePtr var =
      dynamic_pointer_cast<SimpleVariable>(m_variable);
    if (var->getName() == "GLOBALS") {
      m_global = true;
      m_dynamicGlobal = true;
      if (m_offset && m_offset->is(Expression::KindOfScalarExpression)) {
        ScalarExpressionPtr offset =
          dynamic_pointer_cast<ScalarExpression>(m_offset);

        if (offset->isLiteralString()) {
          m_globalName = offset->getIdentifier();
          if (!m_globalName.empty()) {
            m_dynamicGlobal = false;
          }
        }
      }
    }
  }
}
void StaticStatement::analyzeProgram(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(),
                                    variable,
                                    CONSTANT("null"),
                                    false));
        (*m_exp)[i] = exp;
      }
      always_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);
    }
  }
}
void AssignmentExpression::onParseRecur(AnalysisResultConstPtr ar,
                                        ClassScopePtr scope) {
  // This is that much we can do during parse phase.
  TypePtr type;
  if (m_value->is(Expression::KindOfScalarExpression)) {
    type = static_pointer_cast<ScalarExpression>(m_value)->inferenceImpl(
      ar, Type::Some, false);
  } else if (m_value->is(Expression::KindOfUnaryOpExpression)) {
    UnaryOpExpressionPtr uexp =
      dynamic_pointer_cast<UnaryOpExpression>(m_value);
    if (uexp->getOp() == T_ARRAY) {
      type = Type::Array;
    }
  }
  if (!type) type = Type::Some;

  if (m_variable->is(Expression::KindOfConstantExpression)) {
    // ...as in ClassConstant statement
    // We are handling this one here, not in ClassConstant, purely because
    // we need "value" to store in constant table.
    ConstantExpressionPtr exp =
      dynamic_pointer_cast<ConstantExpression>(m_variable);
    scope->getConstants()->add(exp->getName(), type, m_value, ar, m_variable);
  } else if (m_variable->is(Expression::KindOfSimpleVariable)) {
    SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(m_variable);
    scope->getVariables()->add(var->getName(), type, true, ar,
                               shared_from_this(), scope->getModifiers());
    var->clearContext(Declaration); // to avoid wrong CodeError
  } else {
    ASSERT(false); // parse phase shouldn't handle anything else
  }
}
Example #8
0
void ClassVariable::inferTypes(AnalysisResultPtr ar) {
  ASSERT(getScope().get() == getClassScope().get());
  IMPLEMENT_INFER_AND_CHECK_ASSERT(getScope());

  m_declaration->inferAndCheck(ar, Type::Variant, false);

  if (m_modifiers->isStatic()) {
    ClassScopePtr scope = getClassScope();
    for (int i = 0; i < m_declaration->getCount(); i++) {
      ExpressionPtr exp = (*m_declaration)[i];
      if (exp->is(Expression::KindOfAssignmentExpression)) {
        AssignmentExpressionPtr assignment =
          dynamic_pointer_cast<AssignmentExpression>(exp);
        // If the class variable's type is Object, we have to
        // force it to be a Variant, because we don't include
        // the class header files in global_variables.h
        SimpleVariablePtr var =
          dynamic_pointer_cast<SimpleVariable>(assignment->getVariable());
        if (var) {
          TypePtr type = scope->getVariables()->getFinalType(var->getName());
          if (type->is(Type::KindOfObject)) {
            scope->getVariables()->forceVariant(ar, var->getName(),
                                                VariableTable::AnyVars);
          }
        }
        ExpressionPtr value = assignment->getValue();
        if (value->containsDynamicConstant(ar)) {
          scope->getVariables()->
            setAttribute(VariableTable::ContainsDynamicStatic);
        }
      }
    }
  }
}
Example #9
0
void GlobalStatement::inferTypes(AnalysisResultPtr ar) {
  IMPLEMENT_INFER_AND_CHECK_ASSERT(getScope());

  BlockScopePtr scope = getScope();
  for (int i = 0; i < m_exp->getCount(); i++) {
    ExpressionPtr exp = (*m_exp)[i];
    VariableTablePtr variables = scope->getVariables();
    variables->setAttribute(VariableTable::NeedGlobalPointer);
    if (exp->is(Expression::KindOfSimpleVariable)) {
      SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(exp);
      const std::string &name = var->getName();
      /* If we have already seen this variable in the current scope and
         it is not a global variable, record this variable as "redeclared"
         which will force Variant type.
       */
      variables->setAttribute(VariableTable::InsideGlobalStatement);
      variables->checkRedeclared(name, KindOfGlobalStatement);
      variables->addLocalGlobal(name);
      var->setContext(Expression::Declaration);
      var->inferAndCheck(ar, Type::Any, true);
      variables->forceVariant(ar, name, VariableTable::AnyVars);
      variables->clearAttribute(VariableTable::InsideGlobalStatement);
    } else {
      variables->forceVariants(ar, VariableTable::AnyVars);
      variables->setAttribute(VariableTable::ContainsLDynamicVariable);
      assert(exp->is(Expression::KindOfDynamicVariable));
      exp->inferAndCheck(ar, Type::Any, true);
    }
  }
}
TypePtr AssignmentExpression::
inferTypesImpl(AnalysisResultPtr ar, TypePtr type, bool coerce,
               ExpressionPtr variable,
               ExpressionPtr value /* = ExpressionPtr() */) {
  TypePtr ret = type;
  if (value) {
    if (coerce) {
      ret = value->inferAndCheck(ar, type, coerce);
    } else {
      ret = value->inferAndCheck(ar, NEW_TYPE(Some), coerce);
    }
  }

  BlockScopePtr scope = ar->getScope();
  if (variable->is(Expression::KindOfConstantExpression)) {
    // ...as in ClassConstant statement
    ConstantExpressionPtr exp =
      dynamic_pointer_cast<ConstantExpression>(variable);
    bool p;
    scope->getConstants()->check(exp->getName(), ret, true, ar, variable, p);
  } else if (variable->is(Expression::KindOfDynamicVariable)) {
    // simptodo: not too sure about this
    ar->getFileScope()->setAttribute(FileScope::ContainsLDynamicVariable);
  } else if (variable->is(Expression::KindOfSimpleVariable)) {
    SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(variable);
    if (var->getName() == "this" && ar->getClassScope()) {
      if (ar->isFirstPass()) {
        ar->getCodeError()->record(variable, CodeError::ReassignThis,
                                   variable);
      }
    }
    if (ar->getPhase() == AnalysisResult::LastInference && value) {
      if (!value->getExpectedType()) {
        value->setExpectedType(variable->getActualType());
      }
    }
  }
  // if the value may involve object, consider the variable as "referenced"
  // so that objects are not destructed prematurely.
  bool referenced = true;
  if (value && value->isScalar()) referenced = false;
  if (ret && ret->isNoObjectInvolved()) referenced = false;
  if (referenced && variable->is(Expression::KindOfSimpleVariable)) {
    SimpleVariablePtr var =
      dynamic_pointer_cast<SimpleVariable>(variable);
    const std::string &name = var->getName();
    VariableTablePtr variables = ar->getScope()->getVariables();
    variables->addReferenced(name);
  }

  TypePtr vt = variable->inferAndCheck(ar, ret, true);
  if (!coerce && type->is(Type::KindOfAny)) {
    ret = vt;
  }

  return ret;
}
void ExpressionList::optimize(AnalysisResultConstPtr ar) {
  bool changed = false;
  size_t i = m_exps.size();
  if (m_kind != ListKindParam) {
    size_t skip = m_kind == ListKindLeft ? 0 : i - 1;
    while (i--) {
      if (i != skip) {
        ExpressionPtr &e = m_exps[i];
        if (!e || e->getContainedEffects() == NoEffect) {
          removeElement(i);
          changed = true;
        } else if (e->is(KindOfExpressionList)) {
          ExpressionListPtr el(static_pointer_cast<ExpressionList>(e));
          removeElement(i);
          for (size_t j = el->getCount(); j--; ) {
            insertElement((*el)[j], i);
          }
          changed = true;
        } else if (e->getLocalEffects() == NoEffect) {
          e = e->unneeded();
          // changed already handled by unneeded
        }
      }
    }
    if (m_exps.size() == 1) {
      m_kind = ListKindWrapped;
    } else if (m_kind == ListKindLeft && m_exps[0]->isScalar()) {
      ExpressionPtr e = m_exps[0];
      removeElement(0);
      addElement(e);
      m_kind = ListKindWrapped;
    }
  } else {
    if (hasContext(UnsetContext) &&
        ar->getPhase() >= AnalysisResult::PostOptimize) {
      while (i--) {
        ExpressionPtr &e = m_exps[i];
        if (e->is(Expression::KindOfSimpleVariable)) {
          SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(e);
          if (var->checkUnused()) {
            const std::string &name = var->getName();
            VariableTablePtr variables = getScope()->getVariables();
            if (!variables->isNeeded(name)) {
              removeElement(i);
              changed = true;
            }
          }
        }
      }
    }
  }
  if (changed) {
    getScope()->addUpdates(BlockScope::UseKindCaller);
  }
}
static const char *stringBufferPrefix(AnalysisResultPtr ar, ExpressionPtr var) {
  if (var->is(Expression::KindOfSimpleVariable)) {
    if (LoopStatementPtr loop = ar->getLoopStatement()) {
      SimpleVariablePtr sv = static_pointer_cast<SimpleVariable>(var);
      if (loop->checkStringBuf(sv->getName())) {
        return ar->getScope()->getVariables()->
          getVariablePrefix(ar, sv->getName());
      }
    }
  }
  return 0;
}
Example #13
0
StatementPtr StaticStatement::preOptimize(AnalysisResultConstPtr ar) {
  BlockScopePtr scope = getScope();
  for (int i = 0; i < m_exp->getCount(); i++) {
    ExpressionPtr exp = (*m_exp)[i];
    AssignmentExpressionPtr assignment_exp =
      dynamic_pointer_cast<AssignmentExpression>(exp);
    ExpressionPtr variable = assignment_exp->getVariable();
    ExpressionPtr value = assignment_exp->getValue();
    SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(variable);
    Symbol *sym = var->getSymbol();
    sym->setStaticInitVal(value);
  }
  return StatementPtr();
}
ExpressionPtr AssignmentExpression::optimize(AnalysisResultConstPtr ar) {
  if (m_variable->is(Expression::KindOfSimpleVariable)) {
    SimpleVariablePtr var =
      dynamic_pointer_cast<SimpleVariable>(m_variable);
    if (var->checkUnused() &&
        !CheckNeeded(var, m_value)) {
      if (m_value->getContainedEffects() != getContainedEffects()) {
        recomputeEffects();
      }
      return replaceValue(m_value);
    }
  }
  return ExpressionPtr();
}
Example #15
0
void StaticStatement::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) {
  BlockScopePtr scope = getScope();
  if (scope->inPseudoMain()) {
    if (m_exp->getCount() > 1) cg_indentBegin("{\n");
    for (int i = 0; i < m_exp->getCount(); i++) {
      ExpressionPtr exp = (*m_exp)[i];
      if (exp->is(Expression::KindOfAssignmentExpression)) {
        exp->outputCPP(cg, ar);
        cg_printf(";\n");
      } else {
        ASSERT(false);
      }
    }
    if (m_exp->getCount() > 1) cg_indentEnd("}\n");
    return;
  }

  VariableTablePtr variables = scope->getVariables();
  if (m_exp->getCount() > 1) cg_indentBegin("{\n");
  for (int i = 0; i < m_exp->getCount(); i++) {
    ExpressionPtr exp = (*m_exp)[i];
    if (exp->is(Expression::KindOfAssignmentExpression)) {
      AssignmentExpressionPtr assignment_exp =
        dynamic_pointer_cast<AssignmentExpression>(exp);
      ExpressionPtr variable = assignment_exp->getVariable();
      SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(variable);
      assert(var->hasContext(Expression::Declaration));
      const std::string &name = var->getName();

      if (variables->needLocalCopy(name)) {
        ASSERT(var->hasAssignableCPPVariable());
        cg_printf("%s.assignRef(%s%s);\n",
                  var->getAssignableCPPVariable(ar).c_str(),
                  Option::StaticVariablePrefix, name.c_str());
      }

      cg_indentBegin("if (!%s%s%s) {\n", Option::InitPrefix,
                     Option::StaticVariablePrefix, name.c_str());
      exp->outputCPP(cg, ar);
      cg_printf(";\n");
      cg_printf("%s%s%s = true;\n", Option::InitPrefix,
                Option::StaticVariablePrefix, name.c_str());
      cg_indentEnd("}\n");
    } else {
      ASSERT(false);
    }
  }
  if (m_exp->getCount() > 1) cg_indentEnd("}\n");
}
Example #16
0
StatementPtr ClassVariable::preOptimize(AnalysisResultConstPtr ar) {
  ClassScopePtr scope = getClassScope();
  for (int i = 0; i < m_declaration->getCount(); i++) {
    ExpressionPtr exp = (*m_declaration)[i];
    if (exp->is(Expression::KindOfAssignmentExpression)) {
      AssignmentExpressionPtr assignment =
        dynamic_pointer_cast<AssignmentExpression>(exp);
      SimpleVariablePtr var =
        dynamic_pointer_cast<SimpleVariable>(assignment->getVariable());
      ExpressionPtr value = assignment->getValue();
      scope->getVariables()->setClassInitVal(var->getName(), value);
    }
  }
  return StatementPtr();
}
void StaticStatement::analyzeProgramImpl(AnalysisResultPtr ar) {
  m_exp->analyzeProgram(ar);
  BlockScopePtr scope = ar->getScope();
  for (int i = 0; i < m_exp->getCount(); i++) {
    ExpressionPtr exp = (*m_exp)[i];
    ExpressionPtr variable;
    ExpressionPtr value;
    if (ar->getPhase() == AnalysisResult::AnalyzeInclude) {
      // turn static $a; into static $a = null;
      if (exp->is(Expression::KindOfSimpleVariable)) {
        variable = dynamic_pointer_cast<SimpleVariable>(exp);
        exp = AssignmentExpressionPtr
          (new AssignmentExpression(exp->getLocation(),
                                    Expression::KindOfAssignmentExpression,
                                    variable,
                                    CONSTANT("null"),
                                    false));
        (*m_exp)[i] = exp;
      }
    }
    if (exp->is(Expression::KindOfAssignmentExpression)) {
      AssignmentExpressionPtr assignment_exp =
        dynamic_pointer_cast<AssignmentExpression>(exp);
      variable = assignment_exp->getVariable();
      value = assignment_exp->getValue();
    } else {
      ASSERT(false);
    }
    SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(variable);
    if (ar->getPhase() == AnalysisResult::AnalyzeInclude) {
      if (scope->getVariables()->setStaticInitVal(var->getName(), value)) {
        ar->getCodeError()->record(CodeError::DeclaredStaticVariableTwice,
                                   exp);
      }
    } else if (ar->getPhase() == AnalysisResult::AnalyzeAll) {
      // update initial value
      const string &name = var->getName();
      ExpressionPtr initValue =
        (dynamic_pointer_cast<Expression>
          (scope->getVariables()->getStaticInitVal(name)))->clone();
      exp = AssignmentExpressionPtr
        (new AssignmentExpression(exp->getLocation(),
                                  Expression::KindOfAssignmentExpression,
                                  variable, initValue, false));
      (*m_exp)[i] = exp;
    }
  }
}
Example #18
0
void ClassVariable::analyzeProgramImpl(AnalysisResultPtr ar) {
  m_declaration->analyzeProgram(ar);
  if (ar->getPhase() != AnalysisResult::AnalyzeInclude) return;
  ClassScopePtr scope = ar->getClassScope();
  for (int i = 0; i < m_declaration->getCount(); i++) {
    ExpressionPtr exp = (*m_declaration)[i];
    if (exp->is(Expression::KindOfAssignmentExpression)) {
      AssignmentExpressionPtr assignment =
        dynamic_pointer_cast<AssignmentExpression>(exp);
      SimpleVariablePtr var =
        dynamic_pointer_cast<SimpleVariable>(assignment->getVariable());
      ExpressionPtr value = assignment->getValue();
      scope->getVariables()->setClassInitVal(var->getName(), value);
    }
  }
}
Example #19
0
void ClassVariable::getCtorAndInitInfo(
    ExpressionPtr exp,
    bool &needsCppCtor,
    bool &needsInit,
    SimpleVariablePtr &var,
    TypePtr &type,
    Symbol *&sym,
    ExpressionPtr &value) {

  ClassScopePtr scope = getClassScope();
  bool derivFromRedec = scope->derivesFromRedeclaring() &&
    !m_modifiers->isPrivate();
  AssignmentExpressionPtr assignment;
  bool isAssign = exp->is(Expression::KindOfAssignmentExpression);
  if (isAssign) {
    assignment = static_pointer_cast<AssignmentExpression>(exp);
    var = dynamic_pointer_cast<SimpleVariable>(assignment->getVariable());
    ASSERT(var);
    value = assignment->getValue();
    ASSERT(value);
  } else {
    var = dynamic_pointer_cast<SimpleVariable>(exp);
    ASSERT(var);
  }
  sym = scope->getVariables()->getSymbol(var->getName());
  ASSERT(sym);
  type = scope->getVariables()->getFinalType(var->getName());
  ASSERT(type);

  bool isValueNull = isAssign ? value->isLiteralNull() : false;
  bool typeIsInitable = type->is(Type::KindOfVariant) ||
                        type->getCPPInitializer();
  if (!derivFromRedec &&
      !sym->isOverride() &&
      (isAssign ?
        (isValueNull ||
         (value->is(Expression::KindOfScalarExpression) &&
          type->isPrimitive())) :
        typeIsInitable)) {
    needsCppCtor = true;
  } else if (isAssign || typeIsInitable) {
    // if we aren't an assignment and the type is not a variant
    // w/ no CPP initializer, then we currently don't bother
    // to initialize it in init().
    needsInit = true;
  }
}
Example #20
0
/**
 * If a simple variable refers to a name bound inside the query
 * then leave it alone. If not, rewrite it to be reference to
 * a query parameter.
 */
SimpleVariablePtr CaptureExtractor::rewriteSimpleVariable(
  SimpleVariablePtr sv) {
  assert(sv != nullptr);
  auto varName = sv->getName();
  for (auto &boundVar : m_boundVars) {
    if (varName == boundVar) return sv;
  }
  return newQueryParamRef(sv);
}
ExpressionPtr AssignmentExpression::postOptimize(AnalysisResultPtr ar) {
  ar->postOptimize(m_variable);
  ar->postOptimize(m_value);
  if (m_variable->is(Expression::KindOfSimpleVariable)) {
    SimpleVariablePtr var =
      dynamic_pointer_cast<SimpleVariable>(m_variable);
    const std::string &name = var->getName();
    VariableTablePtr variables = ar->getScope()->getVariables();
    if (variables->checkUnused(name)) {
      variables->addUnused(name);
      if (m_value->getContainedEffects() != getContainedEffects()) {
        s_effectsTag++;
      }
      return m_value;
    }
  }
  return ExpressionPtr();
}
Example #22
0
bool Expression::CheckNeeded(ExpressionPtr variable, ExpressionPtr value) {
  // if the value may involve object, consider the variable as "needed"
  // so that objects are not destructed prematurely.
  bool needed = true;
  if (value) needed = CheckNeededRHS(value);
  if (variable->is(Expression::KindOfSimpleVariable)) {
    SimpleVariablePtr var =
      dynamic_pointer_cast<SimpleVariable>(variable);
    const std::string &name = var->getName();
    VariableTablePtr variables = var->getScope()->getVariables();
    if (needed) {
      variables->addNeeded(name);
    } else {
      needed = variables->isNeeded(name);
    }
  }
  return needed;
}
Example #23
0
void ClassVariable::addTraitPropsToScope(AnalysisResultPtr ar,
                                         ClassScopePtr scope) {
  ModifierExpressionPtr modifiers = scope->setModifiers(m_modifiers);
  VariableTablePtr variables = scope->getVariables();

  for (int i = 0; i < m_declaration->getCount(); i++) {
    ExpressionPtr exp = (*m_declaration)[i];

    SimpleVariablePtr var;
    ExpressionPtr value;
    if (exp->is(Expression::KindOfAssignmentExpression)) {
      AssignmentExpressionPtr assignment =
        dynamic_pointer_cast<AssignmentExpression>(exp);
      var = dynamic_pointer_cast<SimpleVariable>(assignment->getVariable());
      value = assignment->getValue();
    } else {
      var = dynamic_pointer_cast<SimpleVariable>(exp);
      value = makeConstant(ar, "null");
    }

    const string &name = var->getName();
    Symbol *sym;
    ClassScopePtr prevScope = variables->isPresent(name) ? scope :
      scope->getVariables()->findParent(ar, name, sym);

    if (prevScope &&
        !isEquivRedecl(name, exp, m_modifiers,
                       prevScope->getVariables()->getSymbol(name))) {
      Compiler::Error(Compiler::DeclaredVariableTwice, exp);
      m_declaration->removeElement(i--);
    } else {
      if (prevScope != scope) { // Property is new or override, so add it
        variables->add(name, Type::Variant, false, ar, exp, m_modifiers);
        variables->getSymbol(name)->setValue(exp);
        variables->setClassInitVal(name, value);
        variables->markOverride(ar, name);
      } else {
        m_declaration->removeElement(i--);
      }
    }
  }
  scope->setModifiers(modifiers);
}
void AssignmentExpression::analyzeProgram(AnalysisResultPtr ar) {
  m_variable->analyzeProgram(ar);
  m_value->analyzeProgram(ar);
  if (ar->getPhase() == AnalysisResult::AnalyzeAll) {
    if (m_ref && m_variable->is(Expression::KindOfSimpleVariable)) {
      SimpleVariablePtr var =
        dynamic_pointer_cast<SimpleVariable>(m_variable);
      const std::string &name = var->getName();
      VariableTablePtr variables = ar->getScope()->getVariables();
      variables->addUsed(name);
    }
    if (m_variable->is(Expression::KindOfConstantExpression)) {
      ConstantExpressionPtr exp =
        dynamic_pointer_cast<ConstantExpression>(m_variable);
      if (!m_value->isScalar()) {
        ar->getScope()->getConstants()->setDynamic(ar, exp->getName());
      }
    }
  }
}
Example #25
0
void ClassVariable::analyzeProgram(AnalysisResultPtr ar) {
  m_declaration->analyzeProgram(ar);
  AnalysisResult::Phase phase = ar->getPhase();
  if (phase != AnalysisResult::AnalyzeAll) {
    return;
  }
  if (m_modifiers->isAbstract()) {
    Compiler::Error(Compiler::AbstractProperty, shared_from_this());
  }
  ClassScopePtr scope = getClassScope();
  for (int i = 0; i < m_declaration->getCount(); i++) {
    ExpressionPtr exp = (*m_declaration)[i];
    bool error;
    if (exp->is(Expression::KindOfAssignmentExpression)) {
      AssignmentExpressionPtr assignment =
        dynamic_pointer_cast<AssignmentExpression>(exp);
      SimpleVariablePtr var =
        dynamic_pointer_cast<SimpleVariable>(assignment->getVariable());
      ExpressionPtr value = assignment->getValue();
      scope->getVariables()->setClassInitVal(var->getName(), value);
      error = scope->getVariables()->markOverride(ar, var->getName());
    } else {
      SimpleVariablePtr var =
        dynamic_pointer_cast<SimpleVariable>(exp);
      error = scope->getVariables()->markOverride(ar, var->getName());
      scope->getVariables()->setClassInitVal(var->getName(),
                                             makeConstant(ar, "null"));
    }
    if (error) {
      Compiler::Error(Compiler::InvalidOverride, exp);
    }
  }
}
Example #26
0
void ClassVariable::analyzeProgramImpl(AnalysisResultPtr ar) {
  m_declaration->analyzeProgram(ar);
  AnalysisResult::Phase phase = ar->getPhase();
  if (phase != AnalysisResult::AnalyzeAll) {
    return;
  }
  ClassScopePtr scope = getClassScope();
  for (int i = 0; i < m_declaration->getCount(); i++) {
    ExpressionPtr exp = (*m_declaration)[i];
    if (exp->is(Expression::KindOfAssignmentExpression)) {
      AssignmentExpressionPtr assignment =
        dynamic_pointer_cast<AssignmentExpression>(exp);
      SimpleVariablePtr var =
        dynamic_pointer_cast<SimpleVariable>(assignment->getVariable());
      ExpressionPtr value = assignment->getValue();
      scope->getVariables()->setClassInitVal(var->getName(), value);
      scope->getVariables()->markOverride(ar, var->getName());
    } else {
      SimpleVariablePtr var =
        dynamic_pointer_cast<SimpleVariable>(exp);
      scope->getVariables()->markOverride(ar, var->getName());
      scope->getVariables()->setClassInitVal(var->getName(),
                                             makeConstant(ar, "null"));
    }
  }
}
void ArrayElementExpression::setContext(Context context) {
  m_context |= context;
  if (context == Expression::LValue) {
    m_variable->setContext(Expression::LValue);
    if (m_variable->is(Expression::KindOfObjectPropertyExpression)) {
      m_variable->clearContext(Expression::NoLValueWrapper);
    }
    // special case for $GLOBALS[], see the if (m_global) check in
    // ArrayElementExpression::outputCPPImpl, we do not need lvalue wrapper
    if (m_variable->is(Expression::KindOfSimpleVariable)) {
      SimpleVariablePtr var =
        dynamic_pointer_cast<SimpleVariable>(m_variable);
      if (var->getName() == "GLOBALS") {
        m_context |= Expression::NoLValueWrapper;
      }
    }
  } else if (context == Expression::DeepAssignmentLHS ||
             context == Expression::ExistContext ||
             context == Expression::UnsetContext) {
    m_variable->setContext(context);
  }
}
bool ObjectPropertyExpression::directVariantProxy(AnalysisResultPtr ar) {
  TypePtr actualType = m_object->getActualType();
  if (actualType && actualType->is(Type::KindOfVariant)) {
    if (m_object->is(KindOfSimpleVariable)) {
      SimpleVariablePtr var =
        dynamic_pointer_cast<SimpleVariable>(m_object);
      const std::string &name = var->getName();
      FunctionScopePtr func =
        dynamic_pointer_cast<FunctionScope>(ar->getScope());
      VariableTablePtr variables = func->getVariables();
      if (!variables->isParameter(name) || variables->isLvalParam(name)) {
        return true;
      }
      if (variables->getAttribute(VariableTable::ContainsDynamicVariable) ||
          variables->getAttribute(VariableTable::ContainsExtract)) {
        return true;
      }
    } else {
      return true;
    }
  }
  return false;
}
ExpressionPtr AssignmentExpression::postOptimize(AnalysisResultPtr ar) {
  ar->postOptimize(m_variable);
  ar->postOptimize(m_value);
  if (m_variable->is(Expression::KindOfSimpleVariable)) {
    SimpleVariablePtr var =
      dynamic_pointer_cast<SimpleVariable>(m_variable);
    const std::string &name = var->getName();
    VariableTablePtr variables = ar->getScope()->getVariables();
    if (!variables->isPseudoMainTable() &&
        !variables->getAttribute(VariableTable::ContainsDynamicVariable) &&
        !variables->isReferenced(name) &&
        variables->isLocal(name)) {
      variables->addUnused(name);
      if (m_value->isScalar()) {
        m_value->setExpectedType(m_expectedType);
        return m_value;
      } else {
        return makeIdCall(ar);
      }
    }
  }
  return ExpressionPtr();
}
Example #30
0
bool ExpressionList::optimize(AnalysisResultPtr ar) {
  bool changed = false;
  size_t i = m_exps.size();
  if (m_kind != ListKindParam) {
    if (i--) {
      while (i--) {
        ExpressionPtr &e = m_exps[i];
        if (!e || e->getContainedEffects() == NoEffect) {
          ar->incOptCounter();
          removeElement(i);
          changed = true;
        } else if (e->getLocalEffects() == NoEffect) {
          e = e->unneeded(ar);
          changed = true;
        }
      }
    }
    return changed;
  }

  if (hasContext(UnsetContext) &&
      ar->getPhase() >= AnalysisResult::PostOptimize) {
    while (i--) {
      ExpressionPtr &e = m_exps[i];
      if (e->is(Expression::KindOfSimpleVariable)) {
        SimpleVariablePtr var = dynamic_pointer_cast<SimpleVariable>(e);
        const std::string &name = var->getName();
        VariableTablePtr variables = ar->getScope()->getVariables();
        if (variables->checkUnused(name)) {
          removeElement(i);
          changed = true;
        }
      }
    }
  }
  return changed;
}