Skip to content

Commit c4f67ea

Browse files
committed
[flang] Allow DATA initialization of derived types w/ allocatable components
While one cannot of course statically initialize an allocatable component of an instance of a derived type, its mere presence should not prevent DATA initialization of the other nonallocatable components. Semantics was treating the existence of an allocatable component as a case of "default initialization", which it is, but not one that should run afoul of C877. Add another Boolean argument to IsInitialized() to allow for a more nuanced test. Differential Revision: https://reviews.llvm.org/D119449
1 parent 34a62f9 commit c4f67ea

File tree

8 files changed

+31
-23
lines changed

8 files changed

+31
-23
lines changed

flang/include/flang/Semantics/tools.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ bool CanBeTypeBoundProc(const Symbol *);
107107
// attribute, or a derived type component default value.)
108108
bool HasDeclarationInitializer(const Symbol &);
109109
// Is the symbol explicitly or implicitly initialized in any way?
110-
bool IsInitialized(const Symbol &, bool ignoreDATAstatements = false);
110+
bool IsInitialized(const Symbol &, bool ignoreDATAstatements = false,
111+
bool ignoreAllocatable = false);
111112
// Is the symbol a component subject to deallocation or finalization?
112113
bool IsDestructible(const Symbol &, const Symbol *derivedType = nullptr);
113114
bool HasIntrinsicTypeName(const Symbol &);

flang/include/flang/Semantics/type.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ class DerivedTypeSpec {
265265

266266
bool MightBeParameterized() const;
267267
bool IsForwardReferenced() const;
268-
bool HasDefaultInitialization() const;
268+
bool HasDefaultInitialization(bool ignoreAllocatable = false) const;
269269
bool HasDestruction() const;
270270
bool HasFinalization() const;
271271

flang/lib/Evaluate/initial-image.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ class AsConstantHelper {
115115
typedValue[j].emplace(component, std::move(*value));
116116
}
117117
}
118-
} else {
118+
} else if (!IsAllocatable(component)) {
119119
auto componentType{DynamicType::From(component)};
120120
CHECK(componentType.has_value());
121121
auto componentExtents{GetConstantExtents(context_, component)};

flang/lib/Semantics/check-data.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@ class DataVarChecker : public evaluate::AllTraverse<DataVarChecker, true> {
6262
: IsDummy(symbol) ? "Dummy argument"
6363
: IsFunctionResult(symbol) ? "Function result"
6464
: IsAllocatable(symbol) ? "Allocatable"
65-
: IsInitialized(symbol, true) ? "Default-initialized"
65+
: IsInitialized(symbol, true /*ignore DATA*/,
66+
true /*ignore allocatable components*/)
67+
? "Default-initialized"
6668
: IsProcedure(symbol) && !IsPointer(symbol) ? "Procedure"
6769
// remaining checks don't apply to components
6870
: !isFirstSymbol ? nullptr

flang/lib/Semantics/tools.cpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -558,23 +558,21 @@ bool HasDeclarationInitializer(const Symbol &symbol) {
558558
}
559559
}
560560

561-
bool IsInitialized(const Symbol &symbol, bool ignoreDataStatements) {
562-
if (IsAllocatable(symbol) ||
563-
(!ignoreDataStatements && symbol.test(Symbol::Flag::InDataStmt)) ||
564-
HasDeclarationInitializer(symbol)) {
561+
bool IsInitialized(
562+
const Symbol &symbol, bool ignoreDataStatements, bool ignoreAllocatable) {
563+
if (!ignoreAllocatable && IsAllocatable(symbol)) {
564+
return true;
565+
} else if (!ignoreDataStatements && symbol.test(Symbol::Flag::InDataStmt)) {
566+
return true;
567+
} else if (HasDeclarationInitializer(symbol)) {
565568
return true;
566569
} else if (IsNamedConstant(symbol) || IsFunctionResult(symbol) ||
567570
IsPointer(symbol)) {
568571
return false;
569572
} else if (const auto *object{symbol.detailsIf<ObjectEntityDetails>()}) {
570573
if (!object->isDummy() && object->type()) {
571574
if (const auto *derived{object->type()->AsDerived()}) {
572-
DirectComponentIterator directs{*derived};
573-
return bool{std::find_if(
574-
directs.begin(), directs.end(), [](const Symbol &component) {
575-
return IsAllocatable(component) ||
576-
HasDeclarationInitializer(component);
577-
})};
575+
return derived->HasDefaultInitialization(ignoreAllocatable);
578576
}
579577
}
580578
}

flang/lib/Semantics/type.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,10 +177,12 @@ bool DerivedTypeSpec::IsForwardReferenced() const {
177177
return typeSymbol_.get<DerivedTypeDetails>().isForwardReferenced();
178178
}
179179

180-
bool DerivedTypeSpec::HasDefaultInitialization() const {
180+
bool DerivedTypeSpec::HasDefaultInitialization(bool ignoreAllocatable) const {
181181
DirectComponentIterator components{*this};
182-
return bool{std::find_if(components.begin(), components.end(),
183-
[&](const Symbol &component) { return IsInitialized(component); })};
182+
return bool{std::find_if(
183+
components.begin(), components.end(), [&](const Symbol &component) {
184+
return IsInitialized(component, true, ignoreAllocatable);
185+
})};
184186
}
185187

186188
bool DerivedTypeSpec::HasDestruction() const {

flang/test/Semantics/data04.f90

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ subroutine CheckObject(i)
5858
integer, allocatable :: allocVal
5959
integer, allocatable :: elt(:)
6060
integer val
61-
type(specialNumbers) numsArray(5)
61+
type(specialNumbers) numsArray(10)
6262
end type
6363
type(large) largeNumber
6464
type(large), allocatable :: allocatableLarge
@@ -69,8 +69,7 @@ subroutine CheckObject(i)
6969
real :: x
7070
end type
7171
type(small), pointer :: sp
72-
!C877
73-
!ERROR: Default-initialized 'largenumber' must not be initialized in a DATA statement
72+
!This case is ok.
7473
DATA(largeNumber % numsArray(j) % headOfTheList, j = 1, 10) / 10 * NULL() /
7574
!C877
7675
!ERROR: Data object must not contain pointer 'headofthelist' as a non-rightmost part
@@ -80,12 +79,12 @@ subroutine CheckObject(i)
8079
DATA(largeNumber % numsArray(j) % ptoarray(1), j = 1, 10) / 10 * 1 /
8180
!C877
8281
!ERROR: Rightmost data object pointer 'ptochar' must not be subscripted
83-
DATA largeNumber % numsArray(0) % ptochar(1:2) / 'ab' /
82+
DATA largeNumber % numsArray(1) % ptochar(1:2) / 'ab' /
8483
!C876
85-
!ERROR: Default-initialized 'largenumber' must not be initialized in a DATA statement
84+
!ERROR: Allocatable 'elt' must not be initialized in a DATA statement
8685
DATA(largeNumber % elt(j) , j = 1, 10) / 10 * 1/
8786
!C876
88-
!ERROR: Default-initialized 'largearray' must not be initialized in a DATA statement
87+
!ERROR: Allocatable 'allocval' must not be initialized in a DATA statement
8988
DATA(largeArray(j) % allocVal , j = 1, 10) / 10 * 1/
9089
!C876
9190
!ERROR: Allocatable 'allocatablelarge' must not be initialized in a DATA statement

flang/test/Semantics/data06.f90

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ subroutine s1
77
type(t1) :: t1x
88
!ERROR: Default-initialized 't1x' must not be initialized in a DATA statement
99
data t1x%j / 777 /
10+
type :: t2
11+
integer, allocatable :: j
12+
integer :: k
13+
end type t2
14+
type(t2) :: t2x
15+
data t2x%k / 777 / ! allocatable component is ok
1016
integer :: ja = 888
1117
!ERROR: Default-initialized 'ja' must not be initialized in a DATA statement
1218
data ja / 999 /

0 commit comments

Comments
 (0)