Skip to content

Commit 1ce9ac2

Browse files
committed
[flang] Relax constraints on PURE/ELEMENTAL dummy arguments
The standard requires that dummy arguments to PURE functions be INTENT(IN) or VALUE, but PURE subroutines are allowed to have modifiable dummy arguments. This makes it impossible to declare atomic operations as PURE functions, which consequently makes such atomic operations ineligible for use in parallel constructs and DO CONCURRENT. This patch downgrades this error to a warning by default, which can be seen with -pedantic & al. and remain an error with -Werror.
1 parent 82bd7ad commit 1ce9ac2

File tree

5 files changed

+62
-19
lines changed

5 files changed

+62
-19
lines changed

flang/docs/Extensions.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,12 @@ end
118118
procedure interface. This compiler accepts it, since there is otherwise
119119
no way to declare an interoperable dummy procedure with an arbitrary
120120
interface like `void (*)()`.
121+
* `PURE` functions are allowed to have dummy arguments that are
122+
neither `INTENT(IN)` nor `VALUE`, similar to `PURE` subroutines,
123+
with a warning.
124+
This enables atomic memory operations to be naturally represented
125+
as `PURE` functions, which allows their use in parallel constructs
126+
and `DO CONCURRENT`.
121127

122128
## Extensions, deletions, and legacy features supported by default
123129

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines,
5050
EmptySequenceType, NonSequenceCrayPointee, BranchIntoConstruct,
5151
BadBranchTarget, ConvertedArgument, HollerithPolymorphic, ListDirectedSize,
5252
NonBindCInteroperability, CudaManaged, CudaUnified,
53-
PolymorphicActualAllocatableOrPointerToMonomorphicDummy)
53+
PolymorphicActualAllocatableOrPointerToMonomorphicDummy, RelaxedPureDummy)
5454

5555
// Portability and suspicious usage warnings
5656
ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,

flang/lib/Semantics/check-declarations.cpp

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -704,29 +704,58 @@ void CheckHelper::CheckObjectEntity(
704704
if (InPure() && !IsStmtFunction(DEREF(innermostSymbol_)) &&
705705
!IsPointer(symbol) && !IsIntentIn(symbol) &&
706706
!symbol.attrs().test(Attr::VALUE)) {
707-
if (InFunction()) { // C1583
708-
messages_.Say(
709-
"non-POINTER dummy argument of pure function must be INTENT(IN) or VALUE"_err_en_US);
710-
} else if (IsIntentOut(symbol)) {
707+
const char *what{InFunction() ? "function" : "subroutine"};
708+
bool ok{true};
709+
if (IsIntentOut(symbol)) {
711710
if (type && type->IsPolymorphic()) { // C1588
712711
messages_.Say(
713-
"An INTENT(OUT) dummy argument of a pure subroutine may not be polymorphic"_err_en_US);
712+
"An INTENT(OUT) dummy argument of a pure %s may not be polymorphic"_err_en_US,
713+
what);
714+
ok = false;
714715
} else if (derived) {
715716
if (FindUltimateComponent(*derived, [](const Symbol &x) {
716717
const DeclTypeSpec *type{x.GetType()};
717718
return type && type->IsPolymorphic();
718719
})) { // C1588
719720
messages_.Say(
720-
"An INTENT(OUT) dummy argument of a pure subroutine may not have a polymorphic ultimate component"_err_en_US);
721+
"An INTENT(OUT) dummy argument of a pure %s may not have a polymorphic ultimate component"_err_en_US,
722+
what);
723+
ok = false;
721724
}
722725
if (HasImpureFinal(symbol)) { // C1587
723726
messages_.Say(
724-
"An INTENT(OUT) dummy argument of a pure subroutine may not have an impure FINAL subroutine"_err_en_US);
727+
"An INTENT(OUT) dummy argument of a pure %s may not have an impure FINAL subroutine"_err_en_US,
728+
what);
729+
ok = false;
725730
}
726731
}
727732
} else if (!IsIntentInOut(symbol)) { // C1586
728-
messages_.Say(
729-
"non-POINTER dummy argument of pure subroutine must have INTENT() or VALUE attribute"_err_en_US);
733+
if (context_.IsEnabled(common::LanguageFeature::RelaxedPureDummy)) {
734+
if (context_.ShouldWarn(common::LanguageFeature::RelaxedPureDummy) &&
735+
!InModuleFile() && !InElemental()) {
736+
messages_.Say(
737+
"non-POINTER dummy argument of pure %s should have INTENT() or VALUE attribute"_warn_en_US,
738+
what);
739+
ok = false;
740+
}
741+
} else {
742+
messages_.Say(
743+
"non-POINTER dummy argument of pure %s must have INTENT() or VALUE attribute"_warn_en_US,
744+
what);
745+
ok = false;
746+
}
747+
}
748+
if (ok && InFunction()) {
749+
if (context_.IsEnabled(common::LanguageFeature::RelaxedPureDummy)) {
750+
if (context_.ShouldWarn(common::LanguageFeature::RelaxedPureDummy) &&
751+
!InModuleFile() && !InElemental()) {
752+
messages_.Say(
753+
"non-POINTER dummy argument of pure function should be INTENT(IN) or VALUE"_warn_en_US);
754+
}
755+
} else {
756+
messages_.Say(
757+
"non-POINTER dummy argument of pure function must be INTENT(IN) or VALUE"_err_en_US);
758+
}
730759
}
731760
}
732761
if (auto ignoreTKR{GetIgnoreTKR(symbol)}; !ignoreTKR.empty()) {
@@ -798,9 +827,17 @@ void CheckHelper::CheckObjectEntity(
798827
"A dummy argument of an ELEMENTAL procedure may not be a POINTER"_err_en_US);
799828
}
800829
if (!symbol.attrs().HasAny(Attrs{Attr::VALUE, Attr::INTENT_IN,
801-
Attr::INTENT_INOUT, Attr::INTENT_OUT})) { // C15102
802-
messages_.Say(
803-
"A dummy argument of an ELEMENTAL procedure must have an INTENT() or VALUE attribute"_err_en_US);
830+
Attr::INTENT_INOUT, Attr::INTENT_OUT})) { // F'2023 C15120
831+
if (context_.IsEnabled(common::LanguageFeature::RelaxedPureDummy)) {
832+
if (context_.ShouldWarn(common::LanguageFeature::RelaxedPureDummy) &&
833+
!InModuleFile()) {
834+
messages_.Say(
835+
"A dummy argument of an ELEMENTAL procedure should have an INTENT() or VALUE attribute"_warn_en_US);
836+
}
837+
} else {
838+
messages_.Say(
839+
"A dummy argument of an ELEMENTAL procedure must have an INTENT() or VALUE attribute"_err_en_US);
840+
}
804841
}
805842
} else if (IsFunctionResult(symbol)) { // C15101
806843
if (details.shape().Rank() > 0) {

flang/test/Semantics/call10.f90

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
! RUN: %python %S/test_errors.py %s %flang_fc1
1+
! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic
22
! Test 15.7 (C1583-C1590, C1592-C1599) constraints and restrictions
33
! for pure procedures.
44
! (C1591 is tested in call11.f90; C1594 in call12.f90.)
@@ -53,14 +53,14 @@ pure real function f02(a)
5353
real, value :: a ! ok
5454
end function
5555
pure real function f03(a) ! C1583
56-
!ERROR: non-POINTER dummy argument of pure function must be INTENT(IN) or VALUE
56+
!ERROR: non-POINTER dummy argument of pure function should have INTENT() or VALUE attribute
5757
real :: a
5858
end function
5959
pure real function f03a(a)
6060
real, pointer :: a ! ok
6161
end function
6262
pure real function f04(a) ! C1583
63-
!ERROR: non-POINTER dummy argument of pure function must be INTENT(IN) or VALUE
63+
!WARNING: non-POINTER dummy argument of pure function should be INTENT(IN) or VALUE
6464
real, intent(out) :: a
6565
end function
6666
pure real function f04a(a)
@@ -83,7 +83,7 @@ pure function f08() ! C1585
8383
end function
8484

8585
pure subroutine s01(a) ! C1586
86-
!ERROR: non-POINTER dummy argument of pure subroutine must have INTENT() or VALUE attribute
86+
!WARNING: non-POINTER dummy argument of pure subroutine should have INTENT() or VALUE attribute
8787
real :: a
8888
end subroutine
8989
pure subroutine s01a(a)

flang/test/Semantics/elemental01.f90

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
! RUN: %python %S/test_errors.py %s %flang_fc1
1+
! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic
22
! Tests ELEMENTAL subprogram constraints C15100-15102
33

44
!ERROR: An ELEMENTAL subroutine may not have an alternate return dummy argument
@@ -26,7 +26,7 @@ elemental subroutine ptrarg(a)
2626
end subroutine
2727

2828
impure elemental subroutine barearg(a)
29-
!ERROR: A dummy argument of an ELEMENTAL procedure must have an INTENT() or VALUE attribute
29+
!WARNING: A dummy argument of an ELEMENTAL procedure should have an INTENT() or VALUE attribute
3030
real :: a
3131
end subroutine
3232

0 commit comments

Comments
 (0)