[flang-commits] [flang] [flang] Add warnings about undefinable actuals for ASYNCHRONOUS/VOLAT… (PR #93851)
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Thu May 30 10:45:32 PDT 2024
https://github.com/klausler created https://github.com/llvm/llvm-project/pull/93851
…ILE dummies
There's language in the standard (F'2023 15.5.2.5 p21) disallowing an actual argument with a vector subscript from associating with a dummy argument with either the ASYNCHRONOUS or VOLATILE attributes. This is a bug in the standard, as (1) these attributes are actually relevant only over the scope of the called procedure, (2) they can be applied in nested scopes (internal subprograms and BLOCK) within the called procedure, and (3) can be implicit within the called procedure and its nested scopes in the case of ASYNCHRONOUS as a side effect of using a dummy argument in an asynchronous data transfer statement. So issue a warning. This new warning about undefinable actual arguments being associated with ASYNCHRONOUS and VOLATILE dummy arguments subsumes an existing warning about passing a constant actual to a VOLATILE dummy.
Resolves https://github.com/llvm/llvm-project/issues/93600.
>From ffa7b4966c32c3b7933135d7088ff44460fb4cc0 Mon Sep 17 00:00:00 2001
From: Peter Klausler <pklausler at nvidia.com>
Date: Thu, 30 May 2024 09:38:45 -0700
Subject: [PATCH] [flang] Add warnings about undefinable actuals for
ASYNCHRONOUS/VOLATILE dummies
There's language in the standard (F'2023 15.5.2.5 p21) disallowing an
actual argument with a vector subscript from associating with a dummy
argument with either the ASYNCHRONOUS or VOLATILE attributes. This is
a bug in the standard, as (1) these attributes are actually relevant only
over the scope of the called procedure, (2) they can be applied in
nested scopes (internal subprograms and BLOCK) within the called procedure,
and (3) can be implicit within the called procedure and its nested
scopes in the case of ASYNCHRONOUS as a side effect of using a dummy
argument in an asynchronous data transfer statement. So issue a warning.
This new warning about undefinable actual arguments being associated with
ASYNCHRONOUS and VOLATILE dummy arguments subsumes an existing warning
about passing a constant actual to a VOLATILE dummy.
Resolves https://github.com/llvm/llvm-project/issues/93600.
---
flang/docs/Extensions.md | 10 +++
flang/include/flang/Common/Fortran-features.h | 8 +--
flang/lib/Semantics/check-call.cpp | 65 ++++++++++---------
flang/test/Semantics/call03.f90 | 8 ++-
flang/test/Semantics/call30.f90 | 45 ++++++++-----
5 files changed, 85 insertions(+), 51 deletions(-)
diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md
index 7b872c786c82c..8afc7dfc89af8 100644
--- a/flang/docs/Extensions.md
+++ b/flang/docs/Extensions.md
@@ -118,6 +118,16 @@ end
procedure interface. This compiler accepts it, since there is otherwise
no way to declare an interoperable dummy procedure with an arbitrary
interface like `void (*)()`.
+* A non-definable actual argument, including the case of a vector
+ subscript, may be associated with an `ASYNCHRONOUS` or `VOLATILE`
+ dummy argument, F'2023 15.5.2.5 p31 notwithstanding.
+ The effects of these attributes are scoped over the lifetime of
+ the procedure reference, and they can by added by internal subprograms
+ and `BLOCK` constructs within the procedure.
+ Further, a dummy argument can acquire the `ASYNCHRONOUS` attribute
+ implicitly simply appearing in an asynchronous data transfer statement,
+ without the attribute being visible in the procedure's explicit
+ interface.
## Extensions, deletions, and legacy features supported by default
diff --git a/flang/include/flang/Common/Fortran-features.h b/flang/include/flang/Common/Fortran-features.h
index 15c4af63f4be7..54ae8c02b69d0 100644
--- a/flang/include/flang/Common/Fortran-features.h
+++ b/flang/include/flang/Common/Fortran-features.h
@@ -50,14 +50,14 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines,
EmptySequenceType, NonSequenceCrayPointee, BranchIntoConstruct,
BadBranchTarget, ConvertedArgument, HollerithPolymorphic, ListDirectedSize,
NonBindCInteroperability, CudaManaged, CudaUnified,
- PolymorphicActualAllocatableOrPointerToMonomorphicDummy)
+ PolymorphicActualAllocatableOrPointerToMonomorphicDummy,
+ UndefinableAsynchronousOrVolatileActual)
// Portability and suspicious usage warnings
ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,
NonTargetPassedToTarget, PointerToPossibleNoncontiguous,
- ShortCharacterActual, ShortArrayActual, ExprPassedToVolatile,
- ImplicitInterfaceActual, PolymorphicTransferArg,
- PointerComponentTransferArg, TransferSizePresence,
+ ShortCharacterActual, ShortArrayActual, ImplicitInterfaceActual,
+ PolymorphicTransferArg, PointerComponentTransferArg, TransferSizePresence,
F202XAllocatableBreakingChange, OptionalMustBePresent, CommonBlockPadding,
LogicalVsCBool, BindCCharLength, ProcDummyArgShapes, ExternalNameConflict,
FoldingException, FoldingAvoidsRuntimeCrash, FoldingValueChecks,
diff --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp
index 48c888c0dfb26..0c6b409827a1b 100644
--- a/flang/lib/Semantics/check-call.cpp
+++ b/flang/lib/Semantics/check-call.cpp
@@ -645,40 +645,44 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
// Definability
bool actualIsVariable{evaluate::IsVariable(actual)};
- const char *reason{nullptr};
- if (dummy.intent == common::Intent::Out) {
- reason = "INTENT(OUT)";
- } else if (dummy.intent == common::Intent::InOut) {
- reason = "INTENT(IN OUT)";
- }
- if (reason && scope) {
- // Problems with polymorphism are caught in the callee's definition.
- DefinabilityFlags flags{DefinabilityFlag::PolymorphicOkInPure};
- if (isElemental) { // 15.5.2.4(21)
- flags.set(DefinabilityFlag::VectorSubscriptIsOk);
- }
- if (actualIsPointer && dummyIsPointer) { // 19.6.8
- flags.set(DefinabilityFlag::PointerDefinition);
+ if (scope) {
+ std::optional<parser::MessageFixedText> undefinableMessage;
+ if (dummy.intent == common::Intent::Out) {
+ undefinableMessage =
+ "Actual argument associated with INTENT(OUT) %s is not definable"_err_en_US;
+ } else if (dummy.intent == common::Intent::InOut) {
+ undefinableMessage =
+ "Actual argument associated with INTENT(IN OUT) %s is not definable"_err_en_US;
+ } else if (context.ShouldWarn(common::LanguageFeature::
+ UndefinableAsynchronousOrVolatileActual)) {
+ if (dummy.attrs.test(
+ characteristics::DummyDataObject::Attr::Asynchronous)) {
+ undefinableMessage =
+ "Actual argument associated with ASYNCHRONOUS %s is not definable"_warn_en_US;
+ } else if (dummy.attrs.test(
+ characteristics::DummyDataObject::Attr::Volatile)) {
+ undefinableMessage =
+ "Actual argument associated with VOLATILE %s is not definable"_warn_en_US;
+ }
}
- if (auto whyNot{WhyNotDefinable(messages.at(), *scope, flags, actual)}) {
- if (auto *msg{messages.Say(
- "Actual argument associated with %s %s is not definable"_err_en_US,
- reason, dummyName)}) {
- msg->Attach(std::move(*whyNot));
+ if (undefinableMessage) {
+ // Problems with polymorphism are caught in the callee's definition.
+ DefinabilityFlags flags{DefinabilityFlag::PolymorphicOkInPure};
+ if (isElemental) { // 15.5.2.4(21)
+ flags.set(DefinabilityFlag::VectorSubscriptIsOk);
+ }
+ if (actualIsPointer && dummyIsPointer) { // 19.6.8
+ flags.set(DefinabilityFlag::PointerDefinition);
+ }
+ if (auto whyNot{WhyNotDefinable(messages.at(), *scope, flags, actual)}) {
+ if (auto *msg{
+ messages.Say(std::move(*undefinableMessage), dummyName)}) {
+ msg->Attach(std::move(*whyNot));
+ }
}
}
}
- // technically legal but worth emitting a warning
- // llvm-project issue #58973: constant actual argument passed in where dummy
- // argument is marked volatile
- if (dummyIsVolatile && !actualIsVariable &&
- context.ShouldWarn(common::UsageWarning::ExprPassedToVolatile)) {
- messages.Say(
- "actual argument associated with VOLATILE %s is not a variable"_warn_en_US,
- dummyName);
- }
-
// Cases when temporaries might be needed but must not be permitted.
bool actualIsContiguous{IsSimplyContiguous(actual, foldingContext)};
bool dummyIsAssumedShape{dummy.type.attrs().test(
@@ -876,7 +880,8 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
dummyName, actual.AsFortran());
}
- // Warn about dubious actual argument association with a TARGET dummy argument
+ // Warn about dubious actual argument association with a TARGET dummy
+ // argument
if (dummy.attrs.test(characteristics::DummyDataObject::Attr::Target) &&
context.ShouldWarn(common::UsageWarning::NonTargetPassedToTarget)) {
bool actualIsTemp{!actualIsVariable || HasVectorSubscript(actual) ||
diff --git a/flang/test/Semantics/call03.f90 b/flang/test/Semantics/call03.f90
index bb7a8cb05c5ac..8f1be1ebff4eb 100644
--- a/flang/test/Semantics/call03.f90
+++ b/flang/test/Semantics/call03.f90
@@ -300,8 +300,12 @@ subroutine test12 ! 15.5.2.4(21)
!ERROR: Actual argument associated with INTENT(IN OUT) dummy argument 'x=' is not definable
!BECAUSE: Variable 'a(int(j,kind=8))' has a vector subscript
call intentinout_arr(a(j))
- call asynchronous_arr(a(j)) ! ok
- call volatile_arr(a(j)) ! ok
+ !WARNING: Actual argument associated with ASYNCHRONOUS dummy argument 'x=' is not definable
+ !BECAUSE: Variable 'a(int(j,kind=8))' has a vector subscript
+ call asynchronous_arr(a(j))
+ !WARNING: Actual argument associated with VOLATILE dummy argument 'x=' is not definable
+ !BECAUSE: Variable 'a(int(j,kind=8))' has a vector subscript
+ call volatile_arr(a(j))
end subroutine
subroutine coarr(x)
diff --git a/flang/test/Semantics/call30.f90 b/flang/test/Semantics/call30.f90
index 3653c29faeeb4..7aec5903606ec 100644
--- a/flang/test/Semantics/call30.f90
+++ b/flang/test/Semantics/call30.f90
@@ -23,35 +23,50 @@ subroutine vol_dum_int_arr(my_int_arr)
end subroutine vol_dum_int_arr
subroutine test_all_subprograms()
- !WARNING: actual argument associated with VOLATILE dummy argument 'my_int=' is not a variable
+ !WARNING: Actual argument associated with VOLATILE dummy argument 'my_int=' is not definable
+ !BECAUSE: '6_4' is not a variable or pointer
call vol_dum_int(6)
- !WARNING: actual argument associated with VOLATILE dummy argument 'my_int=' is not a variable
+ !WARNING: Actual argument associated with VOLATILE dummy argument 'my_int=' is not definable
+ !BECAUSE: '18_4' is not a variable or pointer
call vol_dum_int(6+12)
- !WARNING: actual argument associated with VOLATILE dummy argument 'my_int=' is not a variable
+ !WARNING: Actual argument associated with VOLATILE dummy argument 'my_int=' is not definable
+ !BECAUSE: '72_4' is not a variable or pointer
call vol_dum_int(6*12)
- !WARNING: actual argument associated with VOLATILE dummy argument 'my_int=' is not a variable
+ !WARNING: Actual argument associated with VOLATILE dummy argument 'my_int=' is not definable
+ !BECAUSE: '-3_4' is not a variable or pointer
call vol_dum_int(-6/2)
- !WARNING: actual argument associated with VOLATILE dummy argument 'my_real=' is not a variable
+ !WARNING: Actual argument associated with VOLATILE dummy argument 'my_real=' is not definable
+ !BECAUSE: '3.1415927410125732421875_4' is not a variable or pointer
call vol_dum_real(3.141592653)
- !WARNING: actual argument associated with VOLATILE dummy argument 'my_real=' is not a variable
+ !WARNING: Actual argument associated with VOLATILE dummy argument 'my_real=' is not definable
+ !BECAUSE: '3.1415927410125732421875_4' is not a variable or pointer
call vol_dum_real(3.141592653 + (-10.6e-11))
- !WARNING: actual argument associated with VOLATILE dummy argument 'my_real=' is not a variable
+ !WARNING: Actual argument associated with VOLATILE dummy argument 'my_real=' is not definable
+ !BECAUSE: '3.3300884272335906644002534449100494384765625e-10_4' is not a variable or pointer
call vol_dum_real(3.141592653 * 10.6e-11)
- !WARNING: actual argument associated with VOLATILE dummy argument 'my_real=' is not a variable
+ !WARNING: Actual argument associated with VOLATILE dummy argument 'my_real=' is not definable
+ !BECAUSE: '-2.9637666816e10_4' is not a variable or pointer
call vol_dum_real(3.141592653 / (-10.6e-11))
- !WARNING: actual argument associated with VOLATILE dummy argument 'my_complex=' is not a variable
+ !WARNING: Actual argument associated with VOLATILE dummy argument 'my_complex=' is not definable
+ !BECAUSE: '(1._4,3.2000000476837158203125_4)' is not a variable or pointer
call vol_dum_complex((1., 3.2))
- !WARNING: actual argument associated with VOLATILE dummy argument 'my_complex=' is not a variable
+ !WARNING: Actual argument associated with VOLATILE dummy argument 'my_complex=' is not definable
+ !BECAUSE: '(-1._4,6.340000152587890625_4)' is not a variable or pointer
call vol_dum_complex((1., 3.2) + (-2., 3.14))
- !WARNING: actual argument associated with VOLATILE dummy argument 'my_complex=' is not a variable
+ !WARNING: Actual argument associated with VOLATILE dummy argument 'my_complex=' is not definable
+ !BECAUSE: '(-1.2048000335693359375e1_4,-3.2599999904632568359375_4)' is not a variable or pointer
call vol_dum_complex((1., 3.2) * (-2., 3.14))
- !WARNING: actual argument associated with VOLATILE dummy argument 'my_complex=' is not a variable
+ !WARNING: Actual argument associated with VOLATILE dummy argument 'my_complex=' is not definable
+ !BECAUSE: '(5.80680549144744873046875e-1_4,-6.8833148479461669921875e-1_4)' is not a variable or pointer
call vol_dum_complex((1., 3.2) / (-2., 3.14))
- !WARNING: actual argument associated with VOLATILE dummy argument 'my_int_arr=' is not a variable
+ !WARNING: Actual argument associated with VOLATILE dummy argument 'my_int_arr=' is not definable
+ !BECAUSE: '[INTEGER(4)::1_4,2_4,3_4,4_4]' is not a variable or pointer
call vol_dum_int_arr((/ 1, 2, 3, 4 /))
- !WARNING: actual argument associated with VOLATILE dummy argument 'my_int_arr=' is not a variable
+ !WARNING: Actual argument associated with VOLATILE dummy argument 'my_int_arr=' is not definable
+ !BECAUSE: 'reshape([INTEGER(4)::1_4,2_4,3_4,4_4],shape=[2,2])' is not a variable or pointer
call vol_dum_int_arr(reshape((/ 1, 2, 3, 4 /), (/ 2, 2/)))
- !WARNING: actual argument associated with VOLATILE dummy argument 'my_int_arr=' is not a variable
+ !WARNING: Actual argument associated with VOLATILE dummy argument 'my_int_arr=' is not definable
+ !BECAUSE: '[INTEGER(4)::1_4,2_4,3_4,4_4]' is not a variable or pointer
call vol_dum_int_arr((/ 1, 2, 3, 4 /))
end subroutine test_all_subprograms
end module m
More information about the flang-commits
mailing list