Skip to content

Commit 3dbe8ca

Browse files
akuhlensgithub-actions[bot]
authored andcommitted
Automerge: [flang][semantic] update semantic checks for ansychronous and volatility attributes to use MayNeedCopy (#159477)
Ties the semantic checks for overwriting a asynchronous or volatile value with a copy-out operation to the function `evaluate::MayNeedCopy(..., /*forCopyOut=*/false)`. This should make the checks more accurate and consistent with the lowering. The PR also adds a default check that looks for the undesired behavior directly, in case extension later modify what is possible. A couple portability warnings are added where other compilers are over restrictive. Closes llvm/llvm-project#137369 ``` $ build/bin/flang -c ~/work/llvm-test-suite/Fortran/gfortran/regression/volatile8.f90 -pedantic /home/akuhlenschmi/work/llvm-test-suite/Fortran/gfortran/regression/volatile8.f90:21:16: warning: The array section 'a(1_8:5_8:2_8)' should not be associated with dummy argument 'dummy8=' with VOLATILE attribute, unless the dummy is assumed-shape or assumed-rank [-Wvolatile-or-asynchronous-temporary] call sub8 (a(1:5:2)) ! { dg-error "Array-section actual argument" } ^^^^^^^^ /home/akuhlenschmi/work/llvm-test-suite/Fortran/gfortran/regression/volatile8.f90:37:16: portability: The actual argument 's9dummy' should not be associated with dummy argument 'dummy9=' with VOLATILE attribute, because a temporary copy is required during the call [-Wportability] call sub9 (s9dummy) ! { dg-error "Assumed-shape actual argument" } ^^^^^^^ /home/akuhlenschmi/work/llvm-test-suite/Fortran/gfortran/regression/volatile8.f90:55:17: portability: The actual argument 'a' should not be associated with dummy argument 'dummy10=' with VOLATILE attribute, because a temporary copy is required during the call [-Wportability] call sub10 (a) ! { dg-error "Pointer-array actual argument" } ^ ```
2 parents ab26a37 + 43e4757 commit 3dbe8ca

File tree

5 files changed

+73
-13
lines changed

5 files changed

+73
-13
lines changed

flang/include/flang/Support/Fortran-features.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,
7979
CompatibleDeclarationsFromDistinctModules,
8080
NullActualForDefaultIntentAllocatable, UseAssociationIntoSameNameSubprogram,
8181
HostAssociatedIntentOutInSpecExpr, NonVolatilePointerToVolatile,
82-
RealConstantWidening)
82+
RealConstantWidening, VolatileOrAsynchronousTemporary)
8383

8484
using LanguageFeatures = EnumSet<LanguageFeature, LanguageFeature_enumSize>;
8585
using UsageWarnings = EnumSet<UsageWarning, UsageWarning_enumSize>;

flang/lib/Semantics/check-call.cpp

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,8 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
330330
const Scope *scope, const evaluate::SpecificIntrinsic *intrinsic,
331331
bool allowActualArgumentConversions, bool extentErrors,
332332
const characteristics::Procedure &procedure,
333-
const evaluate::ActualArgument &arg) {
333+
const evaluate::ActualArgument &arg,
334+
const characteristics::DummyArgument &dummyArg) {
334335

335336
// Basic type & rank checking
336337
parser::ContextualMessages &messages{foldingContext.messages()};
@@ -357,6 +358,9 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
357358
bool typesCompatible{typesCompatibleWithIgnoreTKR ||
358359
dummy.type.type().IsTkCompatibleWith(actualType.type())};
359360
int dummyRank{dummy.type.Rank()};
361+
// Used to issue a general warning when we don't generate a specific warning
362+
// or error for this case.
363+
bool volatileOrAsyncNeedsTempDiagnosticIssued{false};
360364
if (typesCompatible) {
361365
if (const auto *constantChar{
362366
evaluate::UnwrapConstantValue<evaluate::Ascii>(actual)};
@@ -742,6 +746,7 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
742746
if (whyNot->IsFatal()) {
743747
if (auto *msg{messages.Say(*undefinableMessage, dummyName)}) {
744748
if (!msg->IsFatal()) {
749+
volatileOrAsyncNeedsTempDiagnosticIssued = true;
745750
msg->set_languageFeature(common::LanguageFeature::
746751
UndefinableAsynchronousOrVolatileActual);
747752
}
@@ -770,12 +775,16 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
770775
// Cases when temporaries might be needed but must not be permitted.
771776
bool dummyIsAssumedShape{dummy.type.attrs().test(
772777
characteristics::TypeAndShape::Attr::AssumedShape)};
773-
if (!dummyIsValue && (dummyIsAsynchronous || dummyIsVolatile)) {
778+
bool copyOutNeeded{
779+
evaluate::MayNeedCopy(&arg, &dummyArg, foldingContext, true)};
780+
if (copyOutNeeded && !dummyIsValue &&
781+
(dummyIsAsynchronous || dummyIsVolatile)) {
774782
if (actualIsAsynchronous || actualIsVolatile) {
775783
if (actualCoarrayRef) { // F'2023 C1547
776784
messages.Say(
777785
"Coindexed ASYNCHRONOUS or VOLATILE actual argument may not be associated with %s with ASYNCHRONOUS or VOLATILE attributes unless VALUE"_err_en_US,
778786
dummyName);
787+
volatileOrAsyncNeedsTempDiagnosticIssued = true;
779788
}
780789
if ((actualRank > 0 || actualIsAssumedRank) && !actualIsContiguous) {
781790
if (dummyIsContiguous ||
@@ -784,22 +793,67 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
784793
messages.Say(
785794
"ASYNCHRONOUS or VOLATILE actual argument that is not simply contiguous may not be associated with a contiguous ASYNCHRONOUS or VOLATILE %s"_err_en_US,
786795
dummyName);
796+
volatileOrAsyncNeedsTempDiagnosticIssued = true;
787797
}
788798
}
789-
// The vector subscript case is handled by the definability check above.
790-
// The copy-in/copy-out cases are handled by the previous checks.
791-
// Nag, GFortran, and NVFortran all error on this case, even though it is
792-
// ok, prossibly as an over-restriction of C1548.
793799
} else if (!(dummyIsAssumedShape || dummyIsAssumedRank ||
794800
(actualIsPointer && dummyIsPointer)) &&
801+
evaluate::IsArraySection(actual) && !actualIsContiguous &&
802+
!evaluate::HasVectorSubscript(actual)) {
803+
context.Warn(common::UsageWarning::VolatileOrAsynchronousTemporary,
804+
messages.at(),
805+
"The array section '%s' should not be associated with %s with %s attribute, unless the dummy is assumed-shape or assumed-rank"_warn_en_US,
806+
actual.AsFortran(), dummyName,
807+
dummyIsAsynchronous ? "ASYNCHRONOUS" : "VOLATILE");
808+
volatileOrAsyncNeedsTempDiagnosticIssued = true;
809+
}
810+
}
811+
// General implementation of F'23 15.5.2.5 note 5
812+
// Adds a less specific error message for any copy-out that could overwrite
813+
// a unread value in the actual argument.
814+
// Occurences of volatileOrAsyncNeedsTempDiagnosticIssued = true indicate a
815+
// more specific error message has already been issued. We might be able to
816+
// clean this up by switching the coding style of MayNeedCopy to be more like
817+
// WhyNotDefinable.
818+
if (copyOutNeeded && !volatileOrAsyncNeedsTempDiagnosticIssued) {
819+
if ((actualIsVolatile || actualIsAsynchronous) &&
820+
(dummyIsVolatile || dummyIsAsynchronous)) {
821+
context.Warn(common::UsageWarning::VolatileOrAsynchronousTemporary,
822+
messages.at(),
823+
"The actual argument '%s' with %s attribute should not be associated with %s with %s attribute, because a temporary copy is required during the call"_warn_en_US,
824+
actual.AsFortran(), actualIsVolatile ? "VOLATILE" : "ASYNCHRONOUS",
825+
dummyName, dummyIsVolatile ? "VOLATILE" : "ASYNCHRONOUS");
826+
}
827+
}
828+
// If there are any cases where we don't need a copy and some other compiler
829+
// does, we issue a portability warning here.
830+
if (context.ShouldWarn(common::UsageWarning::Portability)) {
831+
// Nag, GFortran, and NVFortran all error on this case, even though it is
832+
// ok, prossibly as an over-restriction of F'23 C1548.
833+
if (!copyOutNeeded && !volatileOrAsyncNeedsTempDiagnosticIssued &&
834+
(!dummyIsValue && (dummyIsAsynchronous || dummyIsVolatile)) &&
835+
!(actualIsAsynchronous || actualIsVolatile) &&
836+
!(dummyIsAssumedShape || dummyIsAssumedRank ||
837+
(actualIsPointer && dummyIsPointer)) &&
795838
evaluate::IsArraySection(actual) &&
796839
!evaluate::HasVectorSubscript(actual)) {
797840
context.Warn(common::UsageWarning::Portability, messages.at(),
798841
"The array section '%s' should not be associated with %s with %s attribute, unless the dummy is assumed-shape or assumed-rank"_port_en_US,
799842
actual.AsFortran(), dummyName,
800843
dummyIsAsynchronous ? "ASYNCHRONOUS" : "VOLATILE");
801844
}
845+
// Probably an over-restriction of F'23 15.5.2.5 note 5
846+
if (copyOutNeeded && !volatileOrAsyncNeedsTempDiagnosticIssued) {
847+
if ((dummyIsVolatile && !actualIsVolatile && !actualIsAsynchronous) ||
848+
(dummyIsAsynchronous && !actualIsVolatile && !actualIsAsynchronous)) {
849+
context.Warn(common::UsageWarning::Portability, messages.at(),
850+
"The actual argument '%s' should not be associated with %s with %s attribute, because a temporary copy is required during the call"_port_en_US,
851+
actual.AsFortran(), dummyName,
852+
dummyIsVolatile ? "VOLATILE" : "ASYNCHRONOUS");
853+
}
854+
}
802855
}
856+
803857
// 15.5.2.6 -- dummy is ALLOCATABLE
804858
bool dummyIsOptional{
805859
dummy.attrs.test(characteristics::DummyDataObject::Attr::Optional)};
@@ -1302,7 +1356,8 @@ static void CheckExplicitInterfaceArg(evaluate::ActualArgument &arg,
13021356
object.type.Rank() == 0 && proc.IsElemental()};
13031357
CheckExplicitDataArg(object, dummyName, *expr, *type,
13041358
isElemental, context, foldingContext, scope, intrinsic,
1305-
allowActualArgumentConversions, extentErrors, proc, arg);
1359+
allowActualArgumentConversions, extentErrors, proc, arg,
1360+
dummy);
13061361
} else if (object.type.type().IsTypelessIntrinsicArgument() &&
13071362
IsBOZLiteral(*expr)) {
13081363
// ok

flang/test/Semantics/call03.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic
1+
! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic -Wno-portability
22
! Test 15.5.2.4 constraints and restrictions for non-POINTER non-ALLOCATABLE
33
! dummy arguments.
44

flang/test/Semantics/call44.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic -Werror
1+
! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic -Wno-portability -Werror
22
subroutine assumedshape(normal, contig)
33
real normal(:)
44
real, contiguous :: contig(:)

flang/test/Semantics/call45.f90

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ program call45
77
call sub(v([1,2,2,3,3,3,4,4,4,4]))
88
!PORTABILITY: The array section 'v(21_8:30_8:1_8)' should not be associated with dummy argument 'v=' with VOLATILE attribute, unless the dummy is assumed-shape or assumed-rank [-Wportability]
99
call sub(v(21:30))
10-
!PORTABILITY: The array section 'v(21_8:40_8:2_8)' should not be associated with dummy argument 'v=' with VOLATILE attribute, unless the dummy is assumed-shape or assumed-rank [-Wportability]
10+
!WARNING: The array section 'v(21_8:40_8:2_8)' should not be associated with dummy argument 'v=' with VOLATILE attribute, unless the dummy is assumed-shape or assumed-rank [-Wvolatile-or-asynchronous-temporary]
1111
call sub(v(21:40:2))
1212
call sub2(v(21:40:2))
1313
call sub4(p)
14+
call sub5(p)
1415
print *, v
1516
contains
1617
subroutine sub(v)
@@ -23,7 +24,7 @@ subroutine sub1(v)
2324
end subroutine sub1
2425
subroutine sub2(v)
2526
integer :: v(:)
26-
!TODO: This should either be an portability warning or copy-in-copy-out warning
27+
!PORTABILITY: The actual argument 'v' should not be associated with dummy argument 'v=' with VOLATILE attribute, because a temporary copy is required during the call [-Wportability]
2728
call sub(v)
2829
call sub1(v)
2930
end subroutine sub2
@@ -33,9 +34,13 @@ subroutine sub3(v)
3334
end subroutine sub3
3435
subroutine sub4(v)
3536
integer, pointer :: v(:)
36-
!TODO: This should either be a portability warning or copy-in-copy-out warning
37+
!PORTABILITY: The actual argument 'v' should not be associated with dummy argument 'v=' with VOLATILE attribute, because a temporary copy is required during the call [-Wportability]
3738
call sub(v)
3839
call sub1(v)
3940
call sub3(v)
41+
call sub5(v)
4042
end subroutine sub4
43+
subroutine sub5(v)
44+
integer, pointer, volatile :: v(:)
45+
end subroutine sub5
4146
end program call45

0 commit comments

Comments
 (0)