@@ -1078,6 +1078,9 @@ class DeclarationVisitor : public ArraySpecVisitor,
1078
1078
void EndCheckOnIndexUseInOwnBounds (const std::optional<SourceName> &restore) {
1079
1079
checkIndexUseInOwnBounds_ = restore;
1080
1080
}
1081
+ void NoteScalarSpecificationArgument (const Symbol &symbol) {
1082
+ mustBeScalar_.emplace (symbol);
1083
+ }
1081
1084
1082
1085
private:
1083
1086
// The attribute corresponding to the statement containing an ObjectDecl
@@ -1116,6 +1119,7 @@ class DeclarationVisitor : public ArraySpecVisitor,
1116
1119
std::optional<SourceName> checkIndexUseInOwnBounds_;
1117
1120
bool hasBindCName_{false };
1118
1121
bool isVectorType_{false };
1122
+ UnorderedSymbolSet mustBeScalar_;
1119
1123
1120
1124
bool HandleAttributeStmt (Attr, const std::list<parser::Name> &);
1121
1125
Symbol &HandleAttributeStmt (Attr, const parser::Name &);
@@ -1195,6 +1199,9 @@ class DeclarationVisitor : public ArraySpecVisitor,
1195
1199
return symbol;
1196
1200
}
1197
1201
bool HasCycle (const Symbol &, const Symbol *interface);
1202
+ bool MustBeScalar (const Symbol &symbol) const {
1203
+ return mustBeScalar_.find (symbol) != mustBeScalar_.end ();
1204
+ }
1198
1205
};
1199
1206
1200
1207
// Resolve construct entities and statement entities.
@@ -4886,6 +4893,9 @@ Symbol &DeclarationVisitor::DeclareObjectEntity(
4886
4893
" The dimensions of '%s' have already been declared" _err_en_US);
4887
4894
context ().SetError (symbol);
4888
4895
}
4896
+ } else if (MustBeScalar (symbol)) {
4897
+ Say (name,
4898
+ " '%s' appeared earlier as a scalar actual argument to a specification function" _warn_en_US);
4889
4899
} else {
4890
4900
details->set_shape (arraySpec ());
4891
4901
}
@@ -7635,7 +7645,36 @@ void ResolveNamesVisitor::HandleCall(
7635
7645
},
7636
7646
},
7637
7647
std::get<parser::ProcedureDesignator>(call.t ).u );
7638
- Walk (std::get<std::list<parser::ActualArgSpec>>(call.t ));
7648
+ const auto &arguments{std::get<std::list<parser::ActualArgSpec>>(call.t )};
7649
+ Walk (arguments);
7650
+ // Once an object has appeared in a specification function reference as
7651
+ // a whole scalar actual argument, it cannot be (re)dimensioned later.
7652
+ // The fact that it appeared to be a scalar may determine the resolution
7653
+ // or the result of an inquiry intrinsic function or generic procedure.
7654
+ if (inSpecificationPart_) {
7655
+ for (const auto &argSpec : arguments) {
7656
+ const auto &actual{std::get<parser::ActualArg>(argSpec.t )};
7657
+ if (const auto *expr{
7658
+ std::get_if<common::Indirection<parser::Expr>>(&actual.u )}) {
7659
+ if (const auto *designator{
7660
+ std::get_if<common::Indirection<parser::Designator>>(
7661
+ &expr->value ().u )}) {
7662
+ if (const auto *dataRef{
7663
+ std::get_if<parser::DataRef>(&designator->value ().u )}) {
7664
+ if (const auto *name{std::get_if<parser::Name>(&dataRef->u )};
7665
+ name && name->symbol ) {
7666
+ const Symbol &symbol{*name->symbol };
7667
+ const auto *object{symbol.detailsIf <ObjectEntityDetails>()};
7668
+ if (symbol.has <EntityDetails>() ||
7669
+ (object && !object->IsArray ())) {
7670
+ NoteScalarSpecificationArgument (symbol);
7671
+ }
7672
+ }
7673
+ }
7674
+ }
7675
+ }
7676
+ }
7677
+ }
7639
7678
}
7640
7679
7641
7680
void ResolveNamesVisitor::HandleProcedureName (
0 commit comments