[flang-commits] [flang] 9f7aac1 - [flang] Allow host-associated INTENT(OUT) in specification expr. (#135426)
via flang-commits
flang-commits at lists.llvm.org
Mon Apr 14 09:00:15 PDT 2025
Author: Peter Klausler
Date: 2025-04-14T09:00:12-07:00
New Revision: 9f7aac177cac18e03ca68e2a69e06700250cd3d7
URL: https://github.com/llvm/llvm-project/commit/9f7aac177cac18e03ca68e2a69e06700250cd3d7
DIFF: https://github.com/llvm/llvm-project/commit/9f7aac177cac18e03ca68e2a69e06700250cd3d7.diff
LOG: [flang] Allow host-associated INTENT(OUT) in specification expr. (#135426)
Nearly, but not all, other compilers have a blanket prohibition against
the use of an INTENT(OUT) dummy argument in a specification expression.
Some compilers, however, permit an INTENT(OUT) dummy argument to appear
in a specification expression in a BLOCK construct or inner procedure
via host association.
The argument some have put forth to accept this usage comes from a
reading of 10.1.11 (specification expressions) in Fortran 2023 that, if
followed consistently, would also require host-associated OPTIONAL dummy
argument to be allowed. That would be dangerous for reasons that should
be obvious.
However, I can agree that a non-OPTIONAL dummy argument can't be assumed
to remain undefined on entry to a BLOCK construct or inner procedure, so
we can accept host-associated INTENT(OUT) in specification expressions
with a portability warning.
Added:
Modified:
flang/docs/Extensions.md
flang/include/flang/Support/Fortran-features.h
flang/lib/Evaluate/check-expression.cpp
flang/lib/Support/Fortran-features.cpp
flang/test/Semantics/spec-expr.f90
Removed:
################################################################################
diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md
index d781dee75e07e..05e21ef2d33b5 100644
--- a/flang/docs/Extensions.md
+++ b/flang/docs/Extensions.md
@@ -825,6 +825,19 @@ print *, [(j,j=1,10)]
of these values in violation of the restriction in f23 clause 17.11.42 set
the mode to ieee_nearest.
+* Some compilers allow an `INTENT(OUT)` dummy argument's value to appear
+ via host association in a specification expression. A non-host-associated
+ use is an error because an `INTENT(OUT)` dummy argument's value is not
+ defined. The argument put forth to accept this usage in a `BLOCK` construct
+ or inner procedure is that the language in 10.1.11 (specification expressions)
+ allows any host-associated object to appear, but that's unconvincing
+ because it would also allow a host-associated `OPTIONAL` dummy argument to
+ be used in a nested scope, and that doesn't make sense. This compiler
+ accepts an `INTENT(OUT)` non-`OPTIONAL` host-associated value to appear
+ in a specification expression via host association with a portability
+ warning since such values may have become defined by the time the nested
+ expression's value is required.
+
## De Facto Standard Features
* `EXTENDS_TYPE_OF()` returns `.TRUE.` if both of its arguments have the
diff --git a/flang/include/flang/Support/Fortran-features.h b/flang/include/flang/Support/Fortran-features.h
index 335273100d70e..5b22313754a0f 100644
--- a/flang/include/flang/Support/Fortran-features.h
+++ b/flang/include/flang/Support/Fortran-features.h
@@ -75,7 +75,8 @@ ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,
VectorSubscriptFinalization, UndefinedFunctionResult, UselessIomsg,
MismatchingDummyProcedure, SubscriptedEmptyArray, UnsignedLiteralTruncation,
CompatibleDeclarationsFromDistinctModules,
- NullActualForDefaultIntentAllocatable, UseAssociationIntoSameNameSubprogram)
+ NullActualForDefaultIntentAllocatable, UseAssociationIntoSameNameSubprogram,
+ HostAssociatedIntentOutInSpecExpr)
using LanguageFeatures = EnumSet<LanguageFeature, LanguageFeature_enumSize>;
using UsageWarnings = EnumSet<UsageWarning, UsageWarning_enumSize>;
diff --git a/flang/lib/Evaluate/check-expression.cpp b/flang/lib/Evaluate/check-expression.cpp
index 4d272795ff9bd..78268cd13377a 100644
--- a/flang/lib/Evaluate/check-expression.cpp
+++ b/flang/lib/Evaluate/check-expression.cpp
@@ -545,6 +545,8 @@ class CheckSpecificationExprHelper
!IsAllocatable(ultimate) && object &&
(ultimate.test(Symbol::Flag::InDataStmt) ||
object->init().has_value())};
+ bool hasHostAssociation{
+ &symbol.owner() != &scope_ || &ultimate.owner() != &scope_};
if (const auto *assoc{
ultimate.detailsIf<semantics::AssocEntityDetails>()}) {
return (*this)(assoc->expr());
@@ -563,16 +565,30 @@ class CheckSpecificationExprHelper
} else if (ultimate.attrs().test(semantics::Attr::OPTIONAL)) {
return "reference to OPTIONAL dummy argument '"s +
ultimate.name().ToString() + "'";
- } else if (!inInquiry_ &&
+ } else if (!inInquiry_ && !hasHostAssociation &&
ultimate.attrs().test(semantics::Attr::INTENT_OUT)) {
return "reference to INTENT(OUT) dummy argument '"s +
ultimate.name().ToString() + "'";
- } else if (ultimate.has<semantics::ObjectEntityDetails>()) {
- return std::nullopt;
- } else {
+ } else if (!ultimate.has<semantics::ObjectEntityDetails>()) {
return "dummy procedure argument";
+ } else {
+ // Sketchy case: some compilers allow an INTENT(OUT) dummy argument
+ // to be used in a specification expression if it is host-associated.
+ // The arguments raised in support this usage, however, depend on
+ // a reading of the standard that would also accept an OPTIONAL
+ // host-associated dummy argument, and that doesn't seem like a
+ // good idea.
+ if (!inInquiry_ && hasHostAssociation &&
+ ultimate.attrs().test(semantics::Attr::INTENT_OUT) &&
+ context_.languageFeatures().ShouldWarn(
+ common::UsageWarning::HostAssociatedIntentOutInSpecExpr)) {
+ context_.messages().Say(
+ "specification expression refers to host-associated INTENT(OUT) dummy argument '%s'"_port_en_US,
+ ultimate.name());
+ }
+ return std::nullopt;
}
- } else if (&symbol.owner() != &scope_ || &ultimate.owner() != &scope_) {
+ } else if (hasHostAssociation) {
return std::nullopt; // host association is in play
} else if (isInitialized &&
context_.languageFeatures().IsEnabled(
@@ -582,7 +598,7 @@ class CheckSpecificationExprHelper
common::LanguageFeature::SavedLocalInSpecExpr)) {
context_.messages().Say(common::LanguageFeature::SavedLocalInSpecExpr,
"specification expression refers to local object '%s' (initialized and saved)"_port_en_US,
- ultimate.name().ToString());
+ ultimate.name());
}
return std::nullopt;
} else if (const auto *object{
@@ -831,9 +847,9 @@ bool CheckSpecificationExprHelper::IsPermissibleInquiry(
template <typename A>
void CheckSpecificationExpr(const A &x, const semantics::Scope &scope,
FoldingContext &context, bool forElementalFunctionResult) {
- CheckSpecificationExprHelper helper{
+ CheckSpecificationExprHelper errors{
scope, context, forElementalFunctionResult};
- if (auto why{helper(x)}) {
+ if (auto why{errors(x)}) {
context.messages().Say("Invalid specification expression%s: %s"_err_en_US,
forElementalFunctionResult ? " for elemental function result" : "",
*why);
diff --git a/flang/lib/Support/Fortran-features.cpp b/flang/lib/Support/Fortran-features.cpp
index 4f1af27231301..b3cb62e62f5fb 100644
--- a/flang/lib/Support/Fortran-features.cpp
+++ b/flang/lib/Support/Fortran-features.cpp
@@ -86,6 +86,7 @@ LanguageFeatureControl::LanguageFeatureControl() {
warnUsage_.set(UsageWarning::UnsignedLiteralTruncation);
warnUsage_.set(UsageWarning::NullActualForDefaultIntentAllocatable);
warnUsage_.set(UsageWarning::UseAssociationIntoSameNameSubprogram);
+ warnUsage_.set(UsageWarning::HostAssociatedIntentOutInSpecExpr);
// New warnings, on by default
warnLanguage_.set(LanguageFeature::SavedLocalInSpecExpr);
warnLanguage_.set(LanguageFeature::NullActualForAllocatable);
diff --git a/flang/test/Semantics/spec-expr.f90 b/flang/test/Semantics/spec-expr.f90
index 9d209c3583b43..28ebea1109f1d 100644
--- a/flang/test/Semantics/spec-expr.f90
+++ b/flang/test/Semantics/spec-expr.f90
@@ -28,6 +28,19 @@ subroutine s2(inArg, inoutArg, outArg, optArg)
real, dimension(optArg) :: realVar4
outArg = 3
+ block
+ !PORTABILITY: specification expression refers to host-associated INTENT(OUT) dummy argument 'outarg'
+ real a(outArg)
+ !ERROR: Invalid specification expression: reference to OPTIONAL dummy argument 'optarg'
+ real b(optArg)
+ end block
+ contains
+ subroutine s2inner
+ !PORTABILITY: specification expression refers to host-associated INTENT(OUT) dummy argument 'outarg'
+ real a(outArg)
+ !ERROR: Invalid specification expression: reference to OPTIONAL dummy argument 'optarg'
+ real b(optArg)
+ end
end subroutine s2
! an object designator with a base object that is in a common block,
More information about the flang-commits
mailing list