void ClassVariable::onParse(AnalysisResultPtr ar) {
  ModifierExpressionPtr modifiers =
    ar->getScope()->setModifiers(m_modifiers);

  for (int i = 0; i < m_declaration->getCount(); i++) {
    VariableTablePtr variables = ar->getScope()->getVariables();
    ExpressionPtr exp = (*m_declaration)[i];
    if (exp->is(Expression::KindOfAssignmentExpression)) {
      AssignmentExpressionPtr assignment =
        dynamic_pointer_cast<AssignmentExpression>(exp);
      ExpressionPtr var = assignment->getVariable();
      const std::string &name =
        dynamic_pointer_cast<SimpleVariable>(var)->getName();
      if (variables->isPresent(name)) {
        ar->getCodeError()->record(CodeError::DeclaredVariableTwice, exp);
      }
      IParseHandlerPtr ph = dynamic_pointer_cast<IParseHandler>(exp);
      ph->onParse(ar);
    } else {
      const std::string &name =
        dynamic_pointer_cast<SimpleVariable>(exp)->getName();
      if (variables->isPresent(name)) {
        ar->getCodeError()->record(CodeError::DeclaredVariableTwice, exp);
      }
      variables->add(name, TypePtr(), false, ar, exp, m_modifiers);
    }
  }

  ar->getScope()->setModifiers(modifiers);
}
TypePtr NewObjectExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
                                        bool coerce) {
  reset();
  ConstructPtr self = shared_from_this();
  if (!m_name.empty()) {
    ClassScopePtr cls = ar->resolveClass(m_name);
    if (cls) {
      m_name = cls->getName();
    }
    if (!cls || cls->isRedeclaring()) {
      if (cls) {
        m_redeclared = true;
        ar->getScope()->getVariables()->
          setAttribute(VariableTable::NeedGlobalPointer);
      }
      if (!cls && ar->isFirstPass()) {
        ar->getCodeError()->record(self, CodeError::UnknownClass, self);
      }
      if (m_params) m_params->inferAndCheck(ar, NEW_TYPE(Any), false);
      return NEW_TYPE(Object);
    }
    if (cls->isVolatile()) {
      ar->getScope()->getVariables()->
        setAttribute(VariableTable::NeedGlobalPointer);
    }
    m_dynamic = cls->derivesFromRedeclaring();
    m_validClass = true;
    FunctionScopePtr func = cls->findConstructor(ar, true);
    if (!func) {
      if (m_params) {
        if (!m_dynamic && m_params->getCount()) {
          if (ar->isFirstPass()) {
            ar->getCodeError()->record(self, CodeError::BadConstructorCall,
                                       self);
          }
          m_params->setOutputCount(0);
        }
        m_params->inferAndCheck(ar, NEW_TYPE(Any), false);
      }
    } else {
      m_extraArg = func->inferParamTypes(ar, self, m_params,
                                         m_validClass);
      m_variableArgument = func->isVariableArgument();
    }
    return Type::CreateObjectType(m_name);
  } else {
    ar->containsDynamicClass();
    if (ar->isFirstPass()) {
      ar->getCodeError()->record(self, CodeError::UseDynamicClass,
                                 self);
    }
    if (m_params) {
      m_params->markParams(false);
    }
  }

  m_nameExp->inferAndCheck(ar, Type::String, false);
  if (m_params) m_params->inferAndCheck(ar, NEW_TYPE(Any), false);
  return Type::Variant;//NEW_TYPE(Object);
}
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 ForEachStatement::inferTypes(AnalysisResultPtr ar) {
  if (ar->isFirstPass() &&
      !m_array->is(Expression::KindOfSimpleVariable) &&
      !m_array->is(Expression::KindOfArrayElementExpression) &&
      !m_array->is(Expression::KindOfObjectPropertyExpression)) {
    ConstructPtr self = shared_from_this();
    ar->getCodeError()->record(self, CodeError::ComplexForEach, self);
  }

  m_array->inferAndCheck(ar, Type::Array, true);
  if (m_name) {
    m_name->inferAndCheck(ar, NEW_TYPE(Primitive), true);
  }
  m_value->inferAndCheck(ar, Type::Variant, true);
  if (m_ref) {
    TypePtr actualType = m_array->getActualType();
    if (!actualType ||
        actualType->is(Type::KindOfVariant) ||
        actualType->is(Type::KindOfObject)) {
      ar->forceClassVariants();
    }
  }
  if (m_stmt) {
    ar->getScope()->incLoopNestedLevel();
    m_stmt->inferTypes(ar);
    ar->getScope()->decLoopNestedLevel();
  }
}
void SimpleVariable::analyzeProgram(AnalysisResultPtr ar) {
  Expression::analyzeProgram(ar);
  if (m_name == "argc" || m_name == "argv") {
    // special case: they are NOT superglobals when not in global scope
    if (ar->getScope() == ar) {
      m_superGlobal = BuiltinSymbols::IsSuperGlobal(m_name);
      m_superGlobalType = BuiltinSymbols::GetSuperGlobalType(m_name);
    }
  } else {
    m_superGlobal = BuiltinSymbols::IsSuperGlobal(m_name);
    m_superGlobalType = BuiltinSymbols::GetSuperGlobalType(m_name);
  }

  if (m_superGlobal) {
    ar->getScope()->getVariables()->
      setAttribute(VariableTable::NeedGlobalPointer);
  }

  if (m_name == "this" && ar->getClassScope()) {
    FunctionScopePtr func =
      dynamic_pointer_cast<FunctionScope>(ar->getScope());
    func->setContainsThis();
    m_this = true;
  } else if (m_name == "GLOBALS") {
    m_globals = true;
  }
  if (!(m_context & AssignmentLHS)) {
    BlockScopePtr scope = ar->getScope();
    FunctionScopePtr func = dynamic_pointer_cast<FunctionScope>(scope);
    if (func) {
      func->getVariables()->addUsed(m_name);
    }
  }
}
void WhileStatement::inferTypes(AnalysisResultPtr ar) {
  m_condition->inferAndCheck(ar, Type::Boolean, false);
  if (m_stmt) {
    ar->getScope()->incLoopNestedLevel();
    m_stmt->inferTypes(ar);
    ar->getScope()->decLoopNestedLevel();
  }
}
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;
}
StatementPtr WhileStatement::postOptimize(AnalysisResultPtr ar) {
  ar->postOptimize(m_condition);
  if (m_stmt) {
    ar->getScope()->incLoopNestedLevel();
    ar->postOptimize(m_stmt);
    ar->getScope()->decLoopNestedLevel();
  }
  return StatementPtr();
}
Beispiel #9
0
StatementPtr ForStatement::postOptimize(AnalysisResultPtr ar) {
  ar->postOptimize(m_exp1);
  ar->postOptimize(m_exp2);
  ar->postOptimize(m_exp3);
  if (m_stmt) {
    ar->getScope()->incLoopNestedLevel();
    ar->postOptimize(m_stmt);
    ar->getScope()->decLoopNestedLevel();
  }
  return StatementPtr();
}
Beispiel #10
0
void ForStatement::inferTypes(AnalysisResultPtr ar) {
  if (m_exp1) m_exp1->inferAndCheck(ar, NEW_TYPE(Any), false);
  if (m_exp2) m_exp2->inferAndCheck(ar, Type::Boolean, false);
  if (m_stmt) {
    ar->getScope()->incLoopNestedLevel();
    m_stmt->inferTypes(ar);
    if (m_exp3) m_exp3->inferAndCheck(ar, NEW_TYPE(Any), false);
    ar->getScope()->decLoopNestedLevel();
  } else {
    if (m_exp3) m_exp3->inferAndCheck(ar, NEW_TYPE(Any), false);
  }
}
void ArrayElementExpression::outputPHP(CodeGenerator &cg,
                                       AnalysisResultPtr ar) {
  if (Option::ConvertSuperGlobals && m_global && !m_dynamicGlobal &&
      ar && (ar->getScope() == ar || ar->getScope()->
             getVariables()->isConvertibleSuperGlobal(m_globalName))) {
    cg_printf("$%s", m_globalName.c_str());
  } else {
    m_variable->outputPHP(cg, ar);
    cg_printf("[");
    if (m_offset) m_offset->outputPHP(cg, ar);
    cg_printf("]");
  }
}
void MethodStatement::addParamRTTI(AnalysisResultPtr ar) {
  FunctionScopePtr func =
    dynamic_pointer_cast<FunctionScope>(ar->getScope());
  VariableTablePtr variables = func->getVariables();
  if (variables->getAttribute(VariableTable::ContainsDynamicVariable) ||
      variables->getAttribute(VariableTable::ContainsExtract)) {
    return;
  }
  for (int i = 0; i < m_params->getCount(); i++) {
    ParameterExpressionPtr param =
      dynamic_pointer_cast<ParameterExpression>((*m_params)[i]);
    const string &paramName = param->getName();
    if (variables->isLvalParam(paramName)) continue;
    TypePtr paramType = param->getActualType();
    if ((paramType->is(Type::KindOfVariant) ||
         paramType->is(Type::KindOfSome)) &&
        !param->isRef()) {
      param->setHasRTTI();
      ClassScopePtr cls = ar->getClassScope();
      ar->addParamRTTIEntry(cls, func, paramName);
      const string funcId = ar->getFuncId(cls, func);
      ar->addRTTIFunction(funcId);
    }
  }
}
Beispiel #13
0
bool AliasManager::optimize(AnalysisResultPtr ar, MethodStatementPtr m) {
  m_arp = ar;

  m_variables = ar->getScope()->getVariables();
  if (!m_variables->isPseudoMainTable()) {
    m_variables->clearUsed();
  }

  if (ExpressionListPtr pPtr = m->getParams()) {
    ExpressionList &params = *pPtr;
    for (int i = params.getCount(); i--; ) {
      ParameterExpressionPtr p = spc(ParameterExpression, params[i]);
      AliasInfo &ai = m_aliasInfo[p->getName()];
      if (p->isRef()) {
        ai.setIsRefTo();
      }
    }
  }

  collectAliasInfoRecur(m->getStmts());

  for (AliasInfoMap::iterator it = m_aliasInfo.begin(),
         end = m_aliasInfo.end(); it != end; ++it) {
    if (m_variables->isGlobal(it->first) ||
        m_variables->isStatic(it->first)) {
      it->second.setIsGlobal();
    }
  }

  canonicalizeRecur(m->getStmts());
  return m_changed;
}
Beispiel #14
0
void CatchStatement::analyzeProgramImpl(AnalysisResultPtr ar) {
  addUserClass(ar, m_className);
  if (ar->isFirstPass()) {
    ar->getScope()->getVariables()->addUsed(m_variable);
  }
  if (m_stmt) m_stmt->analyzeProgram(ar);
}
Beispiel #15
0
void CatchStatement::inferTypes(AnalysisResultPtr ar) {
  ClassScopePtr cls = ar->findClass(m_className);
  TypePtr type;
  m_valid = cls;
  if (!m_valid) {
    if (ar->isFirstPass()) {
      ConstructPtr self = shared_from_this();
      ar->getCodeError()->record(self, CodeError::UnknownClass, self);
    }
    type = NEW_TYPE(Object);
  } else if (cls->isRedeclaring()) {
    type = NEW_TYPE(Object);
  } else {
    type = Type::CreateObjectType(m_className);
  }

  BlockScopePtr scope = ar->getScope();
  VariableTablePtr variables = scope->getVariables();
  variables->add(m_variable, type, false, ar, shared_from_this(),
                 ModifierExpressionPtr(), false);
  if (ar->isFirstPass()) {
    FunctionScopePtr func = dynamic_pointer_cast<FunctionScope>(scope);
    if (func && variables->isParameter(m_variable)) {
      variables->addLvalParam(m_variable);
    }
  }
  if (m_stmt) m_stmt->inferTypes(ar);
}
TypePtr DynamicFunctionCall::inferTypes(AnalysisResultPtr ar, TypePtr type,
                                        bool coerce) {
    reset();
    ConstructPtr self = shared_from_this();
    if (!m_className.empty()) {
        ClassScopePtr cls = ar->resolveClass(m_className);
        if (!cls || cls->isRedeclaring()) {
            if (cls) {
                m_redeclared = true;
                ar->getScope()->getVariables()->
                setAttribute(VariableTable::NeedGlobalPointer);
            }
            if (!cls && ar->isFirstPass()) {
                ar->getCodeError()->record(self, CodeError::UnknownClass, self);
            }
        } else {
            m_validClass = true;
        }
    }

    ar->containsDynamicFunctionCall();

    if (ar->isFirstPass()) {
        ar->getCodeError()->record(self, CodeError::UseDynamicFunction, self);
    }
    m_nameExp->inferAndCheck(ar, Type::String, false);
    if (m_params) {
        for (int i = 0; i < m_params->getCount(); i++) {
            (*m_params)[i]->inferAndCheck(ar, Type::Variant, true);
        }
    }
    return Type::Variant;
}
Beispiel #17
0
TypePtr DynamicVariable::inferTypes(AnalysisResultPtr ar, TypePtr type,
                                    bool coerce) {
  ConstructPtr self = shared_from_this();
  if (m_context & (LValue | RefValue)) {
    if (ar->isFirstPass()) {
      ar->getCodeError()->record(self, CodeError::UseLDynamicVariable, self);
    }
    ar->getScope()->getVariables()->forceVariants(ar);
    ar->getScope()->
      getVariables()->setAttribute(VariableTable::ContainsLDynamicVariable);
  } else {
    if (ar->isFirstPass()) {
      ar->getCodeError()->record(self, CodeError::UseRDynamicVariable, self);
    }
  }

  m_exp->inferAndCheck(ar, Type::String, false);
  return m_implementedType = Type::Variant;
}
TypePtr AssignmentExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
                                         bool coerce) {

  if (VariableTable::m_hookHandler) {
    VariableTable::m_hookHandler(ar, ar->getScope()->getVariables().get(),
                                 m_variable,
                                 beforeAssignmentExpressionInferTypes);
  }

  TypePtr ret = inferAssignmentTypes(ar, type, coerce, m_variable, m_value);

  if (VariableTable::m_hookHandler) {
    VariableTable::m_hookHandler(ar, ar->getScope()->getVariables().get(),
                                 m_variable,
                                 afterAssignmentExpressionInferTypes);
  }

  return ret;
}
Beispiel #19
0
void CatchStatement::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) {
  if (m_valid) {
    cg.indentBegin("if (e.instanceof(\"%s\")) {\n", m_className.c_str());
    VariableTablePtr variables = ar->getScope()->getVariables();
    cg.printf("%s = e;\n", variables->getVariableName(ar, m_variable).c_str());
  } else {
    cg.indentBegin("if (false) {\n");
  }
  if (m_stmt) m_stmt->outputCPP(cg, ar);
  cg.indentEnd("}");
}
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());
      }
    }
  }
}
TypePtr ClassConstantExpression::inferTypes(AnalysisResultPtr ar,
                                            TypePtr type, bool coerce) {
  m_valid = false;
  ConstructPtr self = shared_from_this();
  ClassScopePtr cls = ar->resolveClass(m_className);
  if (!cls || cls->isRedeclaring()) {
    if (cls) {
      m_redeclared = true;
      ar->getScope()->getVariables()->
        setAttribute(VariableTable::NeedGlobalPointer);
    }
    if (!cls && ar->isFirstPass()) {
      ar->getCodeError()->record(self, CodeError::UnknownClass, self);
    }
    return type;
  }
  if (cls->getConstants()->isDynamic(m_varName)) {
    ar->getScope()->getVariables()->
      setAttribute(VariableTable::NeedGlobalPointer);
  }
  if (cls->getConstants()->isExplicitlyDeclared(m_varName)) {
    string name = m_className + "::" + m_varName;
    ConstructPtr decl = cls->getConstants()->getDeclaration(m_varName);
    if (decl) { // No decl means an extension class.
      ar->getDependencyGraph()->add(DependencyGraph::KindOfConstant,
                                    ar->getName(),
                                    name, shared_from_this(), name, decl);
    }
    m_valid = true;
  }
  bool present;
  TypePtr t = cls->checkConst(m_varName, type, coerce, ar,
                              shared_from_this(), present);
  if (present) {
    m_valid = true;
  }

  return t;
}
void IncludeExpression::analyzeProgram(AnalysisResultPtr ar) {
  if (ar->isFirstPass()) {
    ConstructPtr self = shared_from_this();
    if (m_op == T_INCLUDE || m_op == T_REQUIRE) {
      ar->getCodeError()->record(self, CodeError::UseInclude, self);
    }
  }

  string include = getCurrentInclude(ar);
  if (!include.empty()) {
    if (ar->getPhase() == AnalysisResult::AnalyzeInclude) {
      analyzeInclude(ar, include);
    }
  }
  if (!ar->getScope()->inPseudoMain()) {
    VariableTablePtr var = ar->getScope()->getVariables();
    var->setAttribute(VariableTable::ContainsLDynamicVariable);
    var->forceVariants(ar);
  }

  UnaryOpExpression::analyzeProgram(ar);
}
void SimpleVariable::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) {
  if (m_this) {
    ASSERT((getContext() & ObjectContext) == 0);
    if (hasContext(LValue)) {
      // LValue and not ObjectContext must be $this = or $this[..] =
      // Wrap with Variant to avoid compiler error
      cg_printf("Variant(GET_THIS())");
    } else {
      cg_printf("GET_THIS()");
    }
  } else if (m_superGlobal) {
    VariableTablePtr variables = ar->getScope()->getVariables();
    string name = variables->getGlobalVariableName(cg, ar, m_name);
    cg_printf("g->%s", name.c_str());
  } else if (m_globals) {
    cg_printf("get_global_array_wrapper()");
  } else {
    const char *prefix =
      ar->getScope()->getVariables()->getVariablePrefix(ar, m_name);
    cg_printf("%s%s", prefix, cg.formatLabel(m_name).c_str());
  }
}
void ParameterExpression::outputCPPImpl(CodeGenerator &cg,
                                        AnalysisResultPtr ar) {
  FunctionScopePtr func =
    dynamic_pointer_cast<FunctionScope>(ar->getScope());
  VariableTablePtr variables = func->getVariables();
  TypePtr paramType = func->getParamType(cg.getItemIndex());
  bool isCVarRef = false;
  if (cg.getContext() == CodeGenerator::CppStaticMethodWrapper ||
      (!variables->isLvalParam(m_name) &&
       !variables->getAttribute(VariableTable::ContainsDynamicVariable) &&
       !variables->getAttribute(VariableTable::ContainsExtract) &&
       !m_ref)) {
    if (paramType->is(Type::KindOfVariant) ||
        paramType->is(Type::KindOfSome)) {
      cg_printf("CVarRef");
      isCVarRef = true;
    }
    else if (paramType->is(Type::KindOfArray)) cg_printf("CArrRef");
    else if (paramType->is(Type::KindOfString)) cg_printf("CStrRef");
    else paramType->outputCPPDecl(cg, ar);
  } else {
    paramType->outputCPPDecl(cg, ar);
  }

  cg_printf(" %s%s", Option::VariablePrefix, m_name.c_str());
  if (m_defaultValue) {
    CodeGenerator::Context context = cg.getContext();
    bool comment =  context == CodeGenerator::CppImplementation ||
      (context == CodeGenerator::CppDeclaration && func->isInlined());
    if (comment) {
      cg_printf(" // ");
    }
    cg_printf(" = ");
    ConstantExpressionPtr con =
      dynamic_pointer_cast<ConstantExpression>(m_defaultValue);
    if (isCVarRef && con && con->isNull()) {
      cg_printf("null_variant");
    } else {
      if (comment) {
        cg.setContext(CodeGenerator::CppParameterDefaultValueImpl);
      } else {
        cg.setContext(CodeGenerator::CppParameterDefaultValueDecl);
      }
      m_defaultValue->outputCPP(cg, ar);
      cg.setContext(context);
    }
    if (comment) {
      cg_printf("\n");
    }
  }
}
void StaticStatement::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) {
  BlockScopePtr scope = ar->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);
      var->setContext(Expression::Declaration);
      const std::string &name = var->getName();

      if (variables->needLocalCopy(name)) {
        cg_printf("%s%s = ref(%s%s);\n",
                  Option::VariablePrefix, name.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");
}
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;
    }
  }
}
Beispiel #27
0
void GlobalStatement::inferTypes(AnalysisResultPtr ar) {
  BlockScopePtr scope = ar->getScope();
  scope->getVariables()->setAttribute(VariableTable::InsideGlobalStatement);
  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);
      VariableTablePtr variables = scope->getVariables();
      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->checkRedeclared(name, KindOfGlobalStatement);

      /* If this is not a top-level global statement, the variable also
         needs to be Variant type. This should not be a common use case in
         php code.
       */
      if (!isTopLevel()) {
        variables->addNestedGlobal(name);
      }
      var->setContext(Expression::Declaration);
      var->inferAndCheck(ar, NEW_TYPE(Any), true);

      if (variables->needLocalCopy(name)) {
        variables->forceVariant(ar, name);
        variables->setAttribute(VariableTable::NeedGlobalPointer);
      }

      ConstructPtr decl =
        ar->getVariables()->getDeclaration(var->getName());
      if (decl) {
        ar->getDependencyGraph()->add(DependencyGraph::KindOfGlobalVariable,
                                      ar->getName(),
                                      var->getName(), var,
                                      var->getName(), decl);
      }
    } else {
      if (ar->isFirstPass()) {
        ar->getCodeError()->record(shared_from_this(), CodeError::UseDynamicGlobal, exp);
      }
      m_dynamicGlobal = true;
    }
  }
  FunctionScopePtr func = ar->getFunctionScope();
  scope->getVariables()->clearAttribute(VariableTable::InsideGlobalStatement);
}
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();
}
void MethodStatement::onParse(AnalysisResultPtr ar) {
  ClassScopePtr classScope =
    dynamic_pointer_cast<ClassScope>(ar->getScope());

  classScope->addFunction(ar, onParseImpl(ar));
  if (m_name == "__construct") {
    classScope->setAttribute(ClassScope::HasConstructor);
  } else if (m_name == "__destruct") {
    classScope->setAttribute(ClassScope::HasDestructor);
  }

  if (m_name == "__call") {
    classScope->setAttribute(ClassScope::HasUnknownMethodHandler);
  } else if (m_name == "__get") {
    classScope->setAttribute(ClassScope::HasUnknownPropHandler);
  }

  m_className = classScope->getName();
}
void ArrayElementExpression::outputCPPExistTest(CodeGenerator &cg,
                                                AnalysisResultPtr ar, int op) {
  switch (op) {
  case T_ISSET:  cg_printf("isset("); break;
  case T_EMPTY:  cg_printf("empty("); break;
  default: ASSERT(false);
  }

  if (m_global) {
    if (!m_globalName.empty()) {
      VariableTablePtr variables = ar->getScope()->getVariables();
      string name = variables->getGlobalVariableName(cg, ar, m_globalName);
      cg_printf("g->%s", name.c_str());
    } else {
      cg_printf("get_variable_table()->get(");
      m_offset->outputCPP(cg, ar);
      cg_printf(")");
    }
  } else {
    m_variable->outputCPP(cg, ar);
    cg_printf(", ");
    m_offset->outputCPP(cg, ar);
    ScalarExpressionPtr sc =
      dynamic_pointer_cast<ScalarExpression>(m_offset);
    if (sc) {
      int64 hash = sc->getHash();
      if (hash >= 0) {
        cg_printf(", 0x%016llXLL", hash);
      }
      if (sc->isLiteralString()) {
        String s(sc->getLiteralString());
        int64 n;
        if (!s.get()->isStrictlyInteger(n)) {
          cg_printf(", true"); // skip toKey() at run time
        }
      }
    }
  }
  cg_printf(")");
}