@@ -582,6 +582,7 @@ mlir::Value Fortran::lower::CalleeInterface::getHostAssociatedTuple() const {
582582
583583static void addSymbolAttribute (mlir::func::FuncOp func,
584584 const Fortran::semantics::Symbol &sym,
585+ fir::FortranProcedureFlagsEnumAttr procAttrs,
585586 mlir::MLIRContext &mlirContext) {
586587 const Fortran::semantics::Symbol &ultimate = sym.GetUltimate ();
587588 // The link between an internal procedure and its host procedure is lost
@@ -611,16 +612,8 @@ static void addSymbolAttribute(mlir::func::FuncOp func,
611612 }
612613 }
613614
614- // Set procedure attributes to the func op.
615- if (IsPureProcedure (sym))
616- func->setAttr (fir::getFuncPureAttrName (),
617- mlir::UnitAttr::get (&mlirContext));
618- if (IsElementalProcedure (sym))
619- func->setAttr (fir::getFuncElementalAttrName (),
620- mlir::UnitAttr::get (&mlirContext));
621- if (sym.attrs ().test (Fortran::semantics::Attr::RECURSIVE))
622- func->setAttr (fir::getFuncRecursiveAttrName (),
623- mlir::UnitAttr::get (&mlirContext));
615+ if (procAttrs)
616+ func->setAttr (fir::getFortranProcedureFlagsAttrName (), procAttrs);
624617
625618 // Only add this on bind(C) functions for which the symbol is not reflected in
626619 // the current context.
@@ -703,6 +696,7 @@ void Fortran::lower::CallInterface<T>::declare() {
703696 func = fir::FirOpBuilder::getNamedFunction (module , symbolTable, name);
704697 if (!func) {
705698 mlir::Location loc = side ().getCalleeLocation ();
699+ mlir::MLIRContext &mlirContext = converter.getMLIRContext ();
706700 mlir::FunctionType ty = genFunctionType ();
707701 func =
708702 fir::FirOpBuilder::createFunction (loc, module , name, ty, symbolTable);
@@ -712,7 +706,8 @@ void Fortran::lower::CallInterface<T>::declare() {
712706 mlir::StringAttr::get (&converter.getMLIRContext (),
713707 sym->name ().ToString ()));
714708 } else {
715- addSymbolAttribute (func, *sym, converter.getMLIRContext ());
709+ addSymbolAttribute (func, *sym, getProcedureAttrs (&mlirContext),
710+ mlirContext);
716711 }
717712 }
718713 for (const auto &placeHolder : llvm::enumerate (inputs))
@@ -1550,8 +1545,8 @@ template <typename T>
15501545fir::FortranProcedureFlagsEnumAttr
15511546Fortran::lower::CallInterface<T>::getProcedureAttrs(
15521547 mlir::MLIRContext *mlirContext) const {
1548+ fir::FortranProcedureFlagsEnum flags = fir::FortranProcedureFlagsEnum::none;
15531549 if (characteristic) {
1554- fir::FortranProcedureFlagsEnum flags = fir::FortranProcedureFlagsEnum::none;
15551550 if (characteristic->IsBindC ())
15561551 flags = flags | fir::FortranProcedureFlagsEnum::bind_c;
15571552 if (characteristic->IsPure ())
@@ -1560,12 +1555,27 @@ Fortran::lower::CallInterface<T>::getProcedureAttrs(
15601555 flags = flags | fir::FortranProcedureFlagsEnum::elemental;
15611556 // TODO:
15621557 // - SIMPLE: F2023, not yet handled by semantics.
1563- // - NON_RECURSIVE: not part of the characteristics. Maybe this should
1564- // simply not be part of FortranProcedureFlagsEnum since cannot accurately
1565- // be known on the caller side.
1566- if (flags != fir::FortranProcedureFlagsEnum::none)
1567- return fir::FortranProcedureFlagsEnumAttr::get (mlirContext, flags);
15681558 }
1559+
1560+ if constexpr (std::is_same_v<Fortran::lower::CalleeInterface, T>) {
1561+ // Only gather and set NON_RECURSIVE for procedure definition. It is
1562+ // meaningless on calls since this is not part of Fortran characteristics
1563+ // (Fortran 2023 15.3.1) so there is no way to always know if the procedure
1564+ // called is recursive or not.
1565+ if (const Fortran::semantics::Symbol *sym = side ().getProcedureSymbol ()) {
1566+ // Note: By default procedures are RECURSIVE unless
1567+ // -fno-automatic/-save/-Msave is set. NON_RECURSIVE is is made explicit
1568+ // in that case in FIR.
1569+ if (sym->attrs ().test (Fortran::semantics::Attr::NON_RECURSIVE) ||
1570+ (sym->owner ().context ().languageFeatures ().IsEnabled (
1571+ Fortran::common::LanguageFeature::DefaultSave) &&
1572+ !sym->attrs ().test (Fortran::semantics::Attr::RECURSIVE))) {
1573+ flags = flags | fir::FortranProcedureFlagsEnum::non_recursive;
1574+ }
1575+ }
1576+ }
1577+ if (flags != fir::FortranProcedureFlagsEnum::none)
1578+ return fir::FortranProcedureFlagsEnumAttr::get (mlirContext, flags);
15691579 return nullptr ;
15701580}
15711581
0 commit comments