void ParameterExpression::outputCPPImpl(CodeGenerator &cg,
                                        AnalysisResultPtr ar) {
  FunctionScopePtr func = getFunctionScope();
  VariableTablePtr variables = func->getVariables();
  Symbol *sym = variables->getSymbol(m_name);
  assert(sym && sym->isParameter());

  bool inHeader = cg.isFileOrClassHeader();
  cg.setFileOrClassHeader(true);
  CodeGenerator::Context context = cg.getContext();
  bool typedWrapper = (context == CodeGenerator::CppTypedParamsWrapperImpl ||
                       context == CodeGenerator::CppTypedParamsWrapperDecl);

  TypePtr paramType =
    typedWrapper && func->getParamTypeSpec(sym->getParameterIndex()) ?
    Type::Variant : func->getParamType(sym->getParameterIndex());
  bool wrapper = typedWrapper ||
    context == CodeGenerator::CppFunctionWrapperImpl ||
    context == CodeGenerator::CppFunctionWrapperDecl;

  bool isCVarRef = false;
  const char *prefix = "";
  if (m_ref) {
    cg_printf("VRefParam");
    if (!wrapper) {
      prefix = "r";
    }
  } else if (wrapper ||
      (!variables->isLvalParam(m_name) &&
       !variables->getAttribute(VariableTable::ContainsDynamicVariable) &&
       !variables->getAttribute(VariableTable::ContainsExtract))) {
    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, getScope());
  } else {
    paramType->outputCPPDecl(cg, ar, getScope());
  }

  cg_printf(" %s%s%s",
            prefix, Option::VariablePrefix,
            CodeGenerator::FormatLabel(m_name).c_str());
  if (m_defaultValue && sym->getParameterIndex() >= func->getMinParamCount()) {
    bool comment = context == CodeGenerator::CppTypedParamsWrapperImpl ||
      context == CodeGenerator::CppFunctionWrapperImpl ||
      context == CodeGenerator::CppImplementation ||
      (context == CodeGenerator::CppDeclaration && func->isInlined());
    if (comment) {
      cg_printf(" // ");
    }
    cg_printf(" = ");
    ConstantExpressionPtr con =
      dynamic_pointer_cast<ConstantExpression>(m_defaultValue);

    bool done = false;
    if (con && con->isNull()) {
      done = true;
      if (isCVarRef) {
        cg_printf("null_variant");
      } else if (paramType->is(Type::KindOfVariant) ||
                 paramType->is(Type::KindOfSome)) {
        cg_printf("null");
      } else if (paramType->is(Type::KindOfObject)) {
        cg_printf("Object()");
      } else if (paramType->is(Type::KindOfArray)) {
        cg_printf("Array()");
      } else if (paramType->is(Type::KindOfString)) {
        cg_printf("String()");
      } else {
        done = false;
      }
    }
    if (!done) {
      if (comment) {
        cg.setContext(CodeGenerator::CppParameterDefaultValueImpl);
      } else {
        cg.setContext(CodeGenerator::CppParameterDefaultValueDecl);
      }
      bool isScalar = m_defaultValue->isScalar();
      if (isCVarRef && isScalar) {
        ASSERT(!cg.hasScalarVariant());
        cg.setScalarVariant();
      }
      m_defaultValue->outputCPP(cg, ar);
      if (isCVarRef && isScalar) cg.clearScalarVariant();
      ASSERT(!cg.hasScalarVariant());
      cg.setContext(context);
    }
    if (comment) {
      cg_printf("\n");
    }
  }
  cg.setFileOrClassHeader(inHeader);
}
Esempio n. 2
0
TypePtr SimpleVariable::inferAndCheck(AnalysisResultPtr ar, TypePtr type,
                                      bool coerce) {
  TypePtr ret;
  ConstructPtr construct = shared_from_this();
  BlockScopePtr scope = getScope();
  VariableTablePtr variables = scope->getVariables();

  // check function parameter that can occur in lval context
  if (m_sym && m_sym->isParameter() &&
      m_context & (LValue | RefValue | DeepReference |
                   UnsetContext | InvokeArgument | OprLValue | DeepOprLValue)) {
    m_sym->setLvalParam();
  }
  if (m_this) {
    ClassScopePtr cls = getOriginalClass();
    if (!hasContext(ObjectContext) && cls->derivedByDynamic()) {
      ret = Type::Object;
    } else {
      ret = Type::CreateObjectType(cls->getName());
    }
    if (!hasContext(ObjectContext) &&
        variables->getAttribute(VariableTable::ContainsDynamicVariable)) {
      ret = variables->add(m_sym, ret, true, ar,
                           construct, scope->getModifiers());
    }
  } else if ((m_context & (LValue|Declaration)) &&
             !(m_context & (ObjectContext|RefValue))) {
    if (m_globals) {
      ret = Type::Variant;
    } else if (m_superGlobal) {
      ret = m_superGlobalType;
    } else if (m_superGlobalType) { // For system
      ret = variables->add(m_sym, m_superGlobalType,
                           ((m_context & Declaration) != Declaration), ar,
                           construct, scope->getModifiers());
    } else {
      ret = variables->add(m_sym, type,
                           ((m_context & Declaration) != Declaration), ar,
                           construct, scope->getModifiers());
    }
  } else {
    if (m_superGlobalType) {
      ret = m_superGlobalType;
    } else if (m_globals) {
      ret = Type::Array;
    } else if (scope->is(BlockScope::ClassScope)) {
      // ClassVariable expression will come to this block of code
      ret = getClassScope()->checkProperty(m_sym, type, true, ar);
    } else {
      TypePtr tmpType = type;
      if (m_context & RefValue) {
        tmpType = Type::Variant;
        coerce = true;
      }
      int p;
      ret = variables->checkVariable(m_sym, tmpType, coerce,
                                     ar, construct, p);
    }
  }

  TypePtr actual = propagateTypes(ar, ret);
  setTypes(ar, actual, type);
  if (Type::SameType(actual, ret)) {
    m_implementedType.reset();
  } else {
    m_implementedType = ret;
  }
  return actual;
}
void ParameterExpression::outputCPPImpl(CodeGenerator &cg,
                                        AnalysisResultPtr ar) {
  FunctionScopePtr func = getFunctionScope();
  VariableTablePtr variables = func->getVariables();
  Symbol *sym = variables->getSymbol(m_name);
  assert(sym && sym->isParameter());

  CodeGenerator::Context context = cg.getContext();
  bool typedWrapper = (context == CodeGenerator::CppTypedParamsWrapperImpl ||
                       context == CodeGenerator::CppTypedParamsWrapperDecl);

  TypePtr paramType =
    typedWrapper && func->getParamTypeSpec(sym->getParameterIndex()) ?
    Type::Variant : func->getParamType(sym->getParameterIndex());

  bool isCVarRef = false;
  if (cg.getContext() == CodeGenerator::CppStaticMethodWrapper ||
      typedWrapper ||
      (!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, getScope());
  } else {
    paramType->outputCPPDecl(cg, ar, getScope());
  }

  cg_printf(" %s%s", Option::VariablePrefix, m_name.c_str());
  if (m_defaultValue && sym->getParameterIndex() >= func->getMinParamCount()) {
    bool comment = context == CodeGenerator::CppTypedParamsWrapperImpl ||
      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 SimpleVariable::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) {
  VariableTablePtr variables = getScope()->getVariables();
  if (m_this) {
    ASSERT((getContext() & ObjectContext) == 0);
    if (hasContext(OprLValue) || hasContext(AssignmentLHS)) {
      cg_printf("throw_assign_this()");
      return;
    }
    if (variables->getAttribute(VariableTable::ContainsLDynamicVariable)) {
      ASSERT(m_sym);
      const string &namePrefix = getNamePrefix();
      cg_printf("%s%sthis",
                namePrefix.c_str(),
                variables->getVariablePrefix(m_sym));
    } else if (hasContext(DeepOprLValue) ||
               hasContext(DeepAssignmentLHS) ||
               hasContext(LValue)) {
      // $this[] op= ...; or $this[] = ...
      cg_printf("Variant(GET_THIS())");
    } else {
      ClassScopePtr cls = getOriginalClass();
      if (!cls || cls->derivedByDynamic()) {
        cg_printf("Object(GET_THIS())");
      } else {
        cg_printf("GET_THIS_TYPED(%s)", cls->getId().c_str());
      }
    }
  } else if (m_superGlobal) {
    const string &name = variables->getGlobalVariableName(ar, m_name);
    cg_printf("g->%s", name.c_str());
  } else if (m_globals) {
    cg_printf("get_global_array_wrapper()");
  } else {
    ASSERT(m_sym);
    bool sw = false;
    if (m_sym->isShrinkWrapped() &&
        m_context == Declaration) {
      ASSERT(!getFunctionScope()->isGenerator());
      TypePtr type = m_sym->getFinalType();
      type->outputCPPDecl(cg, ar, getScope());
      sw = true;
      cg_printf(" ");
    }
    const string &prefix0 = getNamePrefix();
    const char *prefix1   = variables->getVariablePrefix(m_sym);
    cg_printf("%s%s%s",
              prefix0.c_str(),
              prefix1,
              CodeGenerator::FormatLabel(m_name).c_str());
    if (m_originalSym) {
      cg.printf(" /* %s */", m_originalSym->getName().c_str());
    }
    if (sw) {
      TypePtr type = m_sym->getFinalType();
      const char *initializer = type->getCPPInitializer();
      if (initializer) {
        cg_printf(" = %s", initializer);
      }
    }
  }
}
bool SimpleVariable::hasAssignableCPPVariable() const {
  if (!m_this) return true;
  if (hasAnyContext(OprLValue | AssignmentLHS)) return false;
  VariableTablePtr variables = getScope()->getVariables();
  return variables->getAttribute(VariableTable::ContainsLDynamicVariable);
}
TypePtr SimpleVariable::inferAndCheck(AnalysisResultPtr ar, TypePtr type,
                                      bool coerce) {
  IMPLEMENT_INFER_AND_CHECK_ASSERT(getScope());

  resetTypes();
  TypePtr ret;
  ConstructPtr construct = shared_from_this();
  BlockScopePtr scope = getScope();
  VariableTablePtr variables = scope->getVariables();

  // check function parameter that can occur in lval context
  if (m_sym && m_sym->isParameter() &&
      m_context & (LValue | RefValue | DeepReference |
                   UnsetContext | InvokeArgument | OprLValue | DeepOprLValue)) {
    m_sym->setLvalParam();
  }

  if (coerce && m_sym && type && type->is(Type::KindOfAutoSequence)) {
    TypePtr t = m_sym->getType();
    if (!t || t->is(Type::KindOfVoid) ||
        t->is(Type::KindOfSome) || t->is(Type::KindOfArray)) {
      type = Type::Array;
    }
  }

  if (m_this) {
    ret = Type::Object;
    ClassScopePtr cls = getOriginalClass();
    if (cls && (hasContext(ObjectContext) || !cls->derivedByDynamic())) {
      ret = Type::CreateObjectType(cls->getName());
    }
    if (!hasContext(ObjectContext) &&
        variables->getAttribute(VariableTable::ContainsDynamicVariable)) {
      if (variables->getAttribute(VariableTable::ContainsLDynamicVariable)) {
        ret = Type::Variant;
      }
      ret = variables->add(m_sym, ret, true, ar,
                           construct, scope->getModifiers());
    }
  } else if ((m_context & (LValue|Declaration)) &&
             !(m_context & (ObjectContext|RefValue))) {
    if (m_globals) {
      ret = Type::Array;
    } else if (m_superGlobal) {
      ret = m_superGlobalType;
    } else if (m_superGlobalType) { // For system
      ret = variables->add(m_sym, m_superGlobalType,
                           ((m_context & Declaration) != Declaration), ar,
                           construct, scope->getModifiers());
    } else {
      ret = variables->add(m_sym, type,
                           ((m_context & Declaration) != Declaration), ar,
                           construct, scope->getModifiers());
    }
  } else {
    if (m_superGlobalType) {
      ret = m_superGlobalType;
    } else if (m_globals) {
      ret = Type::Array;
    } else if (scope->is(BlockScope::ClassScope)) {
      ASSERT(getClassScope().get() == scope.get());
      // ClassVariable expression will come to this block of code
      ret = getClassScope()->checkProperty(getScope(), m_sym, type, true, ar);
    } else {
      TypePtr tmpType = type;
      if (m_context & RefValue) {
        tmpType = Type::Variant;
        coerce = true;
      }
      ret = variables->checkVariable(m_sym, tmpType, coerce, ar, construct);
      if (ret && (ret->is(Type::KindOfSome) || ret->is(Type::KindOfAny))) {
        ret = Type::Variant;
      }
    }
  }

  // if m_assertedType is set, then this is a type assertion node
  TypePtr inType = m_assertedType ?
    GetAssertedInType(ar, m_assertedType, ret) : ret;
  TypePtr actual = propagateTypes(ar, inType);
  setTypes(ar, actual, type);
  if (Type::SameType(actual, ret)) {
    m_implementedType.reset();
  } else {
    m_implementedType = ret;
  }
  return actual;
}
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();
    }
  }
}
Esempio n. 8
0
void SimpleVariable::analyzeProgram(AnalysisResultPtr ar) {
  m_superGlobal = BuiltinSymbols::IsSuperGlobal(m_name);

  VariableTablePtr variables = getScope()->getVariables();
  if (m_name == "GLOBALS") {
    m_globals = true;
  } else {
    m_sym = variables->addDeclaredSymbol(m_name, shared_from_this());
  }

  if (m_name == "http_response_header" || m_name == "php_errormsg") {
    setInited();
  }

  if (ar->getPhase() == AnalysisResult::AnalyzeAll) {
    if (FunctionScopePtr func = getFunctionScope()) {
      if (m_name == "this" && func->mayContainThis()) {
        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)) {
            variables->add(m_sym, 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 && !m_this) {
      if (!m_sym->isSystem() &&
          !(getContext() &
            (LValue|RefValue|RefParameter|UnsetContext|ExistContext)) &&
          m_sym->getDeclaration().get() == this &&
          !m_sym->isParameter()) {

        if (!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();
      }
    }
  }
}