@@ -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 {
@@ -1976,6 +1988,9 @@ class ResolveNamesVisitor : public virtual ScopeHandler,
1976
1988
Scope &topScope_;
1977
1989
1978
1990
void PreSpecificationConstruct (const parser::SpecificationConstruct &);
1991
+ void EarlyDummyTypeDeclaration (
1992
+ const parser::Statement<common::Indirection<parser::TypeDeclarationStmt>>
1993
+ &);
1979
1994
void CreateCommonBlockSymbols (const parser::CommonStmt &);
1980
1995
void CreateObjectSymbols (const std::list<parser::ObjectDecl> &, Attr);
1981
1996
void CreateGeneric (const parser::GenericSpec &);
@@ -5611,6 +5626,7 @@ Symbol &DeclarationVisitor::DeclareUnknownEntity(
5611
5626
} else {
5612
5627
Symbol &symbol{DeclareEntity<EntityDetails>(name, attrs)};
5613
5628
if (auto *type{GetDeclTypeSpec ()}) {
5629
+ ForgetEarlyDeclaredDummyArgument (symbol);
5614
5630
SetType (name, *type);
5615
5631
}
5616
5632
charInfo_.length .reset ();
@@ -5687,6 +5703,7 @@ Symbol &DeclarationVisitor::DeclareProcEntity(
5687
5703
symbol.set (Symbol::Flag::Subroutine);
5688
5704
}
5689
5705
} else if (auto *type{GetDeclTypeSpec ()}) {
5706
+ ForgetEarlyDeclaredDummyArgument (symbol);
5690
5707
SetType (name, *type);
5691
5708
symbol.set (Symbol::Flag::Function);
5692
5709
}
@@ -5701,6 +5718,7 @@ Symbol &DeclarationVisitor::DeclareObjectEntity(
5701
5718
Symbol &symbol{DeclareEntity<ObjectEntityDetails>(name, attrs)};
5702
5719
if (auto *details{symbol.detailsIf <ObjectEntityDetails>()}) {
5703
5720
if (auto *type{GetDeclTypeSpec ()}) {
5721
+ ForgetEarlyDeclaredDummyArgument (symbol);
5704
5722
SetType (name, *type);
5705
5723
}
5706
5724
if (!arraySpec ().empty ()) {
@@ -5711,9 +5729,11 @@ Symbol &DeclarationVisitor::DeclareObjectEntity(
5711
5729
context ().SetError (symbol);
5712
5730
}
5713
5731
} else if (MustBeScalar (symbol)) {
5714
- context ().Warn (common::UsageWarning::PreviousScalarUse, name.source ,
5715
- " '%s' appeared earlier as a scalar actual argument to a specification function" _warn_en_US,
5716
- name.source );
5732
+ if (!context ().HasError (symbol)) {
5733
+ context ().Warn (common::UsageWarning::PreviousScalarUse, name.source ,
5734
+ " '%s' appeared earlier as a scalar actual argument to a specification function" _warn_en_US,
5735
+ name.source );
5736
+ }
5717
5737
} else if (details->init () || symbol.test (Symbol::Flag::InDataStmt)) {
5718
5738
Say (name, " '%s' was initialized earlier as a scalar" _err_en_US);
5719
5739
} else {
@@ -8467,6 +8487,11 @@ const parser::Name *DeclarationVisitor::ResolveDataRef(
8467
8487
x.u );
8468
8488
}
8469
8489
8490
+ static bool TypesMismatchIfNonNull (
8491
+ const DeclTypeSpec *type1, const DeclTypeSpec *type2) {
8492
+ return type1 && type2 && *type1 != *type2;
8493
+ }
8494
+
8470
8495
// If implicit types are allowed, ensure name is in the symbol table.
8471
8496
// Otherwise, report an error if it hasn't been declared.
8472
8497
const parser::Name *DeclarationVisitor::ResolveName (const parser::Name &name) {
@@ -8488,13 +8513,30 @@ const parser::Name *DeclarationVisitor::ResolveName(const parser::Name &name) {
8488
8513
symbol->set (Symbol::Flag::ImplicitOrError, false );
8489
8514
if (IsUplevelReference (*symbol)) {
8490
8515
MakeHostAssocSymbol (name, *symbol);
8491
- } else if (IsDummy (*symbol) ||
8492
- (!symbol->GetType () && FindCommonBlockContaining (*symbol))) {
8516
+ } else if (IsDummy (*symbol)) {
8493
8517
CheckEntryDummyUse (name.source , symbol);
8518
+ ConvertToObjectEntity (*symbol);
8519
+ if (IsEarlyDeclaredDummyArgument (*symbol)) {
8520
+ ForgetEarlyDeclaredDummyArgument (*symbol);
8521
+ if (isImplicitNoneType ()) {
8522
+ context ().Warn (common::LanguageFeature::ForwardRefImplicitNone,
8523
+ name.source ,
8524
+ " '%s' was used under IMPLICIT NONE(TYPE) before being explicitly typed" _warn_en_US,
8525
+ name.source );
8526
+ } else if (TypesMismatchIfNonNull (
8527
+ symbol->GetType (), GetImplicitType (*symbol))) {
8528
+ context ().Warn (common::LanguageFeature::ForwardRefExplicitTypeDummy,
8529
+ name.source ,
8530
+ " '%s' was used before being explicitly typed (and its implicit type would differ)" _warn_en_US,
8531
+ name.source );
8532
+ }
8533
+ }
8534
+ ApplyImplicitRules (*symbol);
8535
+ } else if (!symbol->GetType () && FindCommonBlockContaining (*symbol)) {
8494
8536
ConvertToObjectEntity (*symbol);
8495
8537
ApplyImplicitRules (*symbol);
8496
8538
} else if (const auto *tpd{symbol->detailsIf <TypeParamDetails>()};
8497
- tpd && !tpd->attr ()) {
8539
+ tpd && !tpd->attr ()) {
8498
8540
Say (name,
8499
8541
" Type parameter '%s' was referenced before being declared" _err_en_US,
8500
8542
name.source );
@@ -9037,11 +9079,6 @@ static bool IsLocallyImplicitGlobalSymbol(
9037
9079
return false ;
9038
9080
}
9039
9081
9040
- static bool TypesMismatchIfNonNull (
9041
- const DeclTypeSpec *type1, const DeclTypeSpec *type2) {
9042
- return type1 && type2 && *type1 != *type2;
9043
- }
9044
-
9045
9082
// Check and set the Function or Subroutine flag on symbol; false on error.
9046
9083
bool ResolveNamesVisitor::SetProcFlag (
9047
9084
const parser::Name &name, Symbol &symbol, Symbol::Flag flag) {
@@ -9258,6 +9295,10 @@ void ResolveNamesVisitor::PreSpecificationConstruct(
9258
9295
const parser::SpecificationConstruct &spec) {
9259
9296
common::visit (
9260
9297
common::visitors{
9298
+ [&](const parser::Statement<
9299
+ common::Indirection<parser::TypeDeclarationStmt>> &y) {
9300
+ EarlyDummyTypeDeclaration (y);
9301
+ },
9261
9302
[&](const parser::Statement<Indirection<parser::GenericStmt>> &y) {
9262
9303
CreateGeneric (std::get<parser::GenericSpec>(y.statement .value ().t ));
9263
9304
},
@@ -9286,6 +9327,44 @@ void ResolveNamesVisitor::PreSpecificationConstruct(
9286
9327
spec.u );
9287
9328
}
9288
9329
9330
+ void ResolveNamesVisitor::EarlyDummyTypeDeclaration (
9331
+ const parser::Statement<common::Indirection<parser::TypeDeclarationStmt>>
9332
+ &stmt) {
9333
+ context ().set_location (stmt.source );
9334
+ const auto &[declTypeSpec, attrs, entities] = stmt.statement .value ().t ;
9335
+ if (const auto *intrin{
9336
+ std::get_if<parser::IntrinsicTypeSpec>(&declTypeSpec.u )}) {
9337
+ if (const auto *intType{std::get_if<parser::IntegerTypeSpec>(&intrin->u )}) {
9338
+ if (const auto &kind{intType->v }) {
9339
+ if (!parser::Unwrap<parser::KindSelector::StarSize>(*kind) &&
9340
+ !parser::Unwrap<parser::IntLiteralConstant>(*kind)) {
9341
+ return ;
9342
+ }
9343
+ }
9344
+ const DeclTypeSpec *type{nullptr };
9345
+ for (const auto &ent : entities) {
9346
+ const auto &objName{std::get<parser::ObjectName>(ent.t )};
9347
+ Resolve (objName, FindInScope (currScope (), objName));
9348
+ if (Symbol * symbol{objName.symbol };
9349
+ symbol && IsDummy (*symbol) && NeedsType (*symbol)) {
9350
+ if (!type) {
9351
+ type = ProcessTypeSpec (declTypeSpec);
9352
+ if (!type || !type->IsNumeric (TypeCategory::Integer)) {
9353
+ break ;
9354
+ }
9355
+ }
9356
+ symbol->SetType (*type);
9357
+ NoteEarlyDeclaredDummyArgument (*symbol);
9358
+ // Set the Implicit flag to disable bogus errors from
9359
+ // being emitted later when this declaration is processed
9360
+ // again normally.
9361
+ symbol->set (Symbol::Flag::Implicit);
9362
+ }
9363
+ }
9364
+ }
9365
+ }
9366
+ }
9367
+
9289
9368
void ResolveNamesVisitor::CreateCommonBlockSymbols (
9290
9369
const parser::CommonStmt &commonStmt) {
9291
9370
for (const parser::CommonStmt::Block &block : commonStmt.blocks ) {
0 commit comments