[flang][NFC] Add GetTopLevelUnitContaining functions

`GetTopLevelUnitContaining` returns the Scope nested in the global scope
that contains the given Scope or Symbol.

Use "Get" rather than "Find" in the name because "Find" implies it might
not be found, which can't happen. Following that logic, rename
`FindProgramUnitContaining` to `GetProgramUnitContaining` and have it
also return a reference rather that a pointer.

Note that the use of "ProgramUnit" is slightly confusing. In the Fortran
standard, "program-unit" refers to what is called a "TopLevelUnit" here.
What we are calling a "ProgramUnit" (here and in `ProgramTree`) includes
internal subprograms while "TopLevelUnit" does not.

Differential Revision: https://reviews.llvm.org/D92491
This commit is contained in:
Tim Keith 2020-12-02 10:28:48 -08:00
parent 291cc1bbea
commit 1f525ece4a
4 changed files with 38 additions and 28 deletions

View File

@ -30,9 +30,14 @@ class DerivedTypeSpec;
class Scope; class Scope;
class Symbol; class Symbol;
// Note: Here ProgramUnit includes internal subprograms while TopLevelUnit
// does not. "program-unit" in the Fortran standard matches TopLevelUnit.
const Scope &GetTopLevelUnitContaining(const Scope &);
const Scope &GetTopLevelUnitContaining(const Symbol &);
const Scope &GetProgramUnitContaining(const Scope &);
const Scope &GetProgramUnitContaining(const Symbol &);
const Scope *FindModuleContaining(const Scope &); const Scope *FindModuleContaining(const Scope &);
const Scope *FindProgramUnitContaining(const Scope &);
const Scope *FindProgramUnitContaining(const Symbol &);
const Scope *FindPureProcedureContaining(const Scope &); const Scope *FindPureProcedureContaining(const Scope &);
const Scope *FindPureProcedureContaining(const Symbol &); const Scope *FindPureProcedureContaining(const Symbol &);
const Symbol *FindPointerComponent(const Scope &); const Symbol *FindPointerComponent(const Scope &);

View File

@ -16,11 +16,10 @@
namespace Fortran::semantics { namespace Fortran::semantics {
static const Scope *FindContainingSubprogram(const Scope &start) { static const Scope *FindContainingSubprogram(const Scope &start) {
const Scope *scope{FindProgramUnitContaining(start)}; const Scope &scope{GetProgramUnitContaining(start)};
return scope && return scope.kind() == Scope::Kind::MainProgram ||
(scope->kind() == Scope::Kind::MainProgram || scope.kind() == Scope::Kind::Subprogram
scope->kind() == Scope::Kind::Subprogram) ? &scope
? scope
: nullptr; : nullptr;
} }

View File

@ -5602,11 +5602,11 @@ bool DeclarationVisitor::CheckForHostAssociatedImplicit(
} }
bool DeclarationVisitor::IsUplevelReference(const Symbol &symbol) { bool DeclarationVisitor::IsUplevelReference(const Symbol &symbol) {
const Scope *symbolUnit{FindProgramUnitContaining(symbol)}; const Scope &symbolUnit{GetProgramUnitContaining(symbol)};
if (symbolUnit == FindProgramUnitContaining(currScope())) { if (symbolUnit == GetProgramUnitContaining(currScope())) {
return false; return false;
} else { } else {
Scope::Kind kind{DEREF(symbolUnit).kind()}; Scope::Kind kind{symbolUnit.kind()};
return kind == Scope::Kind::Subprogram || kind == Scope::Kind::MainProgram; return kind == Scope::Kind::Subprogram || kind == Scope::Kind::MainProgram;
} }
} }

View File

@ -37,13 +37,24 @@ static const Scope *FindScopeContaining(
} }
} }
const Scope &GetTopLevelUnitContaining(const Scope &start) {
CHECK(!start.IsGlobal());
return DEREF(FindScopeContaining(
start, [](const Scope &scope) { return scope.parent().IsGlobal(); }));
}
const Scope &GetTopLevelUnitContaining(const Symbol &symbol) {
return GetTopLevelUnitContaining(symbol.owner());
}
const Scope *FindModuleContaining(const Scope &start) { const Scope *FindModuleContaining(const Scope &start) {
return FindScopeContaining( return FindScopeContaining(
start, [](const Scope &scope) { return scope.IsModule(); }); start, [](const Scope &scope) { return scope.IsModule(); });
} }
const Scope *FindProgramUnitContaining(const Scope &start) { const Scope &GetProgramUnitContaining(const Scope &start) {
return FindScopeContaining(start, [](const Scope &scope) { CHECK(!start.IsGlobal());
return DEREF(FindScopeContaining(start, [](const Scope &scope) {
switch (scope.kind()) { switch (scope.kind()) {
case Scope::Kind::Module: case Scope::Kind::Module:
case Scope::Kind::MainProgram: case Scope::Kind::MainProgram:
@ -53,23 +64,19 @@ const Scope *FindProgramUnitContaining(const Scope &start) {
default: default:
return false; return false;
} }
}); }));
} }
const Scope *FindProgramUnitContaining(const Symbol &symbol) { const Scope &GetProgramUnitContaining(const Symbol &symbol) {
return FindProgramUnitContaining(symbol.owner()); return GetProgramUnitContaining(symbol.owner());
} }
const Scope *FindPureProcedureContaining(const Scope &start) { const Scope *FindPureProcedureContaining(const Scope &start) {
// N.B. We only need to examine the innermost containing program unit // N.B. We only need to examine the innermost containing program unit
// because an internal subprogram of a pure subprogram must also // because an internal subprogram of a pure subprogram must also
// be pure (C1592). // be pure (C1592).
if (const Scope * scope{FindProgramUnitContaining(start)}) { const Scope &scope{GetProgramUnitContaining(start)};
if (IsPureProcedure(*scope)) { return IsPureProcedure(scope) ? &scope : nullptr;
return scope;
}
}
return nullptr;
} }
Tristate IsDefinedAssignment( Tristate IsDefinedAssignment(
@ -176,9 +183,9 @@ bool IsCommonBlockContaining(const Symbol &block, const Symbol &object) {
} }
bool IsUseAssociated(const Symbol &symbol, const Scope &scope) { bool IsUseAssociated(const Symbol &symbol, const Scope &scope) {
const Scope *owner{FindProgramUnitContaining(symbol.GetUltimate().owner())}; const Scope &owner{GetProgramUnitContaining(symbol.GetUltimate().owner())};
return owner && owner->kind() == Scope::Kind::Module && return owner.kind() == Scope::Kind::Module &&
owner != FindProgramUnitContaining(scope); owner != GetProgramUnitContaining(scope);
} }
bool DoesScopeContain( bool DoesScopeContain(
@ -203,10 +210,9 @@ static const Symbol &FollowHostAssoc(const Symbol &symbol) {
} }
bool IsHostAssociated(const Symbol &symbol, const Scope &scope) { bool IsHostAssociated(const Symbol &symbol, const Scope &scope) {
const Scope *subprogram{FindProgramUnitContaining(scope)}; const Scope &subprogram{GetProgramUnitContaining(scope)};
return subprogram && return DoesScopeContain(
DoesScopeContain( &GetProgramUnitContaining(FollowHostAssoc(symbol)), subprogram);
FindProgramUnitContaining(FollowHostAssoc(symbol)), *subprogram);
} }
bool IsInStmtFunction(const Symbol &symbol) { bool IsInStmtFunction(const Symbol &symbol) {