@@ -582,6 +582,7 @@ mlir::Value Fortran::lower::CalleeInterface::getHostAssociatedTuple() const {
582
582
583
583
static void addSymbolAttribute (mlir::func::FuncOp func,
584
584
const Fortran::semantics::Symbol &sym,
585
+ fir::FortranProcedureFlagsEnumAttr procAttrs,
585
586
mlir::MLIRContext &mlirContext) {
586
587
const Fortran::semantics::Symbol &ultimate = sym.GetUltimate ();
587
588
// The link between an internal procedure and its host procedure is lost
@@ -611,16 +612,8 @@ static void addSymbolAttribute(mlir::func::FuncOp func,
611
612
}
612
613
}
613
614
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);
624
617
625
618
// Only add this on bind(C) functions for which the symbol is not reflected in
626
619
// the current context.
@@ -703,6 +696,7 @@ void Fortran::lower::CallInterface<T>::declare() {
703
696
func = fir::FirOpBuilder::getNamedFunction (module , symbolTable, name);
704
697
if (!func) {
705
698
mlir::Location loc = side ().getCalleeLocation ();
699
+ mlir::MLIRContext &mlirContext = converter.getMLIRContext ();
706
700
mlir::FunctionType ty = genFunctionType ();
707
701
func =
708
702
fir::FirOpBuilder::createFunction (loc, module , name, ty, symbolTable);
@@ -712,7 +706,8 @@ void Fortran::lower::CallInterface<T>::declare() {
712
706
mlir::StringAttr::get (&converter.getMLIRContext (),
713
707
sym->name ().ToString ()));
714
708
} else {
715
- addSymbolAttribute (func, *sym, converter.getMLIRContext ());
709
+ addSymbolAttribute (func, *sym, getProcedureAttrs (&mlirContext),
710
+ mlirContext);
716
711
}
717
712
}
718
713
for (const auto &placeHolder : llvm::enumerate (inputs))
@@ -1550,8 +1545,8 @@ template <typename T>
1550
1545
fir::FortranProcedureFlagsEnumAttr
1551
1546
Fortran::lower::CallInterface<T>::getProcedureAttrs(
1552
1547
mlir::MLIRContext *mlirContext) const {
1548
+ fir::FortranProcedureFlagsEnum flags = fir::FortranProcedureFlagsEnum::none;
1553
1549
if (characteristic) {
1554
- fir::FortranProcedureFlagsEnum flags = fir::FortranProcedureFlagsEnum::none;
1555
1550
if (characteristic->IsBindC ())
1556
1551
flags = flags | fir::FortranProcedureFlagsEnum::bind_c;
1557
1552
if (characteristic->IsPure ())
@@ -1560,12 +1555,27 @@ Fortran::lower::CallInterface<T>::getProcedureAttrs(
1560
1555
flags = flags | fir::FortranProcedureFlagsEnum::elemental;
1561
1556
// TODO:
1562
1557
// - 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);
1568
1558
}
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);
1569
1579
return nullptr ;
1570
1580
}
1571
1581
0 commit comments