Skip to content

Commit e18fa6e

Browse files
authored
[flang] Fix compile-time infinite loop (#66246)
When a COMMON block object has a derived type that is part of a set of mutually-dependent types with other members, the compiler loops. Fixes #65572.
1 parent 135e521 commit e18fa6e

File tree

2 files changed

+25
-11
lines changed

2 files changed

+25
-11
lines changed

flang/lib/Semantics/resolve-names.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,7 +1131,8 @@ class DeclarationVisitor : public ArraySpecVisitor,
11311131
bool OkToAddComponent(const parser::Name &, const Symbol * = nullptr);
11321132
ParamValue GetParamValue(
11331133
const parser::TypeParamValue &, common::TypeParamAttr attr);
1134-
void CheckCommonBlockDerivedType(const SourceName &, const Symbol &);
1134+
void CheckCommonBlockDerivedType(
1135+
const SourceName &, const Symbol &, UnorderedSymbolSet &);
11351136
Attrs HandleSaveName(const SourceName &, Attrs);
11361137
void AddSaveName(std::set<SourceName> &, const SourceName &);
11371138
bool HandleUnrestrictedSpecificIntrinsicFunction(const parser::Name &);
@@ -6096,7 +6097,8 @@ void DeclarationVisitor::CheckCommonBlocks() {
60966097
"Derived type '%s' in COMMON block must have the BIND or"
60976098
" SEQUENCE attribute"_err_en_US);
60986099
}
6099-
CheckCommonBlockDerivedType(name, typeSymbol);
6100+
UnorderedSymbolSet typeSet;
6101+
CheckCommonBlockDerivedType(name, typeSymbol, typeSet);
61006102
}
61016103
}
61026104
}
@@ -6120,8 +6122,12 @@ bool DeclarationVisitor::NameIsKnownOrIntrinsic(const parser::Name &name) {
61206122
}
61216123

61226124
// Check if this derived type can be in a COMMON block.
6123-
void DeclarationVisitor::CheckCommonBlockDerivedType(
6124-
const SourceName &name, const Symbol &typeSymbol) {
6125+
void DeclarationVisitor::CheckCommonBlockDerivedType(const SourceName &name,
6126+
const Symbol &typeSymbol, UnorderedSymbolSet &typeSet) {
6127+
if (auto iter{typeSet.find(SymbolRef{typeSymbol})}; iter != typeSet.end()) {
6128+
return;
6129+
}
6130+
typeSet.emplace(typeSymbol);
61256131
if (const auto *scope{typeSymbol.scope()}) {
61266132
for (const auto &pair : *scope) {
61276133
const Symbol &component{*pair.second};
@@ -6144,13 +6150,7 @@ void DeclarationVisitor::CheckCommonBlockDerivedType(
61446150
if (const auto *type{details->type()}) {
61456151
if (const auto *derived{type->AsDerived()}) {
61466152
const Symbol &derivedTypeSymbol{derived->typeSymbol()};
6147-
// Don't call this member function recursively if the derived type
6148-
// symbol is the same symbol that is already being processed.
6149-
// This can happen when a component is a pointer of the same type
6150-
// as its parent component, for instance.
6151-
if (derivedTypeSymbol != typeSymbol) {
6152-
CheckCommonBlockDerivedType(name, derivedTypeSymbol);
6153-
}
6153+
CheckCommonBlockDerivedType(name, derivedTypeSymbol, typeSet);
61546154
}
61556155
}
61566156
}

flang/test/Semantics/equivalence01.f90

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,3 +230,17 @@ real function f17b()
230230
equivalence (dupName, y)
231231
end function f17b
232232
end module m17
233+
234+
module m18
235+
! Regression test: don't loop when checking mutually-referencing types
236+
type t1
237+
sequence
238+
type (t2), pointer :: p
239+
end type
240+
type t2
241+
sequence
242+
type (t1), pointer :: p
243+
end type
244+
type(t1) x
245+
common x
246+
end

0 commit comments

Comments
 (0)