std::unique_ptr<php::Func> parse_func(ParseUnitState& puState, borrowed_ptr<php::Unit> unit, borrowed_ptr<php::Class> cls, const FuncEmitter& fe) { FTRACE(2, " func: {}\n", fe.name()->data() && *fe.name()->data() ? fe.name()->data() : "pseudomain"); auto ret = folly::make_unique<php::Func>(); ret->name = fe.name(); ret->srcInfo = php::SrcInfo { fe.getLocation(), fe.getDocComment() }; ret->unit = unit; ret->cls = cls; ret->nextBlockId = 0; ret->attrs = fe.attrs(); ret->userAttributes = fe.getUserAttributes(); ret->returnUserType = fe.returnUserType(); ret->originalFilename = fe.originalFilename(); ret->top = fe.top(); ret->isClosureBody = fe.isClosureBody(); ret->isGeneratorBody = fe.isGenerator(); ret->isGeneratorFromClosure = fe.isGeneratorFromClosure(); ret->isPairGenerator = fe.isPairGenerator(); ret->isAsync = fe.isAsync(); ret->innerGeneratorFunc = nullptr; ret->outerGeneratorFunc = nullptr; /* * Generators that aren't inside classes (includes generators from * closures) end up with inner generator bodies living as free * functions, not on a class. We track them here to link them after * we've finished parsing the whole unit. parse_methods handles the * within-class generator linking cases. */ if (auto const innerName = fe.getGeneratorBodyName()) { if (!ret->cls || ret->isClosureBody) { puState.generatorsToLink.emplace_back(borrow(ret), innerName); } } if (ret->isGeneratorBody && !cls) { always_assert(!puState.innerGenerators.count(ret->name)); puState.innerGenerators[ret->name] = borrow(ret); } /* * HNI-style native functions get some extra information. */ if (fe.isHNINative()) { ret->nativeInfo = folly::make_unique<php::NativeInfo>(); ret->nativeInfo->returnType = fe.getReturnType(); } add_frame_variables(*ret, fe); build_cfg(puState, *ret, fe); return ret; }
std::unique_ptr<php::Func> parse_func(ParseUnitState& puState, borrowed_ptr<php::Unit> unit, borrowed_ptr<php::Class> cls, const FuncEmitter& fe) { FTRACE(2, " func: {}\n", fe.name()->data() && *fe.name()->data() ? fe.name()->data() : "pseudomain"); auto ret = folly::make_unique<php::Func>(); ret->name = fe.name(); ret->srcInfo = php::SrcInfo { fe.getLocation(), fe.getDocComment() }; ret->unit = unit; ret->cls = cls; // Note: probably need to clear AttrLeaf here eventually. ret->attrs = fe.attrs(); ret->userAttributes = fe.getUserAttributes(); ret->userRetTypeConstraint = fe.returnTypeConstraint(); ret->originalFilename = fe.originalFilename(); ret->top = fe.top(); ret->isClosureBody = fe.isClosureBody(); ret->isGeneratorBody = fe.isGenerator(); ret->isGeneratorFromClosure = fe.isGeneratorFromClosure(); ret->isPairGenerator = fe.isPairGenerator(); ret->hasGeneratorAsBody = fe.hasGeneratorAsBody(); ret->nextBlockId = 0; add_frame_variables(*ret, fe); build_cfg(puState, *ret, fe); return ret; }
std::unique_ptr<php::Func> parse_func(ParseUnitState& puState, borrowed_ptr<php::Unit> unit, borrowed_ptr<php::Class> cls, const FuncEmitter& fe) { FTRACE(2, " func: {}\n", fe.name->data() && *fe.name->data() ? fe.name->data() : "pseudomain"); auto ret = folly::make_unique<php::Func>(); ret->name = fe.name; ret->srcInfo = php::SrcInfo { fe.getLocation(), fe.docComment }; ret->unit = unit; ret->cls = cls; ret->nextBlockId = 0; ret->attrs = static_cast<Attr>(fe.attrs & ~AttrNoOverride); ret->userAttributes = fe.userAttributes; ret->returnUserType = fe.retUserType; ret->retTypeConstraint = fe.retTypeConstraint; ret->originalFilename = fe.originalFilename; ret->top = fe.top; ret->isClosureBody = fe.isClosureBody; ret->isAsync = fe.isAsync; ret->isGenerator = fe.isGenerator; ret->isPairGenerator = fe.isPairGenerator; ret->isNative = fe.isNative; /* * Builtin functions get some extra information. The returnType flag is only * non-folly::none for these, but note that something may be a builtin and * still have a folly::none return type. */ if (fe.attrs & AttrBuiltin) { ret->nativeInfo = folly::make_unique<php::NativeInfo>(); ret->nativeInfo->returnType = fe.returnType; } add_frame_variables(*ret, fe); build_cfg(puState, *ret, fe); return ret; }
std::unique_ptr<php::Func> parse_func(ParseUnitState& puState, borrowed_ptr<php::Unit> unit, borrowed_ptr<php::Class> cls, const FuncEmitter& fe) { FTRACE(2, " func: {}\n", fe.name()->data() && *fe.name()->data() ? fe.name()->data() : "pseudomain"); auto ret = folly::make_unique<php::Func>(); ret->name = fe.name(); ret->srcInfo = php::SrcInfo { fe.getLocation(), fe.getDocComment() }; ret->unit = unit; ret->cls = cls; ret->nextBlockId = 0; ret->attrs = fe.attrs(); ret->userAttributes = fe.getUserAttributes(); ret->returnUserType = fe.returnUserType(); ret->originalFilename = fe.originalFilename(); ret->top = fe.top(); ret->isClosureBody = fe.isClosureBody(); ret->isGeneratorBody = fe.isGenerator(); ret->isGeneratorFromClosure = fe.isGeneratorFromClosure(); ret->isPairGenerator = fe.isPairGenerator(); ret->isAsync = fe.isAsync(); ret->generatorBodyName = fe.getGeneratorBodyName(); /* * HNI-style native functions get some extra information. */ if (fe.isHNINative()) { ret->nativeInfo = folly::make_unique<php::NativeInfo>(); ret->nativeInfo->returnType = fe.getReturnType(); } add_frame_variables(*ret, fe); build_cfg(puState, *ret, fe); return ret; }
std::unique_ptr<php::Func> parse_func(ParseUnitState& puState, borrowed_ptr<php::Unit> unit, borrowed_ptr<php::Class> cls, const FuncEmitter& fe) { FTRACE(2, " func: {}\n", fe.name->data() && *fe.name->data() ? fe.name->data() : "pseudomain"); auto ret = folly::make_unique<php::Func>(); ret->name = fe.name; ret->srcInfo = php::SrcInfo { fe.getLocation(), fe.docComment }; ret->unit = unit; ret->cls = cls; ret->attrs = static_cast<Attr>(fe.attrs & ~AttrNoOverride); ret->userAttributes = fe.userAttributes; ret->returnUserType = fe.retUserType; ret->retTypeConstraint = fe.retTypeConstraint; ret->originalFilename = fe.originalFilename; ret->top = fe.top; ret->isClosureBody = fe.isClosureBody; ret->isAsync = fe.isAsync; ret->isGenerator = fe.isGenerator; ret->isPairGenerator = fe.isPairGenerator; ret->isMemoizeWrapper = fe.isMemoizeWrapper; add_frame_variables(*ret, fe); /* * Builtin functions get some extra information. The returnType flag is only * non-folly::none for these, but note that something may be a builtin and * still have a folly::none return type. */ if (fe.isNative) { auto const f = [&] () -> HPHP::Func* { if (ret->cls) { auto const cls = Unit::lookupClass(ret->cls->name); return cls ? cls->lookupMethod(ret->name) : nullptr; } else { return Unit::lookupFunc(ret->name); } }(); ret->nativeInfo = folly::make_unique<php::NativeInfo>(); ret->nativeInfo->returnType = fe.hniReturnType; ret->nativeInfo->dynCallWrapperId = fe.dynCallWrapperId; if (f && !ret->cls && ret->params.size()) { // There are a handful of functions whose first parameter is by // ref, but which don't require a reference. There is also // array_multisort, which has this property for all its // parameters; but that if (ret->params[0].byRef && !f->mustBeRef(0)) { ret->params[0].mustBeRef = false; } } if (!f || !f->nativeFuncPtr() || (f->userAttributes().count( LowStringPtr(s_attr_Deprecated.get())))) { ret->attrs |= AttrNoFCallBuiltin; } } build_cfg(puState, *ret, fe); return ret; }