@@ -768,10 +768,22 @@ class ScopeHandler : public ImplicitRulesVisitor {
768
768
deferImplicitTyping_ = skipImplicitTyping_ = skip;
769
769
}
770
770
771
+ void NoteEarlyDeclaredDummyArgument (Symbol &symbol) {
772
+ earlyDeclaredDummyArguments_.insert (symbol);
773
+ }
774
+ bool IsEarlyDeclaredDummyArgument (Symbol &symbol) {
775
+ return earlyDeclaredDummyArguments_.find (symbol) !=
776
+ earlyDeclaredDummyArguments_.end ();
777
+ }
778
+ void ForgetEarlyDeclaredDummyArgument (Symbol &symbol) {
779
+ earlyDeclaredDummyArguments_.erase (symbol);
780
+ }
781
+
771
782
private:
772
783
Scope *currScope_{nullptr };
773
784
FuncResultStack funcResultStack_{*this };
774
785
std::map<Scope *, DeferredDeclarationState> deferred_;
786
+ UnorderedSymbolSet earlyDeclaredDummyArguments_;
775
787
};
776
788
777
789
class ModuleVisitor : public virtual ScopeHandler {
@@ -1119,6 +1131,7 @@ class DeclarationVisitor : public ArraySpecVisitor,
1119
1131
template <typename T>
1120
1132
Symbol &DeclareEntity (const parser::Name &name, Attrs attrs) {
1121
1133
Symbol &symbol{MakeSymbol (name, attrs)};
1134
+ ForgetEarlyDeclaredDummyArgument (symbol);
1122
1135
if (context ().HasError (symbol) || symbol.has <T>()) {
1123
1136
return symbol; // OK or error already reported
1124
1137
} else if (symbol.has <UnknownDetails>()) {
@@ -1976,6 +1989,9 @@ class ResolveNamesVisitor : public virtual ScopeHandler,
1976
1989
Scope &topScope_;
1977
1990
1978
1991
void PreSpecificationConstruct (const parser::SpecificationConstruct &);
1992
+ void EarlyDummyTypeDeclaration (
1993
+ const parser::Statement<common::Indirection<parser::TypeDeclarationStmt>>
1994
+ &);
1979
1995
void CreateCommonBlockSymbols (const parser::CommonStmt &);
1980
1996
void CreateObjectSymbols (const std::list<parser::ObjectDecl> &, Attr);
1981
1997
void CreateGeneric (const parser::GenericSpec &);
@@ -8488,13 +8504,24 @@ const parser::Name *DeclarationVisitor::ResolveName(const parser::Name &name) {
8488
8504
symbol->set (Symbol::Flag::ImplicitOrError, false );
8489
8505
if (IsUplevelReference (*symbol)) {
8490
8506
MakeHostAssocSymbol (name, *symbol);
8491
- } else if (IsDummy (*symbol) ||
8492
- (!symbol->GetType () && FindCommonBlockContaining (*symbol))) {
8507
+ } else if (IsDummy (*symbol)) {
8493
8508
CheckEntryDummyUse (name.source , symbol);
8509
+ ConvertToObjectEntity (*symbol);
8510
+ if (IsEarlyDeclaredDummyArgument (*symbol)) {
8511
+ ForgetEarlyDeclaredDummyArgument (*symbol);
8512
+ if (isImplicitNoneType ()) {
8513
+ context ().Warn (common::LanguageFeature::ForwardRefImplicitNone,
8514
+ name.source ,
8515
+ " '%s' was used under IMPLICIT NONE(TYPE) before being explicitly typed" _warn_en_US,
8516
+ name.source );
8517
+ }
8518
+ }
8519
+ ApplyImplicitRules (*symbol);
8520
+ } else if (!symbol->GetType () && FindCommonBlockContaining (*symbol)) {
8494
8521
ConvertToObjectEntity (*symbol);
8495
8522
ApplyImplicitRules (*symbol);
8496
8523
} else if (const auto *tpd{symbol->detailsIf <TypeParamDetails>()};
8497
- tpd && !tpd->attr ()) {
8524
+ tpd && !tpd->attr ()) {
8498
8525
Say (name,
8499
8526
" Type parameter '%s' was referenced before being declared" _err_en_US,
8500
8527
name.source );
@@ -9258,6 +9285,10 @@ void ResolveNamesVisitor::PreSpecificationConstruct(
9258
9285
const parser::SpecificationConstruct &spec) {
9259
9286
common::visit (
9260
9287
common::visitors{
9288
+ [&](const parser::Statement<
9289
+ common::Indirection<parser::TypeDeclarationStmt>> &y) {
9290
+ EarlyDummyTypeDeclaration (y);
9291
+ },
9261
9292
[&](const parser::Statement<Indirection<parser::GenericStmt>> &y) {
9262
9293
CreateGeneric (std::get<parser::GenericSpec>(y.statement .value ().t ));
9263
9294
},
@@ -9286,6 +9317,44 @@ void ResolveNamesVisitor::PreSpecificationConstruct(
9286
9317
spec.u );
9287
9318
}
9288
9319
9320
+ void ResolveNamesVisitor::EarlyDummyTypeDeclaration (
9321
+ const parser::Statement<common::Indirection<parser::TypeDeclarationStmt>>
9322
+ &stmt) {
9323
+ context ().set_location (stmt.source );
9324
+ const auto &[declTypeSpec, attrs, entities] = stmt.statement .value ().t ;
9325
+ if (const auto *intrin{
9326
+ std::get_if<parser::IntrinsicTypeSpec>(&declTypeSpec.u )}) {
9327
+ if (const auto *intType{std::get_if<parser::IntegerTypeSpec>(&intrin->u )}) {
9328
+ if (const auto &kind{intType->v }) {
9329
+ if (!parser::Unwrap<parser::KindSelector::StarSize>(*kind) &&
9330
+ !parser::Unwrap<parser::IntLiteralConstant>(*kind)) {
9331
+ return ;
9332
+ }
9333
+ }
9334
+ const DeclTypeSpec *type{nullptr };
9335
+ for (const auto &ent : entities) {
9336
+ const auto &objName{std::get<parser::ObjectName>(ent.t )};
9337
+ Resolve (objName, FindInScope (currScope (), objName));
9338
+ if (Symbol * symbol{objName.symbol };
9339
+ symbol && IsDummy (*symbol) && NeedsType (*symbol)) {
9340
+ if (!type) {
9341
+ type = ProcessTypeSpec (declTypeSpec);
9342
+ if (!type || !type->IsNumeric (TypeCategory::Integer)) {
9343
+ break ;
9344
+ }
9345
+ }
9346
+ symbol->SetType (*type);
9347
+ NoteEarlyDeclaredDummyArgument (*symbol);
9348
+ // Set the Implicit flag to disable bogus errors from
9349
+ // being emitted later when this declaration is processed
9350
+ // again normally.
9351
+ symbol->set (Symbol::Flag::Implicit);
9352
+ }
9353
+ }
9354
+ }
9355
+ }
9356
+ }
9357
+
9289
9358
void ResolveNamesVisitor::CreateCommonBlockSymbols (
9290
9359
const parser::CommonStmt &commonStmt) {
9291
9360
for (const parser::CommonStmt::Block &block : commonStmt.blocks ) {
0 commit comments