Revert "[flang] Detect circularly defined interfaces of procedures"

This reverts commit 93c5e6bb49.

This patch updates resolve102.f90 which is now failing in 6 out 8 of our
public buildbots:
  * http://lab.llvm.org:8011/#/builders/21/builds/9625
  * http://lab.llvm.org:8011/#/builders/134/builds/2395
  * http://lab.llvm.org:8011/#/builders/79/builds/6298
  * http://lab.llvm.org:8011/#/builders/66/builds/2084
  * http://lab.llvm.org:8011/#/builders/135/builds/2485
  * http://lab.llvm.org:8011/#/builders/32/builds/3551

Please see the following revisions for more context:
  * https://reviews.llvm.org/D97201
  * https://reviews.llvm.org/D97749
This commit is contained in:
Andrzej Warzynski 2021-03-02 14:36:29 +00:00
parent 7556abf821
commit 1253009eb2
5 changed files with 23 additions and 81 deletions

View File

@ -199,7 +199,7 @@ private:
IndexVarKind kind;
};
std::map<SymbolRef, const IndexVarInfo> activeIndexVars_;
SymbolSet errorSymbols_;
std::set<SymbolRef> errorSymbols_;
std::set<std::string> tempNames_;
};

View File

@ -15,10 +15,9 @@
#include "flang/Common/reference.h"
#include "llvm/ADT/DenseMapInfo.h"
#include <array>
#include <functional>
#include <list>
#include <optional>
#include <unordered_set>
#include <set>
#include <vector>
namespace llvm {
@ -596,7 +595,7 @@ public:
bool operator==(const Symbol &that) const { return this == &that; }
bool operator!=(const Symbol &that) const { return !(*this == that); }
bool operator<(const Symbol &that) const {
// For maps of symbols: collate them by source location
// For sets of symbols: collate them by source location
return name_.begin() < that.name_.begin();
}
@ -766,13 +765,7 @@ inline bool operator<(SymbolRef x, SymbolRef y) { return *x < *y; }
inline bool operator<(MutableSymbolRef x, MutableSymbolRef y) {
return *x < *y;
}
struct SymbolHash {
std::size_t operator()(SymbolRef symRef) const {
std::hash<std::string> hasher;
return hasher(symRef->name().ToString());
}
};
using SymbolSet = std::unordered_set<SymbolRef, SymbolHash>;
using SymbolSet = std::set<SymbolRef>;
} // namespace Fortran::semantics

View File

@ -369,7 +369,7 @@ static std::optional<Procedure> CharacterizeProcedure(
std::string procsList{GetSeenProcs(seenProcs)};
context.messages().Say(symbol.name(),
"Procedure '%s' is recursively defined. Procedures in the cycle:"
" %s"_err_en_US,
" '%s'"_err_en_US,
symbol.name(), procsList);
return std::nullopt;
}

View File

@ -1003,7 +1003,6 @@ private:
context().SetError(symbol);
return symbol;
}
bool HasCycle(const Symbol &, const ProcInterface &);
};
// Resolve construct entities and statement entities.
@ -2133,7 +2132,7 @@ static bool NeedsType(const Symbol &symbol) {
void ScopeHandler::ApplyImplicitRules(
Symbol &symbol, bool allowForwardReference) {
if (context().HasError(symbol) || !NeedsType(symbol)) {
if (!NeedsType(symbol)) {
return;
}
if (const DeclTypeSpec * type{GetImplicitType(symbol)}) {
@ -3642,35 +3641,6 @@ Symbol &DeclarationVisitor::DeclareUnknownEntity(
}
}
bool DeclarationVisitor::HasCycle(
const Symbol &procSymbol, const ProcInterface &interface) {
SymbolSet procsInCycle;
procsInCycle.insert(procSymbol);
const ProcInterface *thisInterface{&interface};
bool haveInterface{true};
while (haveInterface) {
haveInterface = false;
if (const Symbol * interfaceSymbol{thisInterface->symbol()}) {
if (procsInCycle.count(*interfaceSymbol) > 0) {
for (const auto procInCycle : procsInCycle) {
Say(procInCycle->name(),
"The interface for procedure '%s' is recursively "
"defined"_err_en_US,
procInCycle->name());
context().SetError(*procInCycle);
}
return true;
} else if (const auto *procDetails{
interfaceSymbol->detailsIf<ProcEntityDetails>()}) {
haveInterface = true;
thisInterface = &procDetails->interface();
procsInCycle.insert(*interfaceSymbol);
}
}
}
return false;
}
Symbol &DeclarationVisitor::DeclareProcEntity(
const parser::Name &name, Attrs attrs, const ProcInterface &interface) {
Symbol &symbol{DeclareEntity<ProcEntityDetails>(name, attrs)};
@ -3680,20 +3650,20 @@ Symbol &DeclarationVisitor::DeclareProcEntity(
"The interface for procedure '%s' has already been "
"declared"_err_en_US);
context().SetError(symbol);
} else if (HasCycle(symbol, interface)) {
return symbol;
} else if (interface.type()) {
symbol.set(Symbol::Flag::Function);
} else if (interface.symbol()) {
if (interface.symbol()->test(Symbol::Flag::Function)) {
} else {
if (interface.type()) {
symbol.set(Symbol::Flag::Function);
} else if (interface.symbol()->test(Symbol::Flag::Subroutine)) {
symbol.set(Symbol::Flag::Subroutine);
} else if (interface.symbol()) {
if (interface.symbol()->test(Symbol::Flag::Function)) {
symbol.set(Symbol::Flag::Function);
} else if (interface.symbol()->test(Symbol::Flag::Subroutine)) {
symbol.set(Symbol::Flag::Subroutine);
}
}
details->set_interface(interface);
SetBindNameOn(symbol);
SetPassNameOn(symbol);
}
details->set_interface(interface);
SetBindNameOn(symbol);
SetPassNameOn(symbol);
}
return symbol;
}
@ -5035,7 +5005,7 @@ Symbol *DeclarationVisitor::NoteInterfaceName(const parser::Name &name) {
void DeclarationVisitor::CheckExplicitInterface(const parser::Name &name) {
if (const Symbol * symbol{name.symbol}) {
if (!context().HasError(*symbol) && !symbol->HasExplicitInterface()) {
if (!symbol->HasExplicitInterface()) {
Say(name,
"'%s' must be an abstract interface or a procedure with "
"an explicit interface"_err_en_US,

View File

@ -1,7 +1,7 @@
! RUN: %S/test_errors.sh %s %t %f18
! Tests for circularly defined procedures
!ERROR: Procedure 'sub' is recursively defined. Procedures in the cycle: 'p2', 'sub'
!ERROR: Procedure 'sub' is recursively defined. Procedures in the cycle: ''sub', 'p2''
subroutine sub(p2)
PROCEDURE(sub) :: p2
@ -9,7 +9,7 @@ subroutine sub(p2)
end subroutine
subroutine circular
!ERROR: Procedure 'p' is recursively defined. Procedures in the cycle: 'p2', 'p', 'sub'
!ERROR: Procedure 'p' is recursively defined. Procedures in the cycle: ''p', 'sub', 'p2''
procedure(sub) :: p
call p(sub)
@ -21,7 +21,7 @@ subroutine circular
end subroutine circular
program iface
!ERROR: Procedure 'p' is recursively defined. Procedures in the cycle: 'p2', 'p', 'sub'
!ERROR: Procedure 'p' is recursively defined. Procedures in the cycle: ''p', 'sub', 'p2''
procedure(sub) :: p
interface
subroutine sub(p2)
@ -38,7 +38,7 @@ Program mutual
Call p(sub)
contains
!ERROR: Procedure 'sub1' is recursively defined. Procedures in the cycle: 'p', 'arg', 'sub1'
!ERROR: Procedure 'sub1' is recursively defined. Procedures in the cycle: ''p', 'sub1', 'arg''
Subroutine sub1(arg)
procedure(sub1) :: arg
End Subroutine
@ -54,7 +54,7 @@ Program mutual1
Call p(sub)
contains
!ERROR: Procedure 'sub1' is recursively defined. Procedures in the cycle: 'p2', 'sub', 'p', 'arg', 'sub1'
!ERROR: Procedure 'sub1' is recursively defined. Procedures in the cycle: ''p', 'sub1', 'arg', 'sub', 'p2''
Subroutine sub1(arg)
procedure(sub) :: arg
End Subroutine
@ -63,24 +63,3 @@ Program mutual1
Procedure(sub1) :: p2
End Subroutine
End Program
program twoCycle
!ERROR: The interface for procedure 'p1' is recursively defined
!ERROR: The interface for procedure 'p2' is recursively defined
procedure(p1) p2
procedure(p2) p1
call p1
call p2
end program
program threeCycle
!ERROR: The interface for procedure 'p1' is recursively defined
!ERROR: The interface for procedure 'p2' is recursively defined
procedure(p1) p2
!ERROR: The interface for procedure 'p3' is recursively defined
procedure(p2) p3
procedure(p3) p1
call p1
call p2
call p3
end program