Index: flang/lib/Evaluate/type.cpp =================================================================== --- flang/lib/Evaluate/type.cpp +++ flang/lib/Evaluate/type.cpp @@ -48,9 +48,8 @@ } static bool IsDescriptor(const ProcEntityDetails &details) { - // A procedure pointer or dummy procedure must be & is a descriptor if - // and only if it requires a static link. - // TODO: refine this placeholder + // TODO: refine this placeholder; procedure pointers and dummy + // procedures should now be simple addresses (possibly of thunks) return details.HasExplicitInterface(); } @@ -93,6 +92,9 @@ if (!IsDescriptor(symbol)) { return false; } + if (IsAllocatableOrPointer(symbol)) { + return true; + } if (const auto *object{ symbol.GetUltimate().detailsIf()}) { if (object->isDummy()) { Index: flang/lib/Semantics/check-declarations.cpp =================================================================== --- flang/lib/Semantics/check-declarations.cpp +++ flang/lib/Semantics/check-declarations.cpp @@ -703,27 +703,44 @@ } } if (auto ignoreTKR{GetIgnoreTKR(symbol)}; !ignoreTKR.empty()) { - if (IsAllocatableOrPointer(symbol)) { + const Symbol *ownerSymbol{symbol.owner().symbol()}; + const auto *ownerSubp{ownerSymbol->detailsIf()}; + bool inInterface{ownerSubp && ownerSubp->isInterface()}; + bool inExplicitInterface{ + inInterface && !IsSeparateModuleProcedureInterface(ownerSymbol)}; + bool inModuleProc{ + !inInterface && ownerSymbol && IsModuleProcedure(*ownerSymbol)}; + if (!inExplicitInterface && !inModuleProc) { messages_.Say( - "!DIR$ IGNORE_TKR may not apply to an allocatable or pointer"_err_en_US); - } else if (ignoreTKR.test(common::IgnoreTKR::Contiguous) && + "!DIR$ IGNORE_TKR may apply only in an interface or a module procedure"_err_en_US); + } + if (ignoreTKR.test(common::IgnoreTKR::Contiguous) && !IsAssumedShape(symbol)) { messages_.Say( "!DIR$ IGNORE_TKR(C) may apply only to an assumed-shape array"_err_en_US); - } else if (ignoreTKR.test(common::IgnoreTKR::Rank) && - IsPassedViaDescriptor(symbol)) { + } + if (ownerSymbol && ownerSymbol->attrs().test(Attr::ELEMENTAL) && + details.ignoreTKR().test(common::IgnoreTKR::Rank)) { messages_.Say( - "!DIR$ IGNORE_TKR(R) may not apply to a dummy argument passed via descriptor"_err_en_US); - } else if (const Symbol * ownerSymbol{symbol.owner().symbol()}) { - if (const auto *ownerSubp{ownerSymbol->detailsIf()}; - ownerSubp && !ownerSubp->isInterface() && - !FindModuleContaining(symbol.owner())) { - messages_.Say( - "!DIR$ IGNORE_TKR may apply only in an interface or a module procedure"_err_en_US); - } else if (ownerSymbol->attrs().test(Attr::ELEMENTAL) && - details.ignoreTKR().test(common::IgnoreTKR::Rank)) { - messages_.Say( - "!DIR$ IGNORE_TKR(R) may not apply in an ELEMENTAL procedure"_err_en_US); + "!DIR$ IGNORE_TKR(R) may not apply in an ELEMENTAL procedure"_err_en_US); + } + if (IsPassedViaDescriptor(symbol)) { + if (IsAllocatableOrPointer(symbol)) { + if (inInterface) { + messages_.Say( + "!DIR$ IGNORE_TKR should not apply to an allocatable or pointer"_warn_en_US); + } else { + messages_.Say( + "!DIR$ IGNORE_TKR may not apply to an allocatable or pointer"_err_en_US); + } + } else if (ignoreTKR.test(common::IgnoreTKR::Rank)) { + if (inInterface) { + messages_.Say( + "!DIR$ IGNORE_TKR(R) should not apply to a dummy argument passed via descriptor"_warn_en_US); + } else { + messages_.Say( + "!DIR$ IGNORE_TKR(R) may not apply to a dummy argument passed via descriptor"_err_en_US); + } } } } Index: flang/test/Semantics/ignore_tkr01.f90 =================================================================== --- flang/test/Semantics/ignore_tkr01.f90 +++ flang/test/Semantics/ignore_tkr01.f90 @@ -53,13 +53,13 @@ subroutine t9(x) !dir$ ignore_tkr x -!ERROR: !DIR$ IGNORE_TKR may not apply to an allocatable or pointer +!WARNING: !DIR$ IGNORE_TKR should not apply to an allocatable or pointer real, intent(in), allocatable :: x end subroutine t10(x) !dir$ ignore_tkr x -!ERROR: !DIR$ IGNORE_TKR may not apply to an allocatable or pointer +!WARNING: !DIR$ IGNORE_TKR should not apply to an allocatable or pointer real, intent(in), pointer :: x end @@ -89,6 +89,18 @@ end interface contains + subroutine t9a(x) +!dir$ ignore_tkr x +!ERROR: !DIR$ IGNORE_TKR may not apply to an allocatable or pointer + real, intent(in), allocatable :: x + end + + subroutine t10a(x) +!dir$ ignore_tkr x +!ERROR: !DIR$ IGNORE_TKR may not apply to an allocatable or pointer + real, intent(in), pointer :: x + end + subroutine t14(x) real x x = x + 1. @@ -128,7 +140,7 @@ subroutine t19(x) !dir$ ignore_tkr(r) x -!ERROR: !DIR$ IGNORE_TKR(R) may not apply to a dummy argument passed via descriptor +!WARNING: !DIR$ IGNORE_TKR(R) may not apply to a dummy argument passed via descriptor real x(..) end