Skip to content

Commit 26ac30b

Browse files
authored
[flang] Accept initialized SAVE local in specification expression (#107656)
Specification expressions may contain references to dummy arguments, host objects, module variables, and variables in COMMON blocks, since they will have values on entry to the scope. A local variable with a initializer and the SAVE attribute (which will always be implied by an explicit initialization) will also always work, and is accepted by at least one other compiler, so accept it with a warning.
1 parent fe58527 commit 26ac30b

File tree

6 files changed

+27
-7
lines changed

6 files changed

+27
-7
lines changed

flang/docs/Extensions.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,9 @@ end
386386
probably by a C or C++ external definition.
387387
* An automatic data object may be declared in the specification part
388388
of the main program.
389+
* A local data object may appear in a specification expression, even
390+
when it is not a dummy argument or in COMMON, so long as it is
391+
has the SAVE attribute and was initialized.
389392

390393
### Extensions supported when enabled by options
391394

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines,
5151
BadBranchTarget, ConvertedArgument, HollerithPolymorphic, ListDirectedSize,
5252
NonBindCInteroperability, CudaManaged, CudaUnified,
5353
PolymorphicActualAllocatableOrPointerToMonomorphicDummy, RelaxedPureDummy,
54-
UndefinableAsynchronousOrVolatileActual, AutomaticInMainProgram, PrintCptr)
54+
UndefinableAsynchronousOrVolatileActual, AutomaticInMainProgram, PrintCptr,
55+
SavedLocalInSpecExpr)
5556

5657
// Portability and suspicious usage warnings
5758
ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,
@@ -146,6 +147,8 @@ class LanguageFeatureControl {
146147
warnUsage_.set(UsageWarning::VectorSubscriptFinalization);
147148
warnUsage_.set(UsageWarning::UndefinedFunctionResult);
148149
warnUsage_.set(UsageWarning::UselessIomsg);
150+
// New warnings, on by default
151+
warnLanguage_.set(LanguageFeature::SavedLocalInSpecExpr);
149152
}
150153
LanguageFeatureControl(const LanguageFeatureControl &) = default;
151154

flang/lib/Evaluate/check-expression.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,18 @@ class CheckSpecificationExprHelper
554554
}
555555
} else if (&symbol.owner() != &scope_ || &ultimate.owner() != &scope_) {
556556
return std::nullopt; // host association is in play
557+
} else if (semantics::IsSaved(ultimate) &&
558+
semantics::IsInitialized(ultimate) &&
559+
context_.languageFeatures().IsEnabled(
560+
common::LanguageFeature::SavedLocalInSpecExpr)) {
561+
if (!scope_.IsModuleFile() &&
562+
context_.languageFeatures().ShouldWarn(
563+
common::LanguageFeature::SavedLocalInSpecExpr)) {
564+
context_.messages().Say(
565+
"specification expression refers to local object '%s' (initialized and saved)"_port_en_US,
566+
ultimate.name().ToString());
567+
}
568+
return std::nullopt;
557569
} else if (const auto *object{
558570
ultimate.detailsIf<semantics::ObjectEntityDetails>()}) {
559571
if (object->commonBlock()) {
@@ -781,8 +793,9 @@ bool CheckSpecificationExprHelper::IsPermissibleInquiry(
781793
template <typename A>
782794
void CheckSpecificationExpr(const A &x, const semantics::Scope &scope,
783795
FoldingContext &context, bool forElementalFunctionResult) {
784-
if (auto why{CheckSpecificationExprHelper{
785-
scope, context, forElementalFunctionResult}(x)}) {
796+
CheckSpecificationExprHelper helper{
797+
scope, context, forElementalFunctionResult};
798+
if (auto why{helper(x)}) {
786799
context.messages().Say("Invalid specification expression%s: %s"_err_en_US,
787800
forElementalFunctionResult ? " for elemental function result" : "",
788801
*why);

flang/test/Semantics/resolve69.f90

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ subroutine s1()
1616
!
1717
integer, parameter :: constVal = 1
1818
integer :: nonConstVal = 1
19-
!ERROR: Invalid specification expression: reference to local entity 'nonconstval'
19+
!PORTABILITY: specification expression refers to local object 'nonconstval' (initialized and saved)
2020
character(nonConstVal) :: colonString1
2121
character(len=20, kind=constVal + 1) :: constKindString
2222
character(len=:, kind=constVal + 1), pointer :: constKindString1
@@ -53,13 +53,13 @@ function foo3()
5353

5454
type (derived(constVal, 3)) :: constDerivedKind
5555
!ERROR: Value of KIND type parameter 'typekind' must be constant
56-
!ERROR: Invalid specification expression: reference to local entity 'nonconstval'
56+
!PORTABILITY: specification expression refers to local object 'nonconstval' (initialized and saved)
5757
type (derived(nonConstVal, 3)) :: nonConstDerivedKind
5858

5959
!OK because all type-params are constants
6060
type (derived(3, constVal)) :: constDerivedLen
6161

62-
!ERROR: Invalid specification expression: reference to local entity 'nonconstval'
62+
!PORTABILITY: specification expression refers to local object 'nonconstval' (initialized and saved)
6363
type (derived(3, nonConstVal)) :: nonConstDerivedLen
6464
!ERROR: 'colonderivedlen' has a type derived(typekind=3_4,typelen=:) with a deferred type parameter but is neither an allocatable nor an object pointer
6565
type (derived(3, :)) :: colonDerivedLen

flang/test/Semantics/resolve77.f90

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ pure integer function if2(n)
6060
block data
6161
common /blk2/ n
6262
data n/100/
63+
!PORTABILITY: specification expression refers to local object 'n' (initialized and saved)
6364
!ERROR: Automatic data object 'a' may not appear in a BLOCK DATA subprogram
6465
real a(n)
6566
end

flang/test/Semantics/spec-expr.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ subroutine s7biii(x, y)
104104
integer :: local = 5
105105
! OK, since "localConst" is a constant
106106
real, dimension(localConst) :: realArray1
107-
!ERROR: Invalid specification expression: reference to local entity 'local'
107+
!PORTABILITY: specification expression refers to local object 'local' (initialized and saved)
108108
real, dimension(local) :: realArray2
109109
real, dimension(size(realArray1)) :: realArray3 ! ok
110110
real, dimension(size(x)) :: realArray4 ! ok

0 commit comments

Comments
 (0)