Skip to content

Commit 00e6513

Browse files
committed
Revert "[flang] Detect circularly defined interfaces of procedures"
This reverts commit 07de084. The original patch has caused 6 out 8 of Flang's public buildbots to fail. As I'm not sure what the fix should be, I'm reverting this for now. Please see https://reviews.llvm.org/D97201 for more context and discussion.
1 parent 6718fda commit 00e6513

File tree

4 files changed

+27
-84
lines changed

4 files changed

+27
-84
lines changed

flang/include/flang/Semantics/symbol.h

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#include <array>
1818
#include <list>
1919
#include <optional>
20-
#include <unordered_set>
20+
#include <set>
2121
#include <vector>
2222

2323
namespace llvm {
@@ -38,12 +38,6 @@ using SymbolRef = common::Reference<const Symbol>;
3838
using SymbolVector = std::vector<SymbolRef>;
3939
using MutableSymbolRef = common::Reference<Symbol>;
4040
using MutableSymbolVector = std::vector<MutableSymbolRef>;
41-
struct SymbolHash {
42-
std::size_t operator()(SymbolRef symRef) const {
43-
return (std::size_t)(&symRef.get());
44-
}
45-
};
46-
using SymbolSet = std::unordered_set<SymbolRef, SymbolHash>;
4741

4842
// A module or submodule.
4943
class ModuleDetails {
@@ -600,10 +594,9 @@ class Symbol {
600594

601595
bool operator==(const Symbol &that) const { return this == &that; }
602596
bool operator!=(const Symbol &that) const { return !(*this == that); }
603-
// For maps using symbols as keys and sorting symbols. Collate them by their
604-
// position in the cooked character stream
605597
bool operator<(const Symbol &that) const {
606-
return sortName_ < that.sortName_;
598+
// For sets of symbols: collate them by source location
599+
return name_.begin() < that.name_.begin();
607600
}
608601

609602
int Rank() const {
@@ -660,7 +653,6 @@ class Symbol {
660653
private:
661654
const Scope *owner_;
662655
SourceName name_;
663-
const char *sortName_; // used in the "<" operator for sorting symbols
664656
Attrs attrs_;
665657
Flags flags_;
666658
Scope *scope_{nullptr};
@@ -695,7 +687,6 @@ template <std::size_t BLOCK_SIZE> class Symbols {
695687
Symbol &symbol = Get();
696688
symbol.owner_ = &owner;
697689
symbol.name_ = name;
698-
symbol.sortName_ = name.begin();
699690
symbol.attrs_ = attrs;
700691
symbol.details_ = std::move(details);
701692
return symbol;
@@ -774,6 +765,7 @@ inline bool operator<(SymbolRef x, SymbolRef y) { return *x < *y; }
774765
inline bool operator<(MutableSymbolRef x, MutableSymbolRef y) {
775766
return *x < *y;
776767
}
768+
using SymbolSet = std::set<SymbolRef>;
777769

778770
} // namespace Fortran::semantics
779771

flang/lib/Evaluate/characteristics.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ static std::optional<Procedure> CharacterizeProcedure(
369369
std::string procsList{GetSeenProcs(seenProcs)};
370370
context.messages().Say(symbol.name(),
371371
"Procedure '%s' is recursively defined. Procedures in the cycle:"
372-
" %s"_err_en_US,
372+
" '%s'"_err_en_US,
373373
symbol.name(), procsList);
374374
return std::nullopt;
375375
}

flang/lib/Semantics/resolve-names.cpp

Lines changed: 17 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,7 +1003,6 @@ class DeclarationVisitor : public ArraySpecVisitor,
10031003
context().SetError(symbol);
10041004
return symbol;
10051005
}
1006-
bool HasCycle(const Symbol &, const ProcInterface &);
10071006
};
10081007

10091008
// Resolve construct entities and statement entities.
@@ -2133,7 +2132,7 @@ static bool NeedsType(const Symbol &symbol) {
21332132

21342133
void ScopeHandler::ApplyImplicitRules(
21352134
Symbol &symbol, bool allowForwardReference) {
2136-
if (context().HasError(symbol) || !NeedsType(symbol)) {
2135+
if (!NeedsType(symbol)) {
21372136
return;
21382137
}
21392138
if (const DeclTypeSpec * type{GetImplicitType(symbol)}) {
@@ -2157,8 +2156,10 @@ void ScopeHandler::ApplyImplicitRules(
21572156
if (allowForwardReference && ImplicitlyTypeForwardRef(symbol)) {
21582157
return;
21592158
}
2160-
Say(symbol.name(), "No explicit type declared for '%s'"_err_en_US);
2161-
context().SetError(symbol);
2159+
if (!context().HasError(symbol)) {
2160+
Say(symbol.name(), "No explicit type declared for '%s'"_err_en_US);
2161+
context().SetError(symbol);
2162+
}
21622163
}
21632164

21642165
// Extension: Allow forward references to scalar integer dummy arguments
@@ -3640,35 +3641,6 @@ Symbol &DeclarationVisitor::DeclareUnknownEntity(
36403641
}
36413642
}
36423643

3643-
bool DeclarationVisitor::HasCycle(
3644-
const Symbol &procSymbol, const ProcInterface &interface) {
3645-
SymbolSet procsInCycle;
3646-
procsInCycle.insert(procSymbol);
3647-
const ProcInterface *thisInterface{&interface};
3648-
bool haveInterface{true};
3649-
while (haveInterface) {
3650-
haveInterface = false;
3651-
if (const Symbol * interfaceSymbol{thisInterface->symbol()}) {
3652-
if (procsInCycle.count(*interfaceSymbol) > 0) {
3653-
for (const auto procInCycle : procsInCycle) {
3654-
Say(procInCycle->name(),
3655-
"The interface for procedure '%s' is recursively "
3656-
"defined"_err_en_US,
3657-
procInCycle->name());
3658-
context().SetError(*procInCycle);
3659-
}
3660-
return true;
3661-
} else if (const auto *procDetails{
3662-
interfaceSymbol->detailsIf<ProcEntityDetails>()}) {
3663-
haveInterface = true;
3664-
thisInterface = &procDetails->interface();
3665-
procsInCycle.insert(*interfaceSymbol);
3666-
}
3667-
}
3668-
}
3669-
return false;
3670-
}
3671-
36723644
Symbol &DeclarationVisitor::DeclareProcEntity(
36733645
const parser::Name &name, Attrs attrs, const ProcInterface &interface) {
36743646
Symbol &symbol{DeclareEntity<ProcEntityDetails>(name, attrs)};
@@ -3678,20 +3650,20 @@ Symbol &DeclarationVisitor::DeclareProcEntity(
36783650
"The interface for procedure '%s' has already been "
36793651
"declared"_err_en_US);
36803652
context().SetError(symbol);
3681-
} else if (HasCycle(symbol, interface)) {
3682-
return symbol;
3683-
} else if (interface.type()) {
3684-
symbol.set(Symbol::Flag::Function);
3685-
} else if (interface.symbol()) {
3686-
if (interface.symbol()->test(Symbol::Flag::Function)) {
3653+
} else {
3654+
if (interface.type()) {
36873655
symbol.set(Symbol::Flag::Function);
3688-
} else if (interface.symbol()->test(Symbol::Flag::Subroutine)) {
3689-
symbol.set(Symbol::Flag::Subroutine);
3656+
} else if (interface.symbol()) {
3657+
if (interface.symbol()->test(Symbol::Flag::Function)) {
3658+
symbol.set(Symbol::Flag::Function);
3659+
} else if (interface.symbol()->test(Symbol::Flag::Subroutine)) {
3660+
symbol.set(Symbol::Flag::Subroutine);
3661+
}
36903662
}
3663+
details->set_interface(interface);
3664+
SetBindNameOn(symbol);
3665+
SetPassNameOn(symbol);
36913666
}
3692-
details->set_interface(interface);
3693-
SetBindNameOn(symbol);
3694-
SetPassNameOn(symbol);
36953667
}
36963668
return symbol;
36973669
}
@@ -5033,7 +5005,7 @@ Symbol *DeclarationVisitor::NoteInterfaceName(const parser::Name &name) {
50335005

50345006
void DeclarationVisitor::CheckExplicitInterface(const parser::Name &name) {
50355007
if (const Symbol * symbol{name.symbol}) {
5036-
if (!context().HasError(*symbol) && !symbol->HasExplicitInterface()) {
5008+
if (!symbol->HasExplicitInterface()) {
50375009
Say(name,
50385010
"'%s' must be an abstract interface or a procedure with "
50395011
"an explicit interface"_err_en_US,

flang/test/Semantics/resolve102.f90

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
! RUN: %S/test_errors.sh %s %t %f18
22

33
! Tests for circularly defined procedures
4-
!ERROR: Procedure 'sub' is recursively defined. Procedures in the cycle: 'p2', 'sub'
4+
!ERROR: Procedure 'sub' is recursively defined. Procedures in the cycle: ''sub', 'p2''
55
subroutine sub(p2)
66
PROCEDURE(sub) :: p2
77

88
call sub()
99
end subroutine
1010

1111
subroutine circular
12-
!ERROR: Procedure 'p' is recursively defined. Procedures in the cycle: 'p2', 'p', 'sub'
12+
!ERROR: Procedure 'p' is recursively defined. Procedures in the cycle: ''p', 'sub', 'p2''
1313
procedure(sub) :: p
1414

1515
call p(sub)
@@ -21,7 +21,7 @@ subroutine sub(p2)
2121
end subroutine circular
2222

2323
program iface
24-
!ERROR: Procedure 'p' is recursively defined. Procedures in the cycle: 'p2', 'p', 'sub'
24+
!ERROR: Procedure 'p' is recursively defined. Procedures in the cycle: ''p', 'sub', 'p2''
2525
procedure(sub) :: p
2626
interface
2727
subroutine sub(p2)
@@ -38,7 +38,7 @@ Program mutual
3838
Call p(sub)
3939

4040
contains
41-
!ERROR: Procedure 'sub1' is recursively defined. Procedures in the cycle: 'arg', 'p', 'sub1'
41+
!ERROR: Procedure 'sub1' is recursively defined. Procedures in the cycle: ''p', 'sub1', 'arg''
4242
Subroutine sub1(arg)
4343
procedure(sub1) :: arg
4444
End Subroutine
@@ -54,7 +54,7 @@ Program mutual1
5454
Call p(sub)
5555

5656
contains
57-
!ERROR: Procedure 'sub1' is recursively defined. Procedures in the cycle: 'p2', 'sub', 'arg', 'p', 'sub1'
57+
!ERROR: Procedure 'sub1' is recursively defined. Procedures in the cycle: ''p', 'sub1', 'arg', 'sub', 'p2''
5858
Subroutine sub1(arg)
5959
procedure(sub) :: arg
6060
End Subroutine
@@ -63,24 +63,3 @@ Subroutine sub(p2)
6363
Procedure(sub1) :: p2
6464
End Subroutine
6565
End Program
66-
67-
program twoCycle
68-
!ERROR: The interface for procedure 'p1' is recursively defined
69-
!ERROR: The interface for procedure 'p2' is recursively defined
70-
procedure(p1) p2
71-
procedure(p2) p1
72-
call p1
73-
call p2
74-
end program
75-
76-
program threeCycle
77-
!ERROR: The interface for procedure 'p1' is recursively defined
78-
!ERROR: The interface for procedure 'p2' is recursively defined
79-
procedure(p1) p2
80-
!ERROR: The interface for procedure 'p3' is recursively defined
81-
procedure(p2) p3
82-
procedure(p3) p1
83-
call p1
84-
call p2
85-
call p3
86-
end program

0 commit comments

Comments
 (0)