Skip to content

Commit 882fa24

Browse files
committed
[flang] Better error messages & more cases caught for bad forward refs
Subclause 10.1.12 in F'2018 prohibits forward references from a specification expression to an object declared later in the same specification part. Catch this error better and emit specific error messages about the violation. Differential revision: https://reviews.llvm.org/D90492
1 parent 86cd233 commit 882fa24

File tree

2 files changed

+163
-10
lines changed

2 files changed

+163
-10
lines changed

flang/lib/Semantics/resolve-names.cpp

Lines changed: 69 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,9 @@ class ScopeHandler : public ImplicitRulesVisitor {
578578
symbol->attrs() |= attrs;
579579
return *symbol;
580580
} else {
581-
SayAlreadyDeclared(name, *symbol);
581+
if (!CheckPossibleBadForwardRef(*symbol)) {
582+
SayAlreadyDeclared(name, *symbol);
583+
}
582584
// replace the old symbol with a new one with correct details
583585
EraseSymbol(*symbol);
584586
auto &result{MakeSymbol(name, attrs, std::move(details))};
@@ -600,8 +602,13 @@ class ScopeHandler : public ImplicitRulesVisitor {
600602
TypeCategory, const std::optional<parser::KindSelector> &);
601603
const DeclTypeSpec &MakeLogicalType(
602604
const std::optional<parser::KindSelector> &);
605+
void NotePossibleBadForwardRef(const parser::Name &);
606+
std::optional<SourceName> HadForwardRef(const Symbol &) const;
607+
bool CheckPossibleBadForwardRef(const Symbol &);
603608

604609
bool inExecutionPart_{false};
610+
bool inSpecificationPart_{false};
611+
std::set<SourceName> specPartForwardRefs_;
605612

606613
private:
607614
Scope *currScope_{nullptr};
@@ -982,7 +989,7 @@ class DeclarationVisitor : public ArraySpecVisitor,
982989
SayWithDecl(
983990
name, symbol, "'%s' is already declared as an object"_err_en_US);
984991
}
985-
} else {
992+
} else if (!CheckPossibleBadForwardRef(symbol)) {
986993
SayAlreadyDeclared(name, symbol);
987994
}
988995
context().SetError(symbol);
@@ -1880,15 +1887,17 @@ void ScopeHandler::SayAlreadyDeclared(const parser::Name &name, Symbol &prev) {
18801887
void ScopeHandler::SayAlreadyDeclared(const SourceName &name, Symbol &prev) {
18811888
if (context().HasError(prev)) {
18821889
// 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());
18881890
} 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);
18901900
}
1891-
context().SetError(prev);
18921901
}
18931902
void ScopeHandler::SayAlreadyDeclared(
18941903
const SourceName &name1, const SourceName &name2) {
@@ -2194,6 +2203,44 @@ const DeclTypeSpec &ScopeHandler::MakeLogicalType(
21942203
}
21952204
}
21962205

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+
21972244
void ScopeHandler::MakeExternal(Symbol &symbol) {
21982245
if (!symbol.attrs().test(Attr::EXTERNAL)) {
21992246
symbol.attrs().set(Attr::EXTERNAL);
@@ -4686,6 +4733,8 @@ void DeclarationVisitor::SetType(
46864733
symbol.SetType(type);
46874734
} else if (symbol.has<UseDetails>()) {
46884735
// error recovery case, redeclaration of use-associated name
4736+
} else if (HadForwardRef(symbol)) {
4737+
// error recovery after use of host-associated name
46894738
} else if (!symbol.test(Symbol::Flag::Implicit)) {
46904739
SayWithDecl(
46914740
name, symbol, "The type of '%s' has already been declared"_err_en_US);
@@ -5466,12 +5515,14 @@ const parser::Name *DeclarationVisitor::ResolveDataRef(
54665515
const parser::Name *DeclarationVisitor::ResolveName(const parser::Name &name) {
54675516
FindSymbol(name);
54685517
if (CheckForHostAssociatedImplicit(name)) {
5518+
NotePossibleBadForwardRef(name);
54695519
return &name;
54705520
}
54715521
if (Symbol * symbol{name.symbol}) {
54725522
if (CheckUseError(name)) {
54735523
return nullptr; // reported an error
54745524
}
5525+
NotePossibleBadForwardRef(name);
54755526
symbol->set(Symbol::Flag::ImplicitOrError, false);
54765527
if (IsUplevelReference(*symbol)) {
54775528
MakeHostAssocSymbol(name, *symbol);
@@ -5496,6 +5547,7 @@ const parser::Name *DeclarationVisitor::ResolveName(const parser::Name &name) {
54965547
}
54975548
ConvertToObjectEntity(*symbol);
54985549
ApplyImplicitRules(*symbol);
5550+
NotePossibleBadForwardRef(name);
54995551
return &name;
55005552
}
55015553

@@ -5518,7 +5570,8 @@ bool DeclarationVisitor::CheckForHostAssociatedImplicit(
55185570
Scope *host{GetHostProcedure()};
55195571
if (!host || isImplicitNoneType(*host)) {
55205572
return false;
5521-
} else if (!name.symbol) {
5573+
}
5574+
if (!name.symbol) {
55225575
hostSymbol = &MakeSymbol(*host, name.source, Attrs{});
55235576
ConvertToObjectEntity(*hostSymbol);
55245577
ApplyImplicitRules(*hostSymbol);
@@ -5989,12 +6042,15 @@ static bool NeedsExplicitType(const Symbol &symbol) {
59896042
bool ResolveNamesVisitor::Pre(const parser::SpecificationPart &x) {
59906043
const auto &[accDecls, ompDecls, compilerDirectives, useStmts, importStmts,
59916044
implicitPart, decls] = x.t;
6045+
auto flagRestorer{common::ScopedSet(inSpecificationPart_, true)};
59926046
Walk(accDecls);
59936047
Walk(ompDecls);
59946048
Walk(compilerDirectives);
59956049
Walk(useStmts);
59966050
Walk(importStmts);
59976051
Walk(implicitPart);
6052+
auto setRestorer{
6053+
common::ScopedSet(specPartForwardRefs_, std::set<SourceName>{})};
59986054
for (const auto &decl : decls) {
59996055
if (const auto *spec{
60006056
std::get_if<parser::SpecificationConstruct>(&decl.u)}) {
@@ -6096,6 +6152,9 @@ void ResolveNamesVisitor::FinishSpecificationPart(
60966152
symbol.set(
60976153
symbol.GetType() ? Symbol::Flag::Function : Symbol::Flag::Subroutine);
60986154
}
6155+
if (!symbol.has<HostAssocDetails>()) {
6156+
CheckPossibleBadForwardRef(symbol);
6157+
}
60996158
}
61006159
currScope().InstantiateDerivedTypes(context());
61016160
for (const auto &decl : decls) {

flang/test/Semantics/resolve97.f90

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
! RUN: %S/test_errors.sh %s %t %f18
2+
3+
! Check errors from illegal (10.1.12 para 2) forward references
4+
! in specification expressions to entities declared later in the
5+
! same specification part.
6+
7+
module m1
8+
integer :: m1j1, m1j2, m1j3, m1j4
9+
contains
10+
subroutine s1
11+
!ERROR: Forward reference to 'm1j1' is not allowed in the same specification part
12+
integer(kind=kind(m1j1)) :: t_s1m1j1
13+
integer(kind=kind(m1s1j1)) :: t_s1j1 ! implicitly typed in s1
14+
integer :: m1j1, m1s1j1, m1s1j2, m1s1j4
15+
block
16+
!ERROR: Forward reference to 'm1j2' is not allowed in the same specification part
17+
integer(kind=kind(m1j2)) :: t_s1bm1j2
18+
!ERROR: Forward reference to 'm1s1j2' is not allowed in the same specification part
19+
integer(kind=kind(m1s1j2)) :: t_s1bm1s1j2
20+
!ERROR: Forward reference to 'm1s1j3' is not allowed in the same specification part
21+
integer(kind=kind(m1s1j3)) :: t_m1s1j3 ! m1s1j3 implicitly typed in s1
22+
integer :: m1j2, m1s1j2, m1s1j3
23+
end block
24+
contains
25+
subroutine s2
26+
!ERROR: Forward reference to 'm1j3' is not allowed in the same specification part
27+
integer(kind=kind(m1j3)) :: t_m1j3
28+
!ERROR: Forward reference to 'm1s1j3' is not allowed in the same specification part
29+
integer(kind=kind(m1s1j3)) :: t_m1s1j3
30+
integer :: m1j3, m1s1j3, m1s2j1
31+
block
32+
!ERROR: Forward reference to 'm1j4' is not allowed in the same specification part
33+
integer(kind=kind(m1j4)) :: t_m1j4
34+
!ERROR: Forward reference to 'm1s1j4' is not allowed in the same specification part
35+
integer(kind=kind(m1s1j4)) :: t_m1s1j4
36+
!ERROR: Forward reference to 'm1s2j1' is not allowed in the same specification part
37+
integer(kind=kind(m1s2j1)) :: t_m1s2j1
38+
!ERROR: Forward reference to 'm1s2j2' is not allowed in the same specification part
39+
integer(kind=kind(m1s2j2)) :: t_m1s2j2 ! m1s2j2 implicitly typed in s2
40+
integer :: m1j4, m1s1j4, m1s2j1, m1s2j2
41+
end block
42+
end subroutine
43+
end subroutine
44+
end module
45+
46+
module m2
47+
implicit none
48+
integer :: m2j1, m2j2, m2j3, m2j4
49+
contains
50+
subroutine s1
51+
!ERROR: Forward reference to 'm2j1' is not allowed in the same specification part
52+
integer(kind=kind(m2j1)) :: t_s1m2j1
53+
!ERROR: No explicit type declared for 'm2s1j1'
54+
integer(kind=kind(m2s1j1)) :: t_s1j1
55+
integer :: m2j1, m2s1j1, m2s1j2, m2s1j4
56+
block
57+
!ERROR: Forward reference to 'm2j2' is not allowed in the same specification part
58+
integer(kind=kind(m2j2)) :: t_s1bm2j2
59+
!ERROR: Forward reference to 'm2s1j2' is not allowed in the same specification part
60+
integer(kind=kind(m2s1j2)) :: t_s1bm2s1j2
61+
!ERROR: No explicit type declared for 'm2s1j3'
62+
integer(kind=kind(m2s1j3)) :: t_m2s1j3
63+
integer :: m2j2, m2s1j2, m2s1j3
64+
end block
65+
contains
66+
subroutine s2
67+
!ERROR: Forward reference to 'm2j3' is not allowed in the same specification part
68+
integer(kind=kind(m2j3)) :: t_m2j3
69+
!ERROR: No explicit type declared for 'm2s1j3'
70+
integer(kind=kind(m2s1j3)) :: t_m2s1j3
71+
integer :: m2j3, m2s1j3, m2s2j1
72+
block
73+
!ERROR: Forward reference to 'm2j4' is not allowed in the same specification part
74+
integer(kind=kind(m2j4)) :: t_m2j4
75+
!ERROR: Forward reference to 'm2s1j4' is not allowed in the same specification part
76+
integer(kind=kind(m2s1j4)) :: t_m2s1j4
77+
!ERROR: Forward reference to 'm2s2j1' is not allowed in the same specification part
78+
integer(kind=kind(m2s2j1)) :: t_m2s2j1
79+
!ERROR: No explicit type declared for 'm2s2j2'
80+
integer(kind=kind(m2s2j2)) :: t_m2s2j2
81+
integer :: m2j4, m2s1j4, m2s2j1, m2s2j2
82+
end block
83+
end subroutine
84+
end subroutine
85+
end module
86+
87+
! Case that elicited bad errors
88+
SUBROUTINE KEEL
89+
INTEGER NODES
90+
CONTAINS
91+
SUBROUTINE SGEOM
92+
REAL :: RADIUS(nodes)
93+
END SUBROUTINE
94+
END SUBROUTINE KEEL

0 commit comments

Comments
 (0)