Skip to content

Commit 5f4d3c8

Browse files
kparzyszaokblast
authored andcommitted
[flang][OpenMP] Keep track of scoping units in OmpStructureChecker (llvm#164419)
Introduce a stack of scopes to OmpStructureChecker for scoping units, plus function/subroutine entries in interfaces. This will help with applying and locating properties introduced by declarative or informational directives (e.g. DECLARE_TARGET, REQUIRES), which are stored as flags on the corresponding symbols.
1 parent b2b62c1 commit 5f4d3c8

File tree

2 files changed

+142
-11
lines changed

2 files changed

+142
-11
lines changed

flang/lib/Semantics/check-omp-structure.cpp

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,124 @@ namespace Fortran::semantics {
6161
using namespace Fortran::semantics::omp;
6262
using namespace Fortran::parser::omp;
6363

64+
OmpStructureChecker::OmpStructureChecker(SemanticsContext &context)
65+
: DirectiveStructureChecker(context,
66+
#define GEN_FLANG_DIRECTIVE_CLAUSE_MAP
67+
#include "llvm/Frontend/OpenMP/OMP.inc"
68+
) {
69+
scopeStack_.push_back(&context.globalScope());
70+
}
71+
72+
bool OmpStructureChecker::Enter(const parser::MainProgram &x) {
73+
using StatementProgramStmt = parser::Statement<parser::ProgramStmt>;
74+
if (auto &stmt{std::get<std::optional<StatementProgramStmt>>(x.t)}) {
75+
scopeStack_.push_back(stmt->statement.v.symbol->scope());
76+
} else {
77+
for (const Scope &scope : context_.globalScope().children()) {
78+
// There can only be one main program.
79+
if (scope.kind() == Scope::Kind::MainProgram) {
80+
scopeStack_.push_back(&scope);
81+
break;
82+
}
83+
}
84+
}
85+
return true;
86+
}
87+
88+
void OmpStructureChecker::Leave(const parser::MainProgram &x) {
89+
scopeStack_.pop_back();
90+
}
91+
92+
bool OmpStructureChecker::Enter(const parser::BlockData &x) {
93+
// The BLOCK DATA name is optional, so we need to look for the
94+
// corresponding scope in the global scope.
95+
auto &stmt{std::get<parser::Statement<parser::BlockDataStmt>>(x.t)};
96+
if (auto &name{stmt.statement.v}) {
97+
scopeStack_.push_back(name->symbol->scope());
98+
} else {
99+
for (const Scope &scope : context_.globalScope().children()) {
100+
if (scope.kind() == Scope::Kind::BlockData) {
101+
if (scope.symbol()->name().empty()) {
102+
scopeStack_.push_back(&scope);
103+
break;
104+
}
105+
}
106+
}
107+
}
108+
return true;
109+
}
110+
111+
void OmpStructureChecker::Leave(const parser::BlockData &x) {
112+
scopeStack_.pop_back();
113+
}
114+
115+
bool OmpStructureChecker::Enter(const parser::Module &x) {
116+
auto &stmt{std::get<parser::Statement<parser::ModuleStmt>>(x.t)};
117+
const Symbol *sym{stmt.statement.v.symbol};
118+
scopeStack_.push_back(sym->scope());
119+
return true;
120+
}
121+
122+
void OmpStructureChecker::Leave(const parser::Module &x) {
123+
scopeStack_.pop_back();
124+
}
125+
126+
bool OmpStructureChecker::Enter(const parser::Submodule &x) {
127+
auto &stmt{std::get<parser::Statement<parser::SubmoduleStmt>>(x.t)};
128+
const Symbol *sym{std::get<parser::Name>(stmt.statement.t).symbol};
129+
scopeStack_.push_back(sym->scope());
130+
return true;
131+
}
132+
133+
void OmpStructureChecker::Leave(const parser::Submodule &x) {
134+
scopeStack_.pop_back();
135+
}
136+
137+
// Function/subroutine subprogram nodes don't appear in INTERFACEs, but
138+
// the subprogram/end statements do.
139+
bool OmpStructureChecker::Enter(const parser::SubroutineStmt &x) {
140+
const Symbol *sym{std::get<parser::Name>(x.t).symbol};
141+
scopeStack_.push_back(sym->scope());
142+
return true;
143+
}
144+
145+
bool OmpStructureChecker::Enter(const parser::EndSubroutineStmt &x) {
146+
scopeStack_.pop_back();
147+
return true;
148+
}
149+
150+
bool OmpStructureChecker::Enter(const parser::FunctionStmt &x) {
151+
const Symbol *sym{std::get<parser::Name>(x.t).symbol};
152+
scopeStack_.push_back(sym->scope());
153+
return true;
154+
}
155+
156+
bool OmpStructureChecker::Enter(const parser::EndFunctionStmt &x) {
157+
scopeStack_.pop_back();
158+
return true;
159+
}
160+
161+
bool OmpStructureChecker::Enter(const parser::BlockConstruct &x) {
162+
auto &specPart{std::get<parser::BlockSpecificationPart>(x.t)};
163+
auto &execPart{std::get<parser::Block>(x.t)};
164+
if (auto &&source{parser::GetSource(specPart)}) {
165+
scopeStack_.push_back(&context_.FindScope(*source));
166+
} else if (auto &&source{parser::GetSource(execPart)}) {
167+
scopeStack_.push_back(&context_.FindScope(*source));
168+
}
169+
return true;
170+
}
171+
172+
void OmpStructureChecker::Leave(const parser::BlockConstruct &x) {
173+
auto &specPart{std::get<parser::BlockSpecificationPart>(x.t)};
174+
auto &execPart{std::get<parser::Block>(x.t)};
175+
if (auto &&source{parser::GetSource(specPart)}) {
176+
scopeStack_.push_back(&context_.FindScope(*source));
177+
} else if (auto &&source{parser::GetSource(execPart)}) {
178+
scopeStack_.push_back(&context_.FindScope(*source));
179+
}
180+
}
181+
64182
// Use when clause falls under 'struct OmpClause' in 'parse-tree.h'.
65183
#define CHECK_SIMPLE_CLAUSE(X, Y) \
66184
void OmpStructureChecker::Enter(const parser::OmpClause::X &) { \

flang/lib/Semantics/check-omp-structure.h

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -56,21 +56,32 @@ using SymbolSourceMap = std::multimap<const Symbol *, parser::CharBlock>;
5656
using DirectivesClauseTriple = std::multimap<llvm::omp::Directive,
5757
std::pair<llvm::omp::Directive, const OmpClauseSet>>;
5858

59-
class OmpStructureChecker
60-
: public DirectiveStructureChecker<llvm::omp::Directive, llvm::omp::Clause,
61-
parser::OmpClause, llvm::omp::Clause_enumSize> {
59+
using OmpStructureCheckerBase = DirectiveStructureChecker<llvm::omp::Directive,
60+
llvm::omp::Clause, parser::OmpClause, llvm::omp::Clause_enumSize>;
61+
62+
class OmpStructureChecker : public OmpStructureCheckerBase {
6263
public:
63-
using Base = DirectiveStructureChecker<llvm::omp::Directive,
64-
llvm::omp::Clause, parser::OmpClause, llvm::omp::Clause_enumSize>;
64+
using Base = OmpStructureCheckerBase;
65+
66+
OmpStructureChecker(SemanticsContext &context);
6567

66-
OmpStructureChecker(SemanticsContext &context)
67-
: DirectiveStructureChecker(context,
68-
#define GEN_FLANG_DIRECTIVE_CLAUSE_MAP
69-
#include "llvm/Frontend/OpenMP/OMP.inc"
70-
) {
71-
}
7268
using llvmOmpClause = const llvm::omp::Clause;
7369

70+
bool Enter(const parser::MainProgram &);
71+
void Leave(const parser::MainProgram &);
72+
bool Enter(const parser::BlockData &);
73+
void Leave(const parser::BlockData &);
74+
bool Enter(const parser::Module &);
75+
void Leave(const parser::Module &);
76+
bool Enter(const parser::Submodule &);
77+
void Leave(const parser::Submodule &);
78+
bool Enter(const parser::SubroutineStmt &);
79+
bool Enter(const parser::EndSubroutineStmt &);
80+
bool Enter(const parser::FunctionStmt &);
81+
bool Enter(const parser::EndFunctionStmt &);
82+
bool Enter(const parser::BlockConstruct &);
83+
void Leave(const parser::BlockConstruct &);
84+
7485
void Enter(const parser::OpenMPConstruct &);
7586
void Leave(const parser::OpenMPConstruct &);
7687
void Enter(const parser::OpenMPInteropConstruct &);
@@ -373,6 +384,8 @@ class OmpStructureChecker
373384
using LoopConstruct = std::variant<const parser::DoConstruct *,
374385
const parser::OpenMPLoopConstruct *>;
375386
std::vector<LoopConstruct> loopStack_;
387+
// Scopes for scoping units.
388+
std::vector<const Scope *> scopeStack_;
376389
};
377390

378391
/// Find a duplicate entry in the range, and return an iterator to it.

0 commit comments

Comments
 (0)