Skip to content

Commit df11165

Browse files
committed
[flang] Extension: allow DATA to precede declaration under IMPLICIT NONE(TYPE)
It is not standard conforming under IMPLICIT NONE(TYPE) for a name to appear in a DATA statement prior to its explicit type declaration, but it is benign, supported in other compilers, and attested in real applications. Support it with an optional portability warning. Fixes GitHub LLVM bug llvm#63783.
1 parent 755180c commit df11165

File tree

4 files changed

+25
-4
lines changed

4 files changed

+25
-4
lines changed

flang/docs/Extensions.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,8 @@ end
283283
* When a name is brought into a scope by multiple ways,
284284
such as USE-association as well as an `IMPORT` from its host,
285285
it's an error only if the resolution is ambiguous.
286+
* An entity may appear in a `DATA` statement before its explicit
287+
type declaration under `IMPLICIT NONE(TYPE)`.
286288

287289
### Extensions supported when enabled by options
288290

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines,
3636
ForwardRefImplicitNone, OpenAccessAppend, BOZAsDefaultInteger,
3737
DistinguishableSpecifics, DefaultSave, PointerInSeqType, NonCharacterFormat,
3838
SaveMainProgram, SaveBigMainProgramVariables,
39-
DistinctArrayConstructorLengths, PPCVector, RelaxedIntentInChecking)
39+
DistinctArrayConstructorLengths, PPCVector, RelaxedIntentInChecking,
40+
ForwardRefImplicitNoneData)
4041

4142
// Portability and suspicious usage warnings for conforming code
4243
ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,

flang/lib/Semantics/resolve-names.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,7 @@ class ScopeHandler : public ImplicitRulesVisitor {
697697
bool CheckPossibleBadForwardRef(const Symbol &);
698698

699699
bool inSpecificationPart_{false};
700+
bool inDataStmtObject_{false};
700701
bool inEquivalenceStmt_{false};
701702

702703
// Some information is collected from a specification part for deferred
@@ -2481,6 +2482,9 @@ void ScopeHandler::ApplyImplicitRules(
24812482
// or object, it'll be caught later.
24822483
return;
24832484
}
2485+
if (inDataStmtObject_) {
2486+
return;
2487+
}
24842488
if (!context().HasError(symbol)) {
24852489
Say(symbol.name(), "No explicit type declared for '%s'"_err_en_US);
24862490
context().SetError(symbol);
@@ -2654,7 +2658,7 @@ const DeclTypeSpec &ScopeHandler::MakeLogicalType(int kind) {
26542658
}
26552659

26562660
void ScopeHandler::NotePossibleBadForwardRef(const parser::Name &name) {
2657-
if (inSpecificationPart_ && name.symbol) {
2661+
if (inSpecificationPart_ && !inDataStmtObject_ && name.symbol) {
26582662
auto kind{currScope().kind()};
26592663
if ((kind == Scope::Kind::Subprogram && !currScope().IsStmtFunction()) ||
26602664
kind == Scope::Kind::BlockConstruct) {
@@ -6281,6 +6285,12 @@ void DeclarationVisitor::SetType(
62816285
}
62826286
auto *prevType{symbol.GetType()};
62836287
if (!prevType) {
6288+
if (symbol.test(Symbol::Flag::InDataStmt) && isImplicitNoneType() &&
6289+
context().ShouldWarn(
6290+
common::LanguageFeature::ForwardRefImplicitNoneData)) {
6291+
Say(name,
6292+
"'%s' appeared in a DATA statement before its type was declared under IMPLICIT NONE(TYPE)"_port_en_US);
6293+
}
62846294
symbol.SetType(type);
62856295
} else if (symbol.has<UseDetails>()) {
62866296
// error recovery case, redeclaration of use-associated name
@@ -6642,6 +6652,7 @@ bool ConstructVisitor::Pre(const parser::DataStmtObject &x) {
66426652
auto flagRestorer{common::ScopedSet(inSpecificationPart_, false)};
66436653
common::visit(common::visitors{
66446654
[&](const Indirection<parser::Variable> &y) {
6655+
auto restorer{common::ScopedSet(inDataStmtObject_, true)};
66456656
Walk(y.value());
66466657
const parser::Name &first{
66476658
parser::GetFirstName(y.value())};
@@ -7199,7 +7210,7 @@ const parser::Name *DeclarationVisitor::ResolveName(const parser::Name &name) {
71997210
}
72007211
return &name;
72017212
}
7202-
if (isImplicitNoneType()) {
7213+
if (isImplicitNoneType() && !inDataStmtObject_) {
72037214
Say(name, "No explicit type declared for '%s'"_err_en_US);
72047215
return nullptr;
72057216
}

flang/test/Semantics/resolve30.f90

Lines changed: 8 additions & 1 deletion
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
subroutine s1
33
integer x
44
block
@@ -37,3 +37,10 @@ subroutine s4
3737
!ERROR: Must have INTEGER type, but is REAL(4)
3838
data(b(j), j=1, 16) / 16 * 0.0 /
3939
end
40+
41+
subroutine s5
42+
implicit none
43+
data x/1./
44+
!PORTABILITY: 'x' appeared in a DATA statement before its type was declared under IMPLICIT NONE(TYPE)
45+
real x
46+
end

0 commit comments

Comments
 (0)