@@ -578,7 +578,9 @@ class ScopeHandler : public ImplicitRulesVisitor {
578
578
symbol->attrs () |= attrs;
579
579
return *symbol;
580
580
} else {
581
- SayAlreadyDeclared (name, *symbol);
581
+ if (!CheckPossibleBadForwardRef (*symbol)) {
582
+ SayAlreadyDeclared (name, *symbol);
583
+ }
582
584
// replace the old symbol with a new one with correct details
583
585
EraseSymbol (*symbol);
584
586
auto &result{MakeSymbol (name, attrs, std::move (details))};
@@ -600,8 +602,13 @@ class ScopeHandler : public ImplicitRulesVisitor {
600
602
TypeCategory, const std::optional<parser::KindSelector> &);
601
603
const DeclTypeSpec &MakeLogicalType (
602
604
const std::optional<parser::KindSelector> &);
605
+ void NotePossibleBadForwardRef (const parser::Name &);
606
+ std::optional<SourceName> HadForwardRef (const Symbol &) const ;
607
+ bool CheckPossibleBadForwardRef (const Symbol &);
603
608
604
609
bool inExecutionPart_{false };
610
+ bool inSpecificationPart_{false };
611
+ std::set<SourceName> specPartForwardRefs_;
605
612
606
613
private:
607
614
Scope *currScope_{nullptr };
@@ -982,7 +989,7 @@ class DeclarationVisitor : public ArraySpecVisitor,
982
989
SayWithDecl (
983
990
name, symbol, " '%s' is already declared as an object" _err_en_US);
984
991
}
985
- } else {
992
+ } else if (! CheckPossibleBadForwardRef (symbol)) {
986
993
SayAlreadyDeclared (name, symbol);
987
994
}
988
995
context ().SetError (symbol);
@@ -1880,15 +1887,17 @@ void ScopeHandler::SayAlreadyDeclared(const parser::Name &name, Symbol &prev) {
1880
1887
void ScopeHandler::SayAlreadyDeclared (const SourceName &name, Symbol &prev) {
1881
1888
if (context ().HasError (prev)) {
1882
1889
// don't report another error about prev
1883
- } else if (const auto *details{prev.detailsIf <UseDetails>()}) {
1884
- Say (name, " '%s' is already declared in this scoping unit" _err_en_US)
1885
- .Attach (details->location (),
1886
- " It is use-associated with '%s' in module '%s'" _err_en_US,
1887
- details->symbol ().name (), GetUsedModule (*details).name ());
1888
1890
} else {
1889
- SayAlreadyDeclared (name, prev.name ());
1891
+ if (const auto *details{prev.detailsIf <UseDetails>()}) {
1892
+ Say (name, " '%s' is already declared in this scoping unit" _err_en_US)
1893
+ .Attach (details->location (),
1894
+ " It is use-associated with '%s' in module '%s'" _err_en_US,
1895
+ details->symbol ().name (), GetUsedModule (*details).name ());
1896
+ } else {
1897
+ SayAlreadyDeclared (name, prev.name ());
1898
+ }
1899
+ context ().SetError (prev);
1890
1900
}
1891
- context ().SetError (prev);
1892
1901
}
1893
1902
void ScopeHandler::SayAlreadyDeclared (
1894
1903
const SourceName &name1, const SourceName &name2) {
@@ -2194,6 +2203,44 @@ const DeclTypeSpec &ScopeHandler::MakeLogicalType(
2194
2203
}
2195
2204
}
2196
2205
2206
+ void ScopeHandler::NotePossibleBadForwardRef (const parser::Name &name) {
2207
+ if (inSpecificationPart_ && name.symbol ) {
2208
+ auto kind{currScope ().kind ()};
2209
+ if ((kind == Scope::Kind::Subprogram && !currScope ().IsStmtFunction ()) ||
2210
+ kind == Scope::Kind::Block) {
2211
+ bool isHostAssociated{&name.symbol ->owner () == &currScope ()
2212
+ ? name.symbol ->has <HostAssocDetails>()
2213
+ : name.symbol ->owner ().Contains (currScope ())};
2214
+ if (isHostAssociated) {
2215
+ specPartForwardRefs_.insert (name.source );
2216
+ }
2217
+ }
2218
+ }
2219
+ }
2220
+
2221
+ std::optional<SourceName> ScopeHandler::HadForwardRef (
2222
+ const Symbol &symbol) const {
2223
+ auto iter{specPartForwardRefs_.find (symbol.name ())};
2224
+ if (iter != specPartForwardRefs_.end ()) {
2225
+ return *iter;
2226
+ }
2227
+ return std::nullopt;
2228
+ }
2229
+
2230
+ bool ScopeHandler::CheckPossibleBadForwardRef (const Symbol &symbol) {
2231
+ if (!context ().HasError (symbol)) {
2232
+ if (auto fwdRef{HadForwardRef (symbol)}) {
2233
+ Say (*fwdRef,
2234
+ " Forward reference to '%s' is not allowed in the same specification part" _err_en_US,
2235
+ *fwdRef)
2236
+ .Attach (symbol.name (), " Later declaration of '%s'" _en_US, *fwdRef);
2237
+ context ().SetError (symbol);
2238
+ return true ;
2239
+ }
2240
+ }
2241
+ return false ;
2242
+ }
2243
+
2197
2244
void ScopeHandler::MakeExternal (Symbol &symbol) {
2198
2245
if (!symbol.attrs ().test (Attr::EXTERNAL)) {
2199
2246
symbol.attrs ().set (Attr::EXTERNAL);
@@ -4686,6 +4733,8 @@ void DeclarationVisitor::SetType(
4686
4733
symbol.SetType (type);
4687
4734
} else if (symbol.has <UseDetails>()) {
4688
4735
// error recovery case, redeclaration of use-associated name
4736
+ } else if (HadForwardRef (symbol)) {
4737
+ // error recovery after use of host-associated name
4689
4738
} else if (!symbol.test (Symbol::Flag::Implicit)) {
4690
4739
SayWithDecl (
4691
4740
name, symbol, " The type of '%s' has already been declared" _err_en_US);
@@ -5466,12 +5515,14 @@ const parser::Name *DeclarationVisitor::ResolveDataRef(
5466
5515
const parser::Name *DeclarationVisitor::ResolveName (const parser::Name &name) {
5467
5516
FindSymbol (name);
5468
5517
if (CheckForHostAssociatedImplicit (name)) {
5518
+ NotePossibleBadForwardRef (name);
5469
5519
return &name;
5470
5520
}
5471
5521
if (Symbol * symbol{name.symbol }) {
5472
5522
if (CheckUseError (name)) {
5473
5523
return nullptr ; // reported an error
5474
5524
}
5525
+ NotePossibleBadForwardRef (name);
5475
5526
symbol->set (Symbol::Flag::ImplicitOrError, false );
5476
5527
if (IsUplevelReference (*symbol)) {
5477
5528
MakeHostAssocSymbol (name, *symbol);
@@ -5496,6 +5547,7 @@ const parser::Name *DeclarationVisitor::ResolveName(const parser::Name &name) {
5496
5547
}
5497
5548
ConvertToObjectEntity (*symbol);
5498
5549
ApplyImplicitRules (*symbol);
5550
+ NotePossibleBadForwardRef (name);
5499
5551
return &name;
5500
5552
}
5501
5553
@@ -5518,7 +5570,8 @@ bool DeclarationVisitor::CheckForHostAssociatedImplicit(
5518
5570
Scope *host{GetHostProcedure ()};
5519
5571
if (!host || isImplicitNoneType (*host)) {
5520
5572
return false ;
5521
- } else if (!name.symbol ) {
5573
+ }
5574
+ if (!name.symbol ) {
5522
5575
hostSymbol = &MakeSymbol (*host, name.source , Attrs{});
5523
5576
ConvertToObjectEntity (*hostSymbol);
5524
5577
ApplyImplicitRules (*hostSymbol);
@@ -5989,12 +6042,15 @@ static bool NeedsExplicitType(const Symbol &symbol) {
5989
6042
bool ResolveNamesVisitor::Pre (const parser::SpecificationPart &x) {
5990
6043
const auto &[accDecls, ompDecls, compilerDirectives, useStmts, importStmts,
5991
6044
implicitPart, decls] = x.t ;
6045
+ auto flagRestorer{common::ScopedSet (inSpecificationPart_, true )};
5992
6046
Walk (accDecls);
5993
6047
Walk (ompDecls);
5994
6048
Walk (compilerDirectives);
5995
6049
Walk (useStmts);
5996
6050
Walk (importStmts);
5997
6051
Walk (implicitPart);
6052
+ auto setRestorer{
6053
+ common::ScopedSet (specPartForwardRefs_, std::set<SourceName>{})};
5998
6054
for (const auto &decl : decls) {
5999
6055
if (const auto *spec{
6000
6056
std::get_if<parser::SpecificationConstruct>(&decl.u )}) {
@@ -6096,6 +6152,9 @@ void ResolveNamesVisitor::FinishSpecificationPart(
6096
6152
symbol.set (
6097
6153
symbol.GetType () ? Symbol::Flag::Function : Symbol::Flag::Subroutine);
6098
6154
}
6155
+ if (!symbol.has <HostAssocDetails>()) {
6156
+ CheckPossibleBadForwardRef (symbol);
6157
+ }
6099
6158
}
6100
6159
currScope ().InstantiateDerivedTypes (context ());
6101
6160
for (const auto &decl : decls) {
0 commit comments