Skip to content

Commit

Permalink
[flang] Catch name conflict between generic TBP and inherited non-gen…
Browse files Browse the repository at this point in the history
…eric

A generic procedure binding in an extended derived type may not have the
same name as a symbol inherited from an ancestor type unless that inherited
symbol is also a generic TBP.  Since generic names can be things like
"ASSIGNMENT(=)", name resolution doesn't use OkToAddComponent() for
generic TBPs, which would have caught this error as it does for other
symbols in derived types, so it must be special-cased.

Differential Revision: https://reviews.llvm.org/D145109
  • Loading branch information
klausler committed Mar 2, 2023
1 parent 69e2665 commit 2216c4c
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 8 deletions.
18 changes: 10 additions & 8 deletions flang/lib/Semantics/resolve-names.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5226,7 +5226,7 @@ bool DeclarationVisitor::Pre(const parser::TypeBoundGenericStmt &x) {
const auto &accessSpec{std::get<std::optional<parser::AccessSpec>>(x.t)};
const auto &genericSpec{std::get<Indirection<parser::GenericSpec>>(x.t)};
const auto &bindingNames{std::get<std::list<parser::Name>>(x.t)};
auto info{GenericSpecInfo{genericSpec.value()}};
GenericSpecInfo info{genericSpec.value()};
SourceName symbolName{info.symbolName()};
bool isPrivate{accessSpec ? accessSpec->v == parser::AccessSpec::Kind::Private
: derivedTypeInfo_.privateBindings};
Expand All @@ -5236,17 +5236,19 @@ bool DeclarationVisitor::Pre(const parser::TypeBoundGenericStmt &x) {
genericSymbol = nullptr; // MakeTypeSymbol will report the error below
}
} else {
// look in parent types:
Symbol *inheritedSymbol{nullptr};
// look in ancestor types for a generic of the same name
for (const auto &name : GetAllNames(context(), symbolName)) {
inheritedSymbol = currScope().FindComponent(SourceName{name});
if (inheritedSymbol) {
if (Symbol * inherited{currScope().FindComponent(SourceName{name})}) {
if (inherited->has<GenericDetails>()) {
CheckAccessibility(symbolName, isPrivate, *inherited); // C771
} else {
Say(symbolName,
"Type bound generic procedure '%s' may not have the same name as a non-generic symbol inherited from an ancestor type"_err_en_US)
.Attach(inherited->name(), "Inherited symbol"_en_US);
}
break;
}
}
if (inheritedSymbol && inheritedSymbol->has<GenericDetails>()) {
CheckAccessibility(symbolName, isPrivate, *inheritedSymbol); // C771
}
}
if (genericSymbol) {
CheckAccessibility(symbolName, isPrivate, *genericSymbol); // C771
Expand Down
27 changes: 27 additions & 0 deletions flang/test/Semantics/resolve117.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
! RUN: %python %S/test_errors.py %s %flang_fc1
! Test name conflicts with type-bound generics
module m
type base1(k)
integer, kind :: k = 4
real x
contains
procedure, nopass :: tbp => sub
generic :: gen => tbp
end type
type, extends(base1) :: ext1
contains
procedure, nopass :: sub
!ERROR: Type parameter, component, or procedure binding 'base1' already defined in this type
generic :: base1 => sub
!ERROR: Type bound generic procedure 'k' may not have the same name as a non-generic symbol inherited from an ancestor type
generic :: k => sub
!ERROR: Type bound generic procedure 'x' may not have the same name as a non-generic symbol inherited from an ancestor type
generic :: x => sub
!ERROR: Type bound generic procedure 'tbp' may not have the same name as a non-generic symbol inherited from an ancestor type
generic :: tbp => sub
generic :: gen => sub ! ok
end type
contains
subroutine sub
end
end

0 comments on commit 2216c4c

Please sign in to comment.