Exemplo n.º 1
0
TypePtr FunctionCall::checkParamsAndReturn(AnalysisResultPtr ar,
                                           TypePtr type, bool coerce,
                                           FunctionScopePtr func) {
  ConstructPtr self = shared_from_this();
  ar->getDependencyGraph()->add(DependencyGraph::KindOfFunctionCall,
                                ar->getName(), getText(),
                                self, func->getFullName(), func->getStmt());
  TypePtr frt = func->getReturnType();
  if (!frt) {
    m_voidReturn = true;
    setActualType(TypePtr());
    if (!type->is(Type::KindOfAny)) {
      if (!m_allowVoidReturn && ar->isSecondPass() && !func->isAbstract()) {
        ar->getCodeError()->record(self, CodeError::UseVoidReturn, self);
      }
      m_voidWrapper = true;
    }
  } else {
    m_voidReturn = false;
    m_voidWrapper = false;
    type = checkTypesImpl(ar, type, frt, coerce);
  }
  m_extraArg = func->inferParamTypes(ar, self, m_params, m_valid);
  m_variableArgument = func->isVariableArgument();
  if (m_valid) {
    m_implementedType.reset();
  } else {
    m_implementedType = Type::Variant;
  }

  return type;
}
Exemplo n.º 2
0
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);
}
TypePtr FunctionCall::checkParamsAndReturn(AnalysisResultPtr ar,
                                           TypePtr type, bool coerce,
                                           FunctionScopePtr func,
                                           bool arrayParams) {
  ConstructPtr self = shared_from_this();
  TypePtr frt = func->getReturnType();
  if (!frt) {
    m_voidReturn = true;
    setActualType(TypePtr());
    if (!type->is(Type::KindOfAny)) {
      if (!m_allowVoidReturn && !func->isFirstPass() && !func->isAbstract()) {
        Compiler::Error(Compiler::UseVoidReturn, self);
      }
      m_voidWrapper = true;
    }
  } else {
    m_voidReturn = false;
    m_voidWrapper = false;
    type = checkTypesImpl(ar, type, frt, coerce);
  }
  if (arrayParams) {
    m_extraArg = 0;
    (*m_params)[0]->inferAndCheck(ar, Type::Array, false);
  } else {
    m_extraArg = func->inferParamTypes(ar, self, m_params, m_valid);
  }
  m_variableArgument = func->isVariableArgument();
  if (m_valid) {
    m_implementedType.reset();
  } else {
    m_implementedType = Type::Variant;
  }

  return type;
}
Exemplo n.º 4
0
TypePtr FunctionCall::checkParamsAndReturn(AnalysisResultPtr ar,
                                           TypePtr type, bool coerce,
                                           FunctionScopePtr func,
                                           bool arrayParams) {
#ifdef HPHP_DETAILED_TYPE_INF_ASSERT
  assert(func->hasUser(getScope(), BlockScope::UseKindCaller));
#endif /* HPHP_DETAILED_TYPE_INF_ASSERT */
  ConstructPtr self = shared_from_this();
  TypePtr frt;
  {
    TRY_LOCK(func);
    func->getInferTypesMutex().assertOwnedBySelf();
    assert(!func->inVisitScopes() || getScope() == func);
    frt = func->getReturnType();
  }
  if (!frt) {
    m_voidReturn = true;
    setActualType(TypePtr());
    if (!isUnused() && !type->is(Type::KindOfAny)) {
      if (!hasContext(ReturnContext) &&
          !func->isFirstPass() && !func->isAbstract()) {
        if (Option::WholeProgram || !func->getContainingClass() ||
            func->isStatic() || func->isFinal() || func->isPrivate()) {
          Compiler::Error(Compiler::UseVoidReturn, self);
        }
      }
      if (!Type::IsMappedToVariant(type)) {
        setExpectedType(type);
      }
      m_voidWrapper = true;
    }
  } else {
    m_voidReturn = false;
    m_voidWrapper = false;
    type = checkTypesImpl(ar, type, frt, coerce);
    assert(m_actualType);
  }
  if (arrayParams) {
    m_extraArg = 0;
    (*m_params)[0]->inferAndCheck(ar, Type::Array, false);
  } else {
    m_extraArg = func->inferParamTypes(ar, self, m_params, m_valid);
  }
  m_variableArgument = func->isVariableArgument();
  if (m_valid) {
    m_implementedType.reset();
  } else {
    m_implementedType = Type::Variant;
  }
  assert(type);

  return type;
}
TypePtr NewObjectExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
                                        bool coerce) {
  reset();
  m_classScope.reset();
  m_funcScope.reset();
  ConstructPtr self = shared_from_this();
  if (!m_name.empty()) {
    ClassScopePtr cls = resolveClass(getScope());
    m_name = m_className;

    if (!cls) {
      if (isRedeclared()) {
        getScope()->getVariables()->
          setAttribute(VariableTable::NeedGlobalPointer);
      } else if (getScope()->isFirstPass()) {
        Compiler::Error(Compiler::UnknownClass, self);
      }
      if (m_params) m_params->inferAndCheck(ar, Type::Any, false);
      return Type::Object;
    }
    if (cls->isVolatile() && !isPresent()) {
      getScope()->getVariables()->
        setAttribute(VariableTable::NeedGlobalPointer);
    }
    m_dynamic = cls->derivesFromRedeclaring();
    bool valid = true;
    FunctionScopePtr func = cls->findConstructor(ar, true);
    if (!func) {
      if (m_params) {
        if (!m_dynamic && m_params->getCount()) {
          if (getScope()->isFirstPass()) {
            Compiler::Error(Compiler::BadConstructorCall, self);
          }
          m_params->setOutputCount(0);
        }
        m_params->inferAndCheck(ar, Type::Some, false);
      }
    } else {
      m_extraArg = func->inferParamTypes(ar, self, m_params,
                                         valid);
      m_variableArgument = func->isVariableArgument();
    }
    if (valid) {
      m_classScope = cls;
      m_funcScope = func;
    }
    if (!valid || m_dynamic) {
      m_implementedType = Type::Object;
    } else {
      m_implementedType.reset();
    }
    return Type::CreateObjectType(m_name);
  } else {
    ar->containsDynamicClass();
    if (m_params) {
      m_params->markParams(false);
    }
  }

  m_implementedType.reset();
  m_nameExp->inferAndCheck(ar, Type::String, false);
  if (m_params) m_params->inferAndCheck(ar, Type::Any, false);
  return Type::Object;
}
Exemplo n.º 6
0
TypePtr NewObjectExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
                                        bool coerce) {
  reset();
  m_classScope.reset();
  FunctionScopePtr prev = m_funcScope;
  m_funcScope.reset();
  ConstructPtr self = shared_from_this();
  if (!m_name.empty() && !isStatic()) {
    ClassScopePtr cls = resolveClassWithChecks();
    m_name = m_className;
    if (!cls) {
      if (m_params) m_params->inferAndCheck(ar, Type::Any, false);
      return Type::Object;
    }

    if (getScope()->isFirstPass() &&
        (cls->isTrait() ?
         !isSelf() && !isParent() :
         cls->isInterface() || cls->isAbstract())) {
      Compiler::Error(Compiler::InvalidInstantiation, self);
    }

    if (cls->isVolatile() && !isPresent()) {
      getScope()->getVariables()->
        setAttribute(VariableTable::NeedGlobalPointer);
    }
    m_dynamic = cls->derivesFromRedeclaring();
    bool valid = true;
    FunctionScopePtr func = cls->findConstructor(ar, true);
    if (!func) {
      if (m_params) {
        if (!m_dynamic && m_params->getCount()) {
          if (getScope()->isFirstPass()) {
            Compiler::Error(Compiler::BadConstructorCall, self);
          }
        }
        m_params->inferAndCheck(ar, Type::Some, false);
      }
    } else {
      if (func != prev) func->addNewObjCaller(getScope());
      m_extraArg = func->inferParamTypes(ar, self, m_params, valid);
      m_variableArgument = func->isVariableArgument();
    }
    if (valid) {
      m_classScope = cls;
      m_funcScope = func;
    }
    if (!valid || m_dynamic) {
      m_implementedType = Type::Object;
    } else {
      m_implementedType.reset();
    }
    return Type::CreateObjectType(m_name);
  } else {
    if (m_params) {
      m_params->markParams(canInvokeFewArgs());
    }
  }

  m_implementedType.reset();
  m_nameExp->inferAndCheck(ar, Type::String, false);
  if (m_params) m_params->inferAndCheck(ar, Type::Any, false);
  return Type::Object;
}
Exemplo n.º 7
0
TypePtr FunctionCall::checkParamsAndReturn(AnalysisResultPtr ar,
                                           TypePtr type, bool coerce,
                                           FunctionScopePtr func,
                                           bool arrayParams) {
#ifdef HPHP_DETAILED_TYPE_INF_ASSERT
  assert(func->hasUser(getScope(), BlockScope::UseKindCaller));
#endif /* HPHP_DETAILED_TYPE_INF_ASSERT */
  ConstructPtr self = shared_from_this();
  TypePtr frt;
  {
    TRY_LOCK(func);
    func->getInferTypesMutex().assertOwnedBySelf();
    assert(!func->inVisitScopes() || getScope() == func);
    frt = func->getReturnType();
  }

  // fix return type for generators and async functions here, keep the
  // infered return type in function scope to allow further optimizations
  if (func->isGenerator()) {
    frt = Type::GetType(Type::KindOfObject, "Generator");
  } else if (func->isAsync()) {
    frt = Type::GetType(Type::KindOfObject, "WaitHandle");
  }

  m_voidUsed = false;
  if (!frt) {
    m_voidReturn = true;
    setActualType(TypePtr());
    if (!isUnused() && !type->is(Type::KindOfAny)) {
      if (!hasContext(ReturnContext) &&
          !func->isFirstPass() && !func->isAbstract()) {
        if (Option::WholeProgram || !func->getContainingClass() ||
            func->isStatic() || func->isFinal() || func->isPrivate()) {
          m_voidUsed = true;
        }
      }
      if (!Type::IsMappedToVariant(type)) {
        setExpectedType(type);
      }
    }
  } else {
    m_voidReturn = false;
    type = checkTypesImpl(ar, type, frt, coerce);
    assert(m_actualType);
  }
  if (arrayParams) {
    m_extraArg = 0;
    (*m_params)[0]->inferAndCheck(ar, Type::Array, false);
  } else {
    m_extraArg = func->inferParamTypes(ar, self, m_params, m_valid);
  }
  m_variableArgument = func->allowsVariableArguments();
  if (m_valid) {
    m_implementedType.reset();
  } else {
    m_implementedType = Type::Variant;
  }
  assert(type);

  return type;
}