Skip to content

Commit 147f54e

Browse files
authored
[flang] Accept whole assumed-size arrays as variable selectors (#82806)
Include variable selectors ("select type (x => y)") as a context in which a whole assumed-size array may legitimately appear. Fixes #81910.
1 parent 1c530b3 commit 147f54e

File tree

2 files changed

+34
-10
lines changed

2 files changed

+34
-10
lines changed

flang/lib/Semantics/expression.cpp

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -973,7 +973,8 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::Name &n) {
973973
}
974974
}
975975
if (!isWholeAssumedSizeArrayOk_ &&
976-
semantics::IsAssumedSizeArray(*n.symbol)) { // C1002, C1014, C1231
976+
semantics::IsAssumedSizeArray(
977+
ResolveAssociations(*n.symbol))) { // C1002, C1014, C1231
977978
AttachDeclaration(
978979
SayAt(n,
979980
"Whole assumed-size array '%s' may not appear here without subscripts"_err_en_US,
@@ -1329,15 +1330,29 @@ std::optional<Component> ExpressionAnalyzer::CreateComponent(DataRef &&base,
13291330

13301331
// Derived type component references and type parameter inquiries
13311332
MaybeExpr ExpressionAnalyzer::Analyze(const parser::StructureComponent &sc) {
1332-
MaybeExpr base{Analyze(sc.base)};
13331333
Symbol *sym{sc.component.symbol};
1334-
if (!base || !sym || context_.HasError(sym)) {
1334+
if (context_.HasError(sym)) {
1335+
return std::nullopt;
1336+
}
1337+
const auto *misc{sym->detailsIf<semantics::MiscDetails>()};
1338+
bool isTypeParamInquiry{sym->has<semantics::TypeParamDetails>() ||
1339+
(misc &&
1340+
(misc->kind() == semantics::MiscDetails::Kind::KindParamInquiry ||
1341+
misc->kind() == semantics::MiscDetails::Kind::LenParamInquiry))};
1342+
MaybeExpr base;
1343+
if (isTypeParamInquiry) {
1344+
auto restorer{AllowWholeAssumedSizeArray()};
1345+
base = Analyze(sc.base);
1346+
} else {
1347+
base = Analyze(sc.base);
1348+
}
1349+
if (!base) {
13351350
return std::nullopt;
13361351
}
13371352
const auto &name{sc.component.source};
13381353
if (auto *dtExpr{UnwrapExpr<Expr<SomeDerived>>(*base)}) {
13391354
const auto *dtSpec{GetDerivedTypeSpec(dtExpr->GetType())};
1340-
if (sym->detailsIf<semantics::TypeParamDetails>()) {
1355+
if (isTypeParamInquiry) {
13411356
if (auto *designator{UnwrapExpr<Designator<SomeDerived>>(*dtExpr)}) {
13421357
if (std::optional<DynamicType> dyType{DynamicType::From(*sym)}) {
13431358
if (dyType->category() == TypeCategory::Integer) {
@@ -1350,8 +1365,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::StructureComponent &sc) {
13501365
Say(name, "Type parameter is not INTEGER"_err_en_US);
13511366
} else {
13521367
Say(name,
1353-
"A type parameter inquiry must be applied to "
1354-
"a designator"_err_en_US);
1368+
"A type parameter inquiry must be applied to a designator"_err_en_US);
13551369
}
13561370
} else if (!dtSpec || !dtSpec->scope()) {
13571371
CHECK(context_.AnyFatalError() || !foldingContext_.messages().empty());
@@ -1393,8 +1407,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::StructureComponent &sc) {
13931407
return AsGenericExpr(std::move(realExpr));
13941408
}
13951409
}
1396-
} else if (kind == MiscKind::KindParamInquiry ||
1397-
kind == MiscKind::LenParamInquiry) {
1410+
} else if (isTypeParamInquiry) { // %kind or %len
13981411
ActualArgument arg{std::move(*base)};
13991412
SetArgSourceLocation(arg, name);
14001413
return MakeFunctionRef(name, ActualArguments{std::move(arg)});
@@ -3743,9 +3756,12 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::Selector &selector) {
37433756
}
37443757
}
37453758
}
3759+
// Not a Variable -> FunctionReference
3760+
auto restorer{AllowWholeAssumedSizeArray()};
3761+
return Analyze(selector.u);
3762+
} else { // Expr
3763+
return Analyze(selector.u);
37463764
}
3747-
// Not a Variable -> FunctionReference; handle normally as Variable or Expr
3748-
return Analyze(selector.u);
37493765
}
37503766

37513767
MaybeExpr ExpressionAnalyzer::Analyze(const parser::DataStmtConstant &x) {
@@ -4001,6 +4017,7 @@ void ArgumentAnalyzer::Analyze(
40014017
const parser::ActualArgSpec &arg, bool isSubroutine) {
40024018
// TODO: C1534: Don't allow a "restricted" specific intrinsic to be passed.
40034019
std::optional<ActualArgument> actual;
4020+
auto restorer{context_.AllowWholeAssumedSizeArray()};
40044021
common::visit(
40054022
common::visitors{
40064023
[&](const common::Indirection<parser::Expr> &x) {

flang/test/Semantics/assign04.f90

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,13 @@ subroutine s6(x)
105105
x(:) = [1, 2, 3]
106106
!ERROR: Whole assumed-size array 'x' may not appear here without subscripts
107107
x = [1, 2, 3]
108+
associate (y => x) ! ok
109+
!ERROR: Whole assumed-size array 'y' may not appear here without subscripts
110+
y = [1, 2, 3]
111+
end associate
112+
!ERROR: Whole assumed-size array 'x' may not appear here without subscripts
113+
associate (y => (x))
114+
end associate
108115
end
109116

110117
module m7

0 commit comments

Comments
 (0)