Skip to content

Commit 8b93089

Browse files
authored
[flang] Don't misinterpret valid component value for ancestor type (#161910)
As a common language extension, this compiler accepts a structure constructor whose first value has no keyword and whose type matches an ancestral type as if the constructor had had a keyword whose name was the ancestral type. For example, given TYPE PARENT; REAL X; END TYPE TYPE, EXTENDS(PARENT) :: CHILD; END TYPE we accept the nonconforming constructor "child(parent(1.))" as if it had been the conforming "child(1.)" or "child(parent=parent(1.))". The detection of this case needs to be constrained a bit to avoid a false positive misinterpretation of conforming code in the case where the actual first component of the derived type is a POINTER or ALLOCATABLE whose type and rank would allow it to correspond with the keywordless first value in the component value list. Fixes #161887.
1 parent ea291d0 commit 8b93089

File tree

2 files changed

+112
-11
lines changed

2 files changed

+112
-11
lines changed

flang/lib/Semantics/expression.cpp

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2171,17 +2171,29 @@ MaybeExpr ExpressionAnalyzer::CheckStructureConstructor(
21712171
// T(1) or T(PT=PT(1)). There may be multiple parent components.
21722172
if (nextAnonymous == components.begin() && parentComponent && valueType &&
21732173
context().IsEnabled(LanguageFeature::AnonymousParents)) {
2174-
for (auto parent{components.begin()};
2175-
parent != afterLastParentComponentIter; ++parent) {
2176-
if (auto parentType{DynamicType::From(*parent)}; parentType &&
2177-
parent->test(Symbol::Flag::ParentComp) &&
2178-
valueType->IsEquivalentTo(*parentType)) {
2179-
symbol = &*parent;
2180-
nextAnonymous = ++parent;
2181-
Warn(LanguageFeature::AnonymousParents, source,
2182-
"Whole parent component '%s' in structure constructor should not be anonymous"_port_en_US,
2183-
symbol->name());
2184-
break;
2174+
auto parent{components.begin()};
2175+
if (!parent->test(Symbol::Flag::ParentComp)) {
2176+
// Ensure that the first value can't initialize the first actual
2177+
// component.
2178+
if (auto firstComponentType{DynamicType::From(*parent)}) {
2179+
if (firstComponentType->IsTkCompatibleWith(*valueType) &&
2180+
value.Rank() == parent->Rank()) {
2181+
parent = afterLastParentComponentIter; // skip next loop
2182+
}
2183+
}
2184+
}
2185+
for (; parent != afterLastParentComponentIter; ++parent) {
2186+
if (auto parentType{DynamicType::From(*parent)}) {
2187+
if (parent->test(Symbol::Flag::ParentComp) &&
2188+
valueType->IsEquivalentTo(*parentType) &&
2189+
value.Rank() == 0 /* scalar only */) {
2190+
symbol = &*parent;
2191+
nextAnonymous = ++parent;
2192+
Warn(LanguageFeature::AnonymousParents, source,
2193+
"Whole parent component '%s' in structure constructor should not be anonymous"_port_en_US,
2194+
symbol->name());
2195+
break;
2196+
}
21852197
}
21862198
}
21872199
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
!RUN: %flang_fc1 -fdebug-unparse %s | FileCheck %s
2+
program test
3+
4+
type t1p
5+
type(t1p), pointer :: arr(:)
6+
end type
7+
type, extends(t1p) :: t1c
8+
end type
9+
type t2p
10+
type(t2p), pointer :: scalar
11+
end type
12+
type, extends(t2p) :: t2c
13+
end type
14+
type t3p
15+
type(t3p), allocatable :: arr(:)
16+
end type
17+
type, extends(t3p) :: t3c
18+
end type
19+
type t4p
20+
type(t4p), allocatable :: scalar
21+
end type
22+
type, extends(t4p) :: t4c
23+
end type
24+
type t5p
25+
class(*), pointer :: arr(:)
26+
end type
27+
type, extends(t5p) :: t5c
28+
end type
29+
type t6p
30+
class(*), pointer :: scalar
31+
end type
32+
type, extends(t6p) :: t6c
33+
end type
34+
type t7p
35+
class(*), allocatable :: arr(:)
36+
end type
37+
type, extends(t7p) :: t7c
38+
end type
39+
type t8p
40+
class(*), allocatable :: scalar
41+
end type
42+
type, extends(t8p) :: t8c
43+
end type
44+
45+
type(t1p), target :: t1pt(1)
46+
type(t1p), pointer :: t1pp(:)
47+
type(t2p), target :: t2pt
48+
type(t2p), pointer :: t2pp
49+
type(t3p) t3pa(1)
50+
type(t4p) t4ps
51+
52+
type(t1c) x1
53+
type(t2c) x2
54+
type(t3c) x3
55+
type(t4c) x4
56+
type(t5c) x5
57+
type(t6c) x6
58+
type(t7c) x7
59+
type(t8c) x8
60+
61+
!CHECK: x1=t1c(arr=t1pt)
62+
x1 = t1c(t1pt)
63+
!CHECK: x1=t1c(arr=t1pp)
64+
x1 = t1c(t1pp)
65+
!CHECK: x2=t2c(scalar=t2pt)
66+
x2 = t2c(t2pt)
67+
!CHECK: x2=t2c(scalar=t2pp)
68+
x2 = t2c(t2pp)
69+
!CHECK: x3=t3c(arr=t3pa)
70+
x3 = t3c(t3pa)
71+
!CHECK: x4=t4c(scalar=t4ps)
72+
x4 = t4c(t4ps)
73+
!CHECK: x4=t4c(scalar=t4p(scalar=NULL()))
74+
x4 = t4c(t4p())
75+
!CHECK: x5=t5c(arr=t1pt)
76+
x5 = t5c(t1pt)
77+
!CHECK: x5=t5c(arr=t1pp)
78+
x5 = t5c(t1pp)
79+
!CHECK: x6=t6c(scalar=t2pt)
80+
x6 = t6c(t2pt)
81+
!CHECK: x6=t6c(scalar=t2pp)
82+
x6 = t6c(t2pp)
83+
!CHECK: x7=t7c(arr=t3pa)
84+
x7 = t7c(t3pa)
85+
!CHECK: x8=t8c(scalar=t4ps)
86+
x8 = t8c(t4ps)
87+
!CHECK: x8=t8c(scalar=t4p(scalar=NULL()))
88+
x8 = t8c(t4p())
89+
end

0 commit comments

Comments
 (0)