forked from OSchip/llvm-project
[flang] Fix scope accessibility check
The check for whether a private component is accessible was depending on determining whether the source range of the current scope was within the source range of the module that the component was declared in. This could fail if the current scope was of kind `ImpliedDos` and had no source range. The fix is to add `Scope::Contains` to check the relationship by traversing the parent links. These are created when the Scope is so are always reliable. The source range of a scope is built up over time. Original-commit: flang-compiler/f18@d787108637 Reviewed-on: https://github.com/flang-compiler/f18/pull/1060
This commit is contained in:
parent
749be7993e
commit
6ab50745c0
|
@ -85,15 +85,8 @@ public:
|
|||
|
||||
const Symbol *GetSymbol() const;
|
||||
const Scope *GetDerivedTypeParent() const;
|
||||
|
||||
std::optional<SourceName> GetName() const {
|
||||
if (const auto *sym{GetSymbol()}) {
|
||||
return sym->name();
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<SourceName> GetName() const;
|
||||
bool Contains(const Scope &) const;
|
||||
/// Make a scope nested in this one
|
||||
Scope &MakeScope(Kind kind, Symbol *symbol = nullptr);
|
||||
|
||||
|
|
|
@ -91,6 +91,25 @@ Symbol *Scope::FindComponent(SourceName name) const {
|
|||
}
|
||||
}
|
||||
|
||||
std::optional<SourceName> Scope::GetName() const {
|
||||
if (const auto *sym{GetSymbol()}) {
|
||||
return sym->name();
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
bool Scope::Contains(const Scope &that) const {
|
||||
for (const Scope *scope{&that};; scope = &scope->parent()) {
|
||||
if (*scope == *this) {
|
||||
return true;
|
||||
}
|
||||
if (scope->IsGlobal()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::list<EquivalenceSet> &Scope::equivalenceSets() const {
|
||||
return equivalenceSets_;
|
||||
}
|
||||
|
@ -244,8 +263,7 @@ Scope *Scope::FindScope(parser::CharBlock source) {
|
|||
}
|
||||
|
||||
void Scope::AddSourceRange(const parser::CharBlock &source) {
|
||||
for (auto *scope = this; !scope->IsGlobal();
|
||||
scope = &scope->parent()) {
|
||||
for (auto *scope = this; !scope->IsGlobal(); scope = &scope->parent()) {
|
||||
scope->sourceRange_.ExtendToCover(source);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -960,7 +960,7 @@ std::optional<parser::MessageFormattedText> CheckAccessibleComponent(
|
|||
CHECK(symbol.owner().IsDerivedType()); // symbol must be a component
|
||||
if (symbol.attrs().test(Attr::PRIVATE)) {
|
||||
if (const Scope * moduleScope{FindModuleContaining(symbol.owner())}) {
|
||||
if (!moduleScope->sourceRange().Contains(scope.sourceRange())) {
|
||||
if (!moduleScope->Contains(scope)) {
|
||||
return parser::MessageFormattedText{
|
||||
"PRIVATE component '%s' is only accessible within module '%s'"_err_en_US,
|
||||
symbol.name(), moduleScope->GetName().value()};
|
||||
|
|
|
@ -98,11 +98,16 @@ module m8
|
|||
integer :: i1
|
||||
integer, private :: i2
|
||||
end type
|
||||
type(t) :: y
|
||||
integer :: a(1)
|
||||
contains
|
||||
subroutine s0
|
||||
type(t) :: x
|
||||
x = t(i1=2, i2=5) !OK
|
||||
end
|
||||
subroutine s1
|
||||
a = [y%i2] !OK
|
||||
end subroutine
|
||||
end
|
||||
subroutine s8
|
||||
use m8
|
||||
|
@ -111,6 +116,8 @@ subroutine s8
|
|||
x = t(2, 5)
|
||||
!ERROR: PRIVATE component 'i2' is only accessible within module 'm8'
|
||||
x = t(i1=2, i2=5)
|
||||
!ERROR: PRIVATE component 'i2' is only accessible within module 'm8'
|
||||
a = [y%i2]
|
||||
end
|
||||
|
||||
! 7.5.4.8(2)
|
||||
|
|
Loading…
Reference in New Issue