-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[flang] Allow host-associated INTENT(OUT) in specification expr. #135426
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
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.
@llvm/pr-subscribers-flang-semantics Author: Peter Klausler (klausler) ChangesNearly, 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. Full diff: https://github.com/llvm/llvm-project/pull/135426.diff 5 Files Affected:
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,
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
…m#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.
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.