@@ -61,6 +61,124 @@ namespace Fortran::semantics {
6161using namespace Fortran ::semantics::omp;
6262using 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 &) { \
0 commit comments