[flang-commits] [flang] [flang] Defer typing of forward-referenced DATA implied-DO indices (PR #214473)
Eugene Epshteyn via flang-commits
flang-commits at lists.llvm.org
Thu Aug 6 05:33:14 PDT 2026
https://github.com/eugeneepshteyn created https://github.com/llvm/llvm-project/pull/214473
F2023 19.4 p5 gives a data-i-do-variable without an explicit integer-type-spec the type that its name would have as a variable of the innermost scoping unit including the DATA statement. That is a property of the whole scoping unit: since a data-stmt is a declaration-construct, the type declaration statement establishing the name's type may follow the DATA statement in the same specification part. Name resolution resolved the index eagerly at the DATA statement, so under IMPLICIT NONE(TYPE) a later declaration drew a spurious "No explicit type declared" error, and without IMPLICIT NONE a later declaration with a non-default kind was ignored.
Defer the typing of such indices to the end of the specification part, mirroring the existing deferral for ordinary DATA statement objects. DATA statements in an execution part keep the current eager resolution.
Assisted-by: AI
>From 97cbf9299c6e6ce9c9186c8f6b048a8654ea7d5d Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Thu, 6 Aug 2026 00:47:37 -0400
Subject: [PATCH] [flang] Defer typing of forward-referenced DATA implied-DO
indices
F2023 19.4 p5 gives a data-i-do-variable without an explicit
integer-type-spec the type that its name would have as a variable of the
innermost scoping unit including the DATA statement. That is a property
of the whole scoping unit: since a data-stmt is a declaration-construct,
the type declaration statement establishing the name's type may follow
the DATA statement in the same specification part. Name resolution
resolved the index eagerly at the DATA statement, so under IMPLICIT
NONE(TYPE) a later declaration drew a spurious "No explicit type
declared" error, and without IMPLICIT NONE a later declaration with a
non-default kind was ignored.
Defer the typing of such indices to the end of the specification part,
mirroring the existing deferral for ordinary DATA statement objects.
DATA statements in an execution part keep the current eager resolution.
---
flang/lib/Semantics/resolve-names.cpp | 33 +++++++++++++++++++++++
flang/test/Semantics/data25.f90 | 39 +++++++++++++++++++++++++++
flang/test/Semantics/data26.f90 | 13 +++++++++
3 files changed, 85 insertions(+)
create mode 100644 flang/test/Semantics/data25.f90
create mode 100644 flang/test/Semantics/data26.f90
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 3f2d97bfc7bef..9eb194e780e84 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -751,6 +751,9 @@ class ScopeHandler : public ImplicitRulesVisitor {
bool deferImplicitTyping_{false};
bool skipImplicitTyping_{false};
bool inEquivalenceStmt_{false};
+ // Whether the DATA statement whose objects are being visited appeared in
+ // a specification part (as opposed to an execution part)
+ bool dataStmtObjectInSpecPart_{false};
// Some information is collected from a specification part for deferred
// processing in DeclarationPartVisitor functions (e.g., CheckSaveStmts())
@@ -764,6 +767,11 @@ class ScopeHandler : public ImplicitRulesVisitor {
std::vector<const std::list<parser::EquivalenceObject> *> equivalenceSets;
// Names of all common block objects in the scope
std::set<SourceName> commonBlockObjects;
+ // data-implied-do index variables whose typing has been deferred until
+ // the end of the specification part, since the declaration determining
+ // the type of the index's name in the scoping unit may follow the DATA
+ // statement (F'2023 19.4 p5)
+ std::vector<MutableSymbolRef> deferredDataIDoVars;
// Info about SAVE statements and attributes in current scope
struct {
std::optional<SourceName> saveAll; // "SAVE" without entity list
@@ -8229,6 +8237,12 @@ Symbol *DeclarationVisitor::DeclareStatementEntity(
auto restorer{
common::ScopedSet(charInfo_.length, std::optional<ParamValue>{})};
SetType(name, *declTypeSpec);
+ } else if (dataStmtObjectInSpecPart_) {
+ // F'2023 19.4 p5: this index has the type that its name would have as
+ // a variable of the scoping unit, and the declaration establishing that
+ // type may follow the DATA statement in the same specification part.
+ // Defer its typing to FinishSpecificationPart().
+ specPartState_.deferredDataIDoVars.emplace_back(symbol);
} else {
ApplyImplicitRules(symbol);
}
@@ -8660,6 +8674,8 @@ bool ConstructVisitor::Pre(const parser::DataStmtObject &x) {
// for purposes of implicit variable declaration vs. host association.
// When a name first appears as an object in a DATA statement, it should
// be implicitly declared locally as if it had been assigned.
+ auto specPartRestorer{
+ common::ScopedSet(dataStmtObjectInSpecPart_, inSpecificationPart_)};
auto flagRestorer{common::ScopedSet(inSpecificationPart_, false)};
common::visit(
common::visitors{
@@ -10667,6 +10683,23 @@ void ResolveNamesVisitor::FinishSpecificationPart(
}
}
}
+ // Define the types of data-implied-do index variables whose typing was
+ // deferred, now that the whole specification part has been visited, using
+ // the type that the index's name has in the scoping unit (F'2023 19.4 p5).
+ for (MutableSymbolRef ref : specPartState_.deferredDataIDoVars) {
+ Symbol &symbol{*ref};
+ if (!symbol.GetType()) {
+ if (const Symbol *outer{currScope().FindSymbol(symbol.name())};
+ outer && outer->GetType()) {
+ symbol.SetType(*outer->GetType());
+ // Inhibit unused-variable diagnostics: the outer declaration may
+ // exist solely to give the index its type.
+ context().NoteDefinedSymbol(*outer);
+ } else {
+ ApplyImplicitRules(symbol);
+ }
+ }
+ }
currScope().InstantiateDerivedTypes();
for (const auto &decl : decls) {
if (const auto *statement{std::get_if<
diff --git a/flang/test/Semantics/data25.f90 b/flang/test/Semantics/data25.f90
new file mode 100644
index 0000000000000..71ace2c72a259
--- /dev/null
+++ b/flang/test/Semantics/data25.f90
@@ -0,0 +1,39 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+! F'2023 19.4 p5: a data-implied-do index variable without an explicit
+! integer-type-spec takes the type that its name would have as a variable
+! of the scoping unit, and the type declaration statement establishing that
+! type may appear later in the same specification part than the DATA
+! statement.
+
+! Index declared after the DATA statement: conforming, no error.
+subroutine s1
+ implicit none
+ logical, dimension(4), save :: util
+ data (util(i),i=1,4)/4*.true./
+ integer :: i
+end subroutine
+
+! Nested implied-DOs, both indices declared later.
+subroutine s2
+ implicit none
+ logical, dimension(2,2), save :: m
+ data ((m(i,j),i=1,2),j=1,2)/4*.true./
+ integer :: i, j
+end subroutine
+
+! Index never declared under IMPLICIT NONE(TYPE): still an error.
+subroutine s3
+ implicit none
+ logical, dimension(4), save :: util
+ !ERROR: No explicit type declared for 'i'
+ data (util(i),i=1,4)/4*.true./
+end subroutine
+
+! The index's type, wherever its name is declared, must be integer.
+subroutine s4
+ implicit none
+ logical, dimension(4), save :: util
+ !ERROR: Must have INTEGER type, but is CHARACTER(KIND=1,LEN=1_8)
+ data (util(i),i=1,4)/4*.true./
+ character :: i
+end subroutine
diff --git a/flang/test/Semantics/data26.f90 b/flang/test/Semantics/data26.f90
new file mode 100644
index 0000000000000..7550645a5da4b
--- /dev/null
+++ b/flang/test/Semantics/data26.f90
@@ -0,0 +1,13 @@
+! RUN: %flang_fc1 -fdebug-dump-symbols %s 2>&1 | FileCheck %s
+! F'2023 19.4 p5: a data-implied-do index variable takes the type of its
+! name in the scoping unit -- including its kind, and even when the
+! declaration follows the DATA statement.
+! CHECK: Subprogram scope: s
+! CHECK: i size=8 offset={{[0-9]+}}: ObjectEntity type: INTEGER(8)
+! CHECK: ImpliedDos scope:
+! CHECK: i size=8 offset=0: ObjectEntity type: INTEGER(8)
+subroutine s
+ logical, dimension(4), save :: util
+ data (util(i),i=1,4)/4*.true./
+ integer(8) :: i
+end subroutine
More information about the flang-commits
mailing list