Skip to content

Commit 10cc4a5

Browse files
authored
[flang] More support for anonymous parent components in struct constr… (#102642)
…uctors A non-conforming extension to Fortran present in a couple other compilers is allowing a anonymous component in a structure constructor to initialize a parent (or greater ancestor) component. This was working in this compiler only for direct parents, and only when the type was not use-associated. Fixes #102557.
1 parent ce132a5 commit 10cc4a5

File tree

2 files changed

+49
-13
lines changed

2 files changed

+49
-13
lines changed

flang/lib/Semantics/expression.cpp

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2015,6 +2015,15 @@ MaybeExpr ExpressionAnalyzer::Analyze(
20152015
// initialize X or A by name, but not both.
20162016
auto components{semantics::OrderedComponentIterator{spec}};
20172017
auto nextAnonymous{components.begin()};
2018+
auto afterLastParentComponentIter{components.end()};
2019+
if (parentComponent) {
2020+
for (auto iter{components.begin()}; iter != components.end(); ++iter) {
2021+
if (iter->test(Symbol::Flag::ParentComp)) {
2022+
afterLastParentComponentIter = iter;
2023+
++afterLastParentComponentIter;
2024+
}
2025+
}
2026+
}
20182027

20192028
std::set<parser::CharBlock> unavailable;
20202029
bool anyKeyword{false};
@@ -2060,20 +2069,22 @@ MaybeExpr ExpressionAnalyzer::Analyze(
20602069
}
20612070
// Here's a regrettably common extension of the standard: anonymous
20622071
// initialization of parent components, e.g., T(PT(1)) rather than
2063-
// T(1) or T(PT=PT(1)).
2064-
if (nextAnonymous == components.begin() && parentComponent &&
2065-
valueType == DynamicType::From(*parentComponent) &&
2072+
// T(1) or T(PT=PT(1)). There may be multiple parent components.
2073+
if (nextAnonymous == components.begin() && parentComponent && valueType &&
20662074
context().IsEnabled(LanguageFeature::AnonymousParents)) {
2067-
auto iter{
2068-
std::find(components.begin(), components.end(), *parentComponent)};
2069-
if (iter != components.end()) {
2070-
symbol = parentComponent;
2071-
nextAnonymous = ++iter;
2072-
if (context().ShouldWarn(LanguageFeature::AnonymousParents)) {
2073-
Say(source,
2074-
"Whole parent component '%s' in structure "
2075-
"constructor should not be anonymous"_port_en_US,
2076-
symbol->name());
2075+
for (auto parent{components.begin()};
2076+
parent != afterLastParentComponentIter; ++parent) {
2077+
if (auto parentType{DynamicType::From(*parent)}; parentType &&
2078+
parent->test(Symbol::Flag::ParentComp) &&
2079+
valueType->IsEquivalentTo(*parentType)) {
2080+
symbol = &*parent;
2081+
nextAnonymous = ++parent;
2082+
if (context().ShouldWarn(LanguageFeature::AnonymousParents)) {
2083+
Say(source,
2084+
"Whole parent component '%s' in structure constructor should not be anonymous"_port_en_US,
2085+
symbol->name());
2086+
}
2087+
break;
20772088
}
20782089
}
20792090
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic -Werror
2+
module m1
3+
type a1
4+
integer ::x1=1
5+
end type a1
6+
type,extends(a1)::a2
7+
integer ::x2=3
8+
end type a2
9+
type,extends(a2)::a3
10+
integer ::x3=3
11+
end type a3
12+
end module m1
13+
14+
program test
15+
use m1
16+
type(a3) v
17+
!PORTABILITY: Whole parent component 'a2' in structure constructor should not be anonymous
18+
v=a3(a2(x1=18,x2=6),x3=6)
19+
!PORTABILITY: Whole parent component 'a1' in structure constructor should not be anonymous
20+
v=a3(a1(x1=18),x2=6,x3=6)
21+
!PORTABILITY: Whole parent component 'a2' in structure constructor should not be anonymous
22+
!PORTABILITY: Whole parent component 'a1' in structure constructor should not be anonymous
23+
v=a3(a2(a1(x1=18),x2=6),x3=6)
24+
v=a3(a2=a2(a1=a1(x1=18),x2=6),x3=6) ! ok
25+
end

0 commit comments

Comments
 (0)