Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion flang/include/flang/Support/Fortran-features.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,
CompatibleDeclarationsFromDistinctModules,
NullActualForDefaultIntentAllocatable, UseAssociationIntoSameNameSubprogram,
HostAssociatedIntentOutInSpecExpr, NonVolatilePointerToVolatile,
RealConstantWidening)
RealConstantWidening, VolatileOrAsynchronousTemporary)

using LanguageFeatures = EnumSet<LanguageFeature, LanguageFeature_enumSize>;
using UsageWarnings = EnumSet<UsageWarning, UsageWarning_enumSize>;
Expand Down
69 changes: 62 additions & 7 deletions flang/lib/Semantics/check-call.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,8 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
const Scope *scope, const evaluate::SpecificIntrinsic *intrinsic,
bool allowActualArgumentConversions, bool extentErrors,
const characteristics::Procedure &procedure,
const evaluate::ActualArgument &arg) {
const evaluate::ActualArgument &arg,
const characteristics::DummyArgument &dummyArg) {

// Basic type & rank checking
parser::ContextualMessages &messages{foldingContext.messages()};
Expand All @@ -357,6 +358,9 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
bool typesCompatible{typesCompatibleWithIgnoreTKR ||
dummy.type.type().IsTkCompatibleWith(actualType.type())};
int dummyRank{dummy.type.Rank()};
// Used to issue a general warning when we don't generate a specific warning
// or error for this case.
bool volatileOrAsyncNeedsTempDiagnosticIssued{false};
if (typesCompatible) {
if (const auto *constantChar{
evaluate::UnwrapConstantValue<evaluate::Ascii>(actual)};
Expand Down Expand Up @@ -742,6 +746,7 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
if (whyNot->IsFatal()) {
if (auto *msg{messages.Say(*undefinableMessage, dummyName)}) {
if (!msg->IsFatal()) {
volatileOrAsyncNeedsTempDiagnosticIssued = true;
msg->set_languageFeature(common::LanguageFeature::
UndefinableAsynchronousOrVolatileActual);
}
Expand Down Expand Up @@ -770,12 +775,16 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
// Cases when temporaries might be needed but must not be permitted.
bool dummyIsAssumedShape{dummy.type.attrs().test(
characteristics::TypeAndShape::Attr::AssumedShape)};
if (!dummyIsValue && (dummyIsAsynchronous || dummyIsVolatile)) {
bool copyOutNeeded{
evaluate::MayNeedCopy(&arg, &dummyArg, foldingContext, true)};
if (copyOutNeeded && !dummyIsValue &&
(dummyIsAsynchronous || dummyIsVolatile)) {
if (actualIsAsynchronous || actualIsVolatile) {
if (actualCoarrayRef) { // F'2023 C1547
messages.Say(
"Coindexed ASYNCHRONOUS or VOLATILE actual argument may not be associated with %s with ASYNCHRONOUS or VOLATILE attributes unless VALUE"_err_en_US,
dummyName);
volatileOrAsyncNeedsTempDiagnosticIssued = true;
}
if ((actualRank > 0 || actualIsAssumedRank) && !actualIsContiguous) {
if (dummyIsContiguous ||
Expand All @@ -784,22 +793,67 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
messages.Say(
"ASYNCHRONOUS or VOLATILE actual argument that is not simply contiguous may not be associated with a contiguous ASYNCHRONOUS or VOLATILE %s"_err_en_US,
dummyName);
volatileOrAsyncNeedsTempDiagnosticIssued = true;
}
}
// The vector subscript case is handled by the definability check above.
// The copy-in/copy-out cases are handled by the previous checks.
// Nag, GFortran, and NVFortran all error on this case, even though it is
// ok, prossibly as an over-restriction of C1548.
} else if (!(dummyIsAssumedShape || dummyIsAssumedRank ||
(actualIsPointer && dummyIsPointer)) &&
evaluate::IsArraySection(actual) && !actualIsContiguous &&
!evaluate::HasVectorSubscript(actual)) {
context.Warn(common::UsageWarning::VolatileOrAsynchronousTemporary,
messages.at(),
"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,
actual.AsFortran(), dummyName,
dummyIsAsynchronous ? "ASYNCHRONOUS" : "VOLATILE");
volatileOrAsyncNeedsTempDiagnosticIssued = true;
}
}
// General implementation of F'23 15.5.2.5 note 5
// Adds a less specific error message for any copy-out that could overwrite
// a unread value in the actual argument.
// Occurences of volatileOrAsyncNeedsTempDiagnosticIssued = true indicate a
// more specific error message has already been issued. We might be able to
// clean this up by switching the coding style of MayNeedCopy to be more like
// WhyNotDefinable.
if (copyOutNeeded && !volatileOrAsyncNeedsTempDiagnosticIssued) {
if ((actualIsVolatile || actualIsAsynchronous) &&
(dummyIsVolatile || dummyIsAsynchronous)) {
context.Warn(common::UsageWarning::VolatileOrAsynchronousTemporary,
messages.at(),
"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,
actual.AsFortran(), actualIsVolatile ? "VOLATILE" : "ASYNCHRONOUS",
dummyName, dummyIsVolatile ? "VOLATILE" : "ASYNCHRONOUS");
}
}
// If there are any cases where we don't need a copy and some other compiler
// does, we issue a portability warning here.
if (context.ShouldWarn(common::UsageWarning::Portability)) {
// Nag, GFortran, and NVFortran all error on this case, even though it is
// ok, prossibly as an over-restriction of F'23 C1548.
if (!copyOutNeeded && !volatileOrAsyncNeedsTempDiagnosticIssued &&
(!dummyIsValue && (dummyIsAsynchronous || dummyIsVolatile)) &&
!(actualIsAsynchronous || actualIsVolatile) &&
!(dummyIsAssumedShape || dummyIsAssumedRank ||
(actualIsPointer && dummyIsPointer)) &&
evaluate::IsArraySection(actual) &&
!evaluate::HasVectorSubscript(actual)) {
context.Warn(common::UsageWarning::Portability, messages.at(),
"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,
actual.AsFortran(), dummyName,
dummyIsAsynchronous ? "ASYNCHRONOUS" : "VOLATILE");
}
// Probably an over-restriction of F'23 15.5.2.5 note 5
if (copyOutNeeded && !volatileOrAsyncNeedsTempDiagnosticIssued) {
if ((dummyIsVolatile && !actualIsVolatile && !actualIsAsynchronous) ||
(dummyIsAsynchronous && !actualIsVolatile && !actualIsAsynchronous)) {
context.Warn(common::UsageWarning::Portability, messages.at(),
"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,
actual.AsFortran(), dummyName,
dummyIsVolatile ? "VOLATILE" : "ASYNCHRONOUS");
}
}
}

// 15.5.2.6 -- dummy is ALLOCATABLE
bool dummyIsOptional{
dummy.attrs.test(characteristics::DummyDataObject::Attr::Optional)};
Expand Down Expand Up @@ -1302,7 +1356,8 @@ static void CheckExplicitInterfaceArg(evaluate::ActualArgument &arg,
object.type.Rank() == 0 && proc.IsElemental()};
CheckExplicitDataArg(object, dummyName, *expr, *type,
isElemental, context, foldingContext, scope, intrinsic,
allowActualArgumentConversions, extentErrors, proc, arg);
allowActualArgumentConversions, extentErrors, proc, arg,
dummy);
} else if (object.type.type().IsTypelessIntrinsicArgument() &&
IsBOZLiteral(*expr)) {
// ok
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Semantics/call03.f90
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic
! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic -Wno-portability
! Test 15.5.2.4 constraints and restrictions for non-POINTER non-ALLOCATABLE
! dummy arguments.

Expand Down
2 changes: 1 addition & 1 deletion flang/test/Semantics/call44.f90
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic -Werror
! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic -Wno-portability -Werror
subroutine assumedshape(normal, contig)
real normal(:)
real, contiguous :: contig(:)
Expand Down
11 changes: 8 additions & 3 deletions flang/test/Semantics/call45.f90
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ program call45
call sub(v([1,2,2,3,3,3,4,4,4,4]))
!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]
call sub(v(21:30))
!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]
!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]
call sub(v(21:40:2))
call sub2(v(21:40:2))
call sub4(p)
call sub5(p)
print *, v
contains
subroutine sub(v)
Expand All @@ -23,7 +24,7 @@ subroutine sub1(v)
end subroutine sub1
subroutine sub2(v)
integer :: v(:)
!TODO: This should either be an portability warning or copy-in-copy-out warning
!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]
call sub(v)
call sub1(v)
end subroutine sub2
Expand All @@ -33,9 +34,13 @@ subroutine sub3(v)
end subroutine sub3
subroutine sub4(v)
integer, pointer :: v(:)
!TODO: This should either be a portability warning or copy-in-copy-out warning
!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]
call sub(v)
call sub1(v)
call sub3(v)
call sub5(v)
end subroutine sub4
subroutine sub5(v)
integer, pointer, volatile :: v(:)
end subroutine sub5
end program call45