Skip to content

Commit 0dd105d

Browse files
committed
[flang] Process pointer component default initializers sooner
Name resolution defers the analysis of all object pointer initializers to the end of a specification part, including the default initializers of derived type data pointer components. This deferment allows object pointer initializers to contain forward references to objects whose declarations appear later. However, this deferment has the unfortunate effect of causing NULL default initialization of such object pointer components when they do not appear in structure constructors that are used as default initializers, and their default initializers are required. So handle object pointer default initializers of components as they appear, as before.
1 parent 5eb24fd commit 0dd105d

File tree

5 files changed

+51
-18
lines changed

5 files changed

+51
-18
lines changed

flang/docs/Extensions.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -868,6 +868,13 @@ print *, [(j,j=1,10)]
868868
the elements for each component before proceeding to the next component.
869869
A program using defined assignment might be able to detect the difference.
870870

871+
* Forward references to target objects are allowed to appear
872+
in the initializers of data pointer declarationss.
873+
Forward references to target objects are not accepted in the default
874+
initializers of derived type component declarations, however,
875+
since these default values need to be available to process incomplete
876+
structure constructors.
877+
871878
## De Facto Standard Features
872879

873880
* `EXTENDS_TYPE_OF()` returns `.TRUE.` if both of its arguments have the

flang/lib/Semantics/resolve-names.cpp

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5383,7 +5383,7 @@ void DeclarationVisitor::Post(const parser::EntityDecl &x) {
53835383
ConvertToObjectEntity(symbol) || ConvertToProcEntity(symbol);
53845384
symbol.set(
53855385
Symbol::Flag::EntryDummyArgument, false); // forestall excessive errors
5386-
Initialization(name, *init, false);
5386+
Initialization(name, *init, /*inComponentDecl=*/false);
53875387
} else if (attrs.test(Attr::PARAMETER)) { // C882, C883
53885388
Say(name, "Missing initialization for parameter '%s'"_err_en_US);
53895389
}
@@ -6398,7 +6398,7 @@ void DeclarationVisitor::Post(const parser::ComponentDecl &x) {
63986398
SetCUDADataAttr(name.source, symbol, cudaDataAttr());
63996399
if (symbol.has<ObjectEntityDetails>()) {
64006400
if (auto &init{std::get<std::optional<parser::Initialization>>(x.t)}) {
6401-
Initialization(name, *init, true);
6401+
Initialization(name, *init, /*inComponentDecl=*/true);
64026402
}
64036403
}
64046404
currScope().symbol()->get<DerivedTypeDetails>().add_component(symbol);
@@ -8933,9 +8933,13 @@ void DeclarationVisitor::Initialization(const parser::Name &name,
89338933
// Defer analysis to the end of the specification part
89348934
// so that forward references and attribute checks like SAVE
89358935
// work better.
8936-
auto restorer{common::ScopedSet(deferImplicitTyping_, true)};
8937-
Walk(target);
8938-
ultimate.set(Symbol::Flag::InDataStmt);
8936+
if (inComponentDecl) {
8937+
PointerInitialization(name, target);
8938+
} else {
8939+
auto restorer{common::ScopedSet(deferImplicitTyping_, true)};
8940+
Walk(target);
8941+
ultimate.set(Symbol::Flag::InDataStmt);
8942+
}
89398943
},
89408944
[&](const std::list<Indirection<parser::DataStmtValue>> &values) {
89418945
// Handled later in data-to-inits conversion
@@ -10355,11 +10359,6 @@ class DeferredCheckVisitor {
1035510359
std::get<std::optional<parser::Initialization>>(decl.t));
1035610360
return false;
1035710361
}
10358-
bool Pre(const parser::ComponentDecl &decl) {
10359-
Init(std::get<parser::Name>(decl.t),
10360-
std::get<std::optional<parser::Initialization>>(decl.t));
10361-
return false;
10362-
}
1036310362
bool Pre(const parser::ProcDecl &decl) {
1036410363
if (const auto &init{
1036510364
std::get<std::optional<parser::ProcPointerInit>>(decl.t)}) {

flang/test/Semantics/bug1056.f90

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
! RUN: %flang_fc1 -fdebug-unparse %s | FileCheck %s
2+
program bug
3+
integer, target :: ita(2) = [1,2], itb(2) = [3,4], itc(2) = [5,6]
4+
type t1
5+
integer, pointer :: p1(:) => ita, p2(:) => itb
6+
end type
7+
type t2
8+
!CHECK: TYPE(t1) :: comp = t1(p1=itc,p2=itb)
9+
type(t1) :: comp = t1(itc)
10+
end type
11+
integer, pointer :: p3(:) => itd
12+
integer, target :: itd(2) = [7,8]
13+
end

flang/test/Semantics/symbol15.f90

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ subroutine iface
4343
!DEF: /m/pp6 EXTERNAL, POINTER, PUBLIC (Subroutine) ProcEntity
4444
!DEF: /m/modproc1 PUBLIC (Subroutine) Subprogram
4545
procedure(iface), pointer :: pp6 => modproc1
46+
!DEF: /m/xx PUBLIC, TARGET ObjectEntity REAL(4)
47+
!DEF: /m/yy PUBLIC, TARGET ObjectEntity REAL(4)
48+
real, target :: xx, yy(2)
4649
!DEF: /m/t1 PUBLIC DerivedType
4750
type :: t1
4851
!DEF: /m/t1/opc1 POINTER ObjectEntity REAL(4)
@@ -51,11 +54,11 @@ subroutine iface
5154
!REF: /m/null
5255
real, pointer :: opc2 => null()
5356
!DEF: /m/t1/opc3 POINTER ObjectEntity REAL(4)
54-
!REF: /m/x
55-
real, pointer :: opc3 => x
57+
!REF: /m/xx
58+
real, pointer :: opc3 => xx
5659
!DEF: /m/t1/opc4 POINTER ObjectEntity REAL(4)
57-
!REF: /m/y
58-
real, pointer :: opc4 => y(1)
60+
!REF: /m/yy
61+
real, pointer :: opc4 => yy(1)
5962
!REF: /m/iface
6063
!DEF: /m/t1/ppc1 NOPASS, POINTER (Subroutine) ProcEntity
6164
procedure(iface), nopass, pointer :: ppc1
@@ -101,12 +104,12 @@ subroutine iface
101104
!REF: /m/null
102105
real, pointer :: opc2 => null()
103106
!DEF: /m/pdt1/opc3 POINTER ObjectEntity REAL(4)
104-
!REF: /m/x
105-
real, pointer :: opc3 => x
107+
!REF: /m/xx
108+
real, pointer :: opc3 => xx
106109
!DEF: /m/pdt1/opc4 POINTER ObjectEntity REAL(4)
107-
!REF: /m/y
110+
!REF: /m/yy
108111
!REF: /m/pdt1/k
109-
real, pointer :: opc4 => y(k)
112+
real, pointer :: opc4 => yy(k)
110113
!REF: /m/iface
111114
!DEF: /m/pdt1/ppc1 NOPASS, POINTER (Subroutine) ProcEntity
112115
procedure(iface), nopass, pointer :: ppc1

t.f90

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
integer, target :: ita(2) = [1,2], itb(2) = [3,4], itc(2) = [5,6]
2+
type t1
3+
integer, pointer :: p1(:) => ita, p2(:) => itb
4+
end type
5+
type t2
6+
type(t1) :: comp = t1(itc)
7+
end type
8+
type(t2) :: var
9+
print *, var%comp%p2
10+
var%comp = t1(itc)
11+
end

0 commit comments

Comments
 (0)