@@ -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 {
@@ -1970,6 +1982,9 @@ class ResolveNamesVisitor : public virtual ScopeHandler,
1970
1982
Scope &topScope_;
1971
1983
1972
1984
void PreSpecificationConstruct (const parser::SpecificationConstruct &);
1985
+ void EarlyDummyTypeDeclaration (
1986
+ const parser::Statement<common::Indirection<parser::TypeDeclarationStmt>>
1987
+ &);
1973
1988
void CreateCommonBlockSymbols (const parser::CommonStmt &);
1974
1989
void CreateObjectSymbols (const std::list<parser::ObjectDecl> &, Attr);
1975
1990
void CreateGeneric (const parser::GenericSpec &);
@@ -5605,6 +5620,7 @@ Symbol &DeclarationVisitor::DeclareUnknownEntity(
5605
5620
} else {
5606
5621
Symbol &symbol{DeclareEntity<EntityDetails>(name, attrs)};
5607
5622
if (auto *type{GetDeclTypeSpec ()}) {
5623
+ ForgetEarlyDeclaredDummyArgument (symbol);
5608
5624
SetType (name, *type);
5609
5625
}
5610
5626
charInfo_.length .reset ();
@@ -5681,6 +5697,7 @@ Symbol &DeclarationVisitor::DeclareProcEntity(
5681
5697
symbol.set (Symbol::Flag::Subroutine);
5682
5698
}
5683
5699
} else if (auto *type{GetDeclTypeSpec ()}) {
5700
+ ForgetEarlyDeclaredDummyArgument (symbol);
5684
5701
SetType (name, *type);
5685
5702
symbol.set (Symbol::Flag::Function);
5686
5703
}
@@ -5695,6 +5712,7 @@ Symbol &DeclarationVisitor::DeclareObjectEntity(
5695
5712
Symbol &symbol{DeclareEntity<ObjectEntityDetails>(name, attrs)};
5696
5713
if (auto *details{symbol.detailsIf <ObjectEntityDetails>()}) {
5697
5714
if (auto *type{GetDeclTypeSpec ()}) {
5715
+ ForgetEarlyDeclaredDummyArgument (symbol);
5698
5716
SetType (name, *type);
5699
5717
}
5700
5718
if (!arraySpec ().empty ()) {
@@ -5705,9 +5723,11 @@ Symbol &DeclarationVisitor::DeclareObjectEntity(
5705
5723
context ().SetError (symbol);
5706
5724
}
5707
5725
} else if (MustBeScalar (symbol)) {
5708
- context ().Warn (common::UsageWarning::PreviousScalarUse, name.source ,
5709
- " '%s' appeared earlier as a scalar actual argument to a specification function" _warn_en_US,
5710
- name.source );
5726
+ if (!context ().HasError (symbol)) {
5727
+ context ().Warn (common::UsageWarning::PreviousScalarUse, name.source ,
5728
+ " '%s' appeared earlier as a scalar actual argument to a specification function" _warn_en_US,
5729
+ name.source );
5730
+ }
5711
5731
} else if (details->init () || symbol.test (Symbol::Flag::InDataStmt)) {
5712
5732
Say (name, " '%s' was initialized earlier as a scalar" _err_en_US);
5713
5733
} else {
@@ -8461,6 +8481,11 @@ const parser::Name *DeclarationVisitor::ResolveDataRef(
8461
8481
x.u );
8462
8482
}
8463
8483
8484
+ static bool TypesMismatchIfNonNull (
8485
+ const DeclTypeSpec *type1, const DeclTypeSpec *type2) {
8486
+ return type1 && type2 && *type1 != *type2;
8487
+ }
8488
+
8464
8489
// If implicit types are allowed, ensure name is in the symbol table.
8465
8490
// Otherwise, report an error if it hasn't been declared.
8466
8491
const parser::Name *DeclarationVisitor::ResolveName (const parser::Name &name) {
@@ -8482,13 +8507,30 @@ const parser::Name *DeclarationVisitor::ResolveName(const parser::Name &name) {
8482
8507
symbol->set (Symbol::Flag::ImplicitOrError, false );
8483
8508
if (IsUplevelReference (*symbol)) {
8484
8509
MakeHostAssocSymbol (name, *symbol);
8485
- } else if (IsDummy (*symbol) ||
8486
- (!symbol->GetType () && FindCommonBlockContaining (*symbol))) {
8510
+ } else if (IsDummy (*symbol)) {
8487
8511
CheckEntryDummyUse (name.source , symbol);
8512
+ ConvertToObjectEntity (*symbol);
8513
+ if (IsEarlyDeclaredDummyArgument (*symbol)) {
8514
+ ForgetEarlyDeclaredDummyArgument (*symbol);
8515
+ if (isImplicitNoneType ()) {
8516
+ context ().Warn (common::LanguageFeature::ForwardRefImplicitNone,
8517
+ name.source ,
8518
+ " '%s' was used under IMPLICIT NONE(TYPE) before being explicitly typed" _warn_en_US,
8519
+ name.source );
8520
+ } else if (TypesMismatchIfNonNull (
8521
+ symbol->GetType (), GetImplicitType (*symbol))) {
8522
+ context ().Warn (common::LanguageFeature::ForwardRefExplicitTypeDummy,
8523
+ name.source ,
8524
+ " '%s' was used before being explicitly typed (and its implicit type would differ)" _warn_en_US,
8525
+ name.source );
8526
+ }
8527
+ }
8528
+ ApplyImplicitRules (*symbol);
8529
+ } else if (!symbol->GetType () && FindCommonBlockContaining (*symbol)) {
8488
8530
ConvertToObjectEntity (*symbol);
8489
8531
ApplyImplicitRules (*symbol);
8490
8532
} else if (const auto *tpd{symbol->detailsIf <TypeParamDetails>()};
8491
- tpd && !tpd->attr ()) {
8533
+ tpd && !tpd->attr ()) {
8492
8534
Say (name,
8493
8535
" Type parameter '%s' was referenced before being declared" _err_en_US,
8494
8536
name.source );
@@ -9031,11 +9073,6 @@ static bool IsLocallyImplicitGlobalSymbol(
9031
9073
return false ;
9032
9074
}
9033
9075
9034
- static bool TypesMismatchIfNonNull (
9035
- const DeclTypeSpec *type1, const DeclTypeSpec *type2) {
9036
- return type1 && type2 && *type1 != *type2;
9037
- }
9038
-
9039
9076
// Check and set the Function or Subroutine flag on symbol; false on error.
9040
9077
bool ResolveNamesVisitor::SetProcFlag (
9041
9078
const parser::Name &name, Symbol &symbol, Symbol::Flag flag) {
@@ -9252,6 +9289,10 @@ void ResolveNamesVisitor::PreSpecificationConstruct(
9252
9289
const parser::SpecificationConstruct &spec) {
9253
9290
common::visit (
9254
9291
common::visitors{
9292
+ [&](const parser::Statement<
9293
+ common::Indirection<parser::TypeDeclarationStmt>> &y) {
9294
+ EarlyDummyTypeDeclaration (y);
9295
+ },
9255
9296
[&](const parser::Statement<Indirection<parser::GenericStmt>> &y) {
9256
9297
CreateGeneric (std::get<parser::GenericSpec>(y.statement .value ().t ));
9257
9298
},
@@ -9280,6 +9321,44 @@ void ResolveNamesVisitor::PreSpecificationConstruct(
9280
9321
spec.u );
9281
9322
}
9282
9323
9324
+ void ResolveNamesVisitor::EarlyDummyTypeDeclaration (
9325
+ const parser::Statement<common::Indirection<parser::TypeDeclarationStmt>>
9326
+ &stmt) {
9327
+ context ().set_location (stmt.source );
9328
+ const auto &[declTypeSpec, attrs, entities] = stmt.statement .value ().t ;
9329
+ if (const auto *intrin{
9330
+ std::get_if<parser::IntrinsicTypeSpec>(&declTypeSpec.u )}) {
9331
+ if (const auto *intType{std::get_if<parser::IntegerTypeSpec>(&intrin->u )}) {
9332
+ if (const auto &kind{intType->v }) {
9333
+ if (!parser::Unwrap<parser::KindSelector::StarSize>(*kind) &&
9334
+ !parser::Unwrap<parser::IntLiteralConstant>(*kind)) {
9335
+ return ;
9336
+ }
9337
+ }
9338
+ const DeclTypeSpec *type{nullptr };
9339
+ for (const auto &ent : entities) {
9340
+ const auto &objName{std::get<parser::ObjectName>(ent.t )};
9341
+ Resolve (objName, FindInScope (currScope (), objName));
9342
+ if (Symbol * symbol{objName.symbol };
9343
+ symbol && IsDummy (*symbol) && NeedsType (*symbol)) {
9344
+ if (!type) {
9345
+ type = ProcessTypeSpec (declTypeSpec);
9346
+ if (!type || !type->IsNumeric (TypeCategory::Integer)) {
9347
+ break ;
9348
+ }
9349
+ }
9350
+ symbol->SetType (*type);
9351
+ NoteEarlyDeclaredDummyArgument (*symbol);
9352
+ // Set the Implicit flag to disable bogus errors from
9353
+ // being emitted later when this declaration is processed
9354
+ // again normally.
9355
+ symbol->set (Symbol::Flag::Implicit);
9356
+ }
9357
+ }
9358
+ }
9359
+ }
9360
+ }
9361
+
9283
9362
void ResolveNamesVisitor::CreateCommonBlockSymbols (
9284
9363
const parser::CommonStmt &commonStmt) {
9285
9364
for (const parser::CommonStmt::Block &block : commonStmt.blocks ) {
0 commit comments