Skip to content

Commit

Permalink
[flang] Extension: allow DATA to precede declaration under IMPLICIT N…
Browse files Browse the repository at this point in the history
…ONE(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 #63783.
  • Loading branch information
klausler committed Jul 17, 2023
1 parent 755180c commit df11165
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 4 deletions.
2 changes: 2 additions & 0 deletions flang/docs/Extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,8 @@ end
* When a name is brought into a scope by multiple ways,
such as USE-association as well as an `IMPORT` from its host,
it's an error only if the resolution is ambiguous.
* An entity may appear in a `DATA` statement before its explicit
type declaration under `IMPLICIT NONE(TYPE)`.

### Extensions supported when enabled by options

Expand Down
3 changes: 2 additions & 1 deletion flang/include/flang/Common/Fortran-features.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines,
ForwardRefImplicitNone, OpenAccessAppend, BOZAsDefaultInteger,
DistinguishableSpecifics, DefaultSave, PointerInSeqType, NonCharacterFormat,
SaveMainProgram, SaveBigMainProgramVariables,
DistinctArrayConstructorLengths, PPCVector, RelaxedIntentInChecking)
DistinctArrayConstructorLengths, PPCVector, RelaxedIntentInChecking,
ForwardRefImplicitNoneData)

// Portability and suspicious usage warnings for conforming code
ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,
Expand Down
15 changes: 13 additions & 2 deletions flang/lib/Semantics/resolve-names.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,7 @@ class ScopeHandler : public ImplicitRulesVisitor {
bool CheckPossibleBadForwardRef(const Symbol &);

bool inSpecificationPart_{false};
bool inDataStmtObject_{false};
bool inEquivalenceStmt_{false};

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

void ScopeHandler::NotePossibleBadForwardRef(const parser::Name &name) {
if (inSpecificationPart_ && name.symbol) {
if (inSpecificationPart_ && !inDataStmtObject_ && name.symbol) {
auto kind{currScope().kind()};
if ((kind == Scope::Kind::Subprogram && !currScope().IsStmtFunction()) ||
kind == Scope::Kind::BlockConstruct) {
Expand Down Expand Up @@ -6281,6 +6285,12 @@ void DeclarationVisitor::SetType(
}
auto *prevType{symbol.GetType()};
if (!prevType) {
if (symbol.test(Symbol::Flag::InDataStmt) && isImplicitNoneType() &&
context().ShouldWarn(
common::LanguageFeature::ForwardRefImplicitNoneData)) {
Say(name,
"'%s' appeared in a DATA statement before its type was declared under IMPLICIT NONE(TYPE)"_port_en_US);
}
symbol.SetType(type);
} else if (symbol.has<UseDetails>()) {
// error recovery case, redeclaration of use-associated name
Expand Down Expand Up @@ -6642,6 +6652,7 @@ bool ConstructVisitor::Pre(const parser::DataStmtObject &x) {
auto flagRestorer{common::ScopedSet(inSpecificationPart_, false)};
common::visit(common::visitors{
[&](const Indirection<parser::Variable> &y) {
auto restorer{common::ScopedSet(inDataStmtObject_, true)};
Walk(y.value());
const parser::Name &first{
parser::GetFirstName(y.value())};
Expand Down Expand Up @@ -7199,7 +7210,7 @@ const parser::Name *DeclarationVisitor::ResolveName(const parser::Name &name) {
}
return &name;
}
if (isImplicitNoneType()) {
if (isImplicitNoneType() && !inDataStmtObject_) {
Say(name, "No explicit type declared for '%s'"_err_en_US);
return nullptr;
}
Expand Down
9 changes: 8 additions & 1 deletion flang/test/Semantics/resolve30.f90
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
! RUN: %python %S/test_errors.py %s %flang_fc1
! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic
subroutine s1
integer x
block
Expand Down Expand Up @@ -37,3 +37,10 @@ subroutine s4
!ERROR: Must have INTEGER type, but is REAL(4)
data(b(j), j=1, 16) / 16 * 0.0 /
end

subroutine s5
implicit none
data x/1./
!PORTABILITY: 'x' appeared in a DATA statement before its type was declared under IMPLICIT NONE(TYPE)
real x
end

0 comments on commit df11165

Please sign in to comment.