@@ -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 &);
@@ -5711,9 +5727,11 @@ Symbol &DeclarationVisitor::DeclareObjectEntity(
5711
5727
context ().SetError (symbol);
5712
5728
}
5713
5729
} 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 );
5730
+ if (!context ().HasError (symbol)) {
5731
+ context ().Warn (common::UsageWarning::PreviousScalarUse, name.source ,
5732
+ " '%s' appeared earlier as a scalar actual argument to a specification function" _warn_en_US,
5733
+ name.source );
5734
+ }
5717
5735
} else if (details->init () || symbol.test (Symbol::Flag::InDataStmt)) {
5718
5736
Say (name, " '%s' was initialized earlier as a scalar" _err_en_US);
5719
5737
} else {
@@ -8467,6 +8485,11 @@ const parser::Name *DeclarationVisitor::ResolveDataRef(
8467
8485
x.u );
8468
8486
}
8469
8487
8488
+ static bool TypesMismatchIfNonNull (
8489
+ const DeclTypeSpec *type1, const DeclTypeSpec *type2) {
8490
+ return type1 && type2 && *type1 != *type2;
8491
+ }
8492
+
8470
8493
// If implicit types are allowed, ensure name is in the symbol table.
8471
8494
// Otherwise, report an error if it hasn't been declared.
8472
8495
const parser::Name *DeclarationVisitor::ResolveName (const parser::Name &name) {
@@ -8488,13 +8511,30 @@ const parser::Name *DeclarationVisitor::ResolveName(const parser::Name &name) {
8488
8511
symbol->set (Symbol::Flag::ImplicitOrError, false );
8489
8512
if (IsUplevelReference (*symbol)) {
8490
8513
MakeHostAssocSymbol (name, *symbol);
8491
- } else if (IsDummy (*symbol) ||
8492
- (!symbol->GetType () && FindCommonBlockContaining (*symbol))) {
8514
+ } else if (IsDummy (*symbol)) {
8493
8515
CheckEntryDummyUse (name.source , symbol);
8516
+ ConvertToObjectEntity (*symbol);
8517
+ if (IsEarlyDeclaredDummyArgument (*symbol)) {
8518
+ ForgetEarlyDeclaredDummyArgument (*symbol);
8519
+ if (isImplicitNoneType ()) {
8520
+ context ().Warn (common::LanguageFeature::ForwardRefImplicitNone,
8521
+ name.source ,
8522
+ " '%s' was used under IMPLICIT NONE(TYPE) before being explicitly typed" _warn_en_US,
8523
+ name.source );
8524
+ } else if (TypesMismatchIfNonNull (
8525
+ symbol->GetType (), GetImplicitType (*symbol))) {
8526
+ context ().Warn (common::LanguageFeature::ForwardRefExplicitTypeDummy,
8527
+ name.source ,
8528
+ " '%s' was used before being explicitly typed (and its implicit type would differ)" _warn_en_US,
8529
+ name.source );
8530
+ }
8531
+ }
8532
+ ApplyImplicitRules (*symbol);
8533
+ } else if (!symbol->GetType () && FindCommonBlockContaining (*symbol)) {
8494
8534
ConvertToObjectEntity (*symbol);
8495
8535
ApplyImplicitRules (*symbol);
8496
8536
} else if (const auto *tpd{symbol->detailsIf <TypeParamDetails>()};
8497
- tpd && !tpd->attr ()) {
8537
+ tpd && !tpd->attr ()) {
8498
8538
Say (name,
8499
8539
" Type parameter '%s' was referenced before being declared" _err_en_US,
8500
8540
name.source );
@@ -9037,11 +9077,6 @@ static bool IsLocallyImplicitGlobalSymbol(
9037
9077
return false ;
9038
9078
}
9039
9079
9040
- static bool TypesMismatchIfNonNull (
9041
- const DeclTypeSpec *type1, const DeclTypeSpec *type2) {
9042
- return type1 && type2 && *type1 != *type2;
9043
- }
9044
-
9045
9080
// Check and set the Function or Subroutine flag on symbol; false on error.
9046
9081
bool ResolveNamesVisitor::SetProcFlag (
9047
9082
const parser::Name &name, Symbol &symbol, Symbol::Flag flag) {
@@ -9258,6 +9293,10 @@ void ResolveNamesVisitor::PreSpecificationConstruct(
9258
9293
const parser::SpecificationConstruct &spec) {
9259
9294
common::visit (
9260
9295
common::visitors{
9296
+ [&](const parser::Statement<
9297
+ common::Indirection<parser::TypeDeclarationStmt>> &y) {
9298
+ EarlyDummyTypeDeclaration (y);
9299
+ },
9261
9300
[&](const parser::Statement<Indirection<parser::GenericStmt>> &y) {
9262
9301
CreateGeneric (std::get<parser::GenericSpec>(y.statement .value ().t ));
9263
9302
},
@@ -9286,6 +9325,44 @@ void ResolveNamesVisitor::PreSpecificationConstruct(
9286
9325
spec.u );
9287
9326
}
9288
9327
9328
+ void ResolveNamesVisitor::EarlyDummyTypeDeclaration (
9329
+ const parser::Statement<common::Indirection<parser::TypeDeclarationStmt>>
9330
+ &stmt) {
9331
+ context ().set_location (stmt.source );
9332
+ const auto &[declTypeSpec, attrs, entities] = stmt.statement .value ().t ;
9333
+ if (const auto *intrin{
9334
+ std::get_if<parser::IntrinsicTypeSpec>(&declTypeSpec.u )}) {
9335
+ if (const auto *intType{std::get_if<parser::IntegerTypeSpec>(&intrin->u )}) {
9336
+ if (const auto &kind{intType->v }) {
9337
+ if (!parser::Unwrap<parser::KindSelector::StarSize>(*kind) &&
9338
+ !parser::Unwrap<parser::IntLiteralConstant>(*kind)) {
9339
+ return ;
9340
+ }
9341
+ }
9342
+ const DeclTypeSpec *type{nullptr };
9343
+ for (const auto &ent : entities) {
9344
+ const auto &objName{std::get<parser::ObjectName>(ent.t )};
9345
+ Resolve (objName, FindInScope (currScope (), objName));
9346
+ if (Symbol * symbol{objName.symbol };
9347
+ symbol && IsDummy (*symbol) && NeedsType (*symbol)) {
9348
+ if (!type) {
9349
+ type = ProcessTypeSpec (declTypeSpec);
9350
+ if (!type || !type->IsNumeric (TypeCategory::Integer)) {
9351
+ break ;
9352
+ }
9353
+ }
9354
+ symbol->SetType (*type);
9355
+ NoteEarlyDeclaredDummyArgument (*symbol);
9356
+ // Set the Implicit flag to disable bogus errors from
9357
+ // being emitted later when this declaration is processed
9358
+ // again normally.
9359
+ symbol->set (Symbol::Flag::Implicit);
9360
+ }
9361
+ }
9362
+ }
9363
+ }
9364
+ }
9365
+
9289
9366
void ResolveNamesVisitor::CreateCommonBlockSymbols (
9290
9367
const parser::CommonStmt &commonStmt) {
9291
9368
for (const parser::CommonStmt::Block &block : commonStmt.blocks ) {
0 commit comments