[flang-commits] [flang] [flang][OpenMP] Keep track of scoping units in OmpStructureChecker (PR #164419)
Krzysztof Parzyszek via flang-commits
flang-commits at lists.llvm.org
Tue Oct 21 06:23:42 PDT 2025
https://github.com/kparzysz created https://github.com/llvm/llvm-project/pull/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.
>From 6acfa6d01979ba07e3e4e109142549830c020692 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Sat, 11 Oct 2025 13:47:36 -0500
Subject: [PATCH] [flang][OpenMP] Keep track of scoping units in
OmpStructureChecker
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.
---
flang/lib/Semantics/check-omp-structure.cpp | 118 ++++++++++++++++++++
flang/lib/Semantics/check-omp-structure.h | 35 ++++--
2 files changed, 142 insertions(+), 11 deletions(-)
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index be10669ac2536..b3c4d24ad496d 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -61,6 +61,124 @@ namespace Fortran::semantics {
using namespace Fortran::semantics::omp;
using namespace Fortran::parser::omp;
+OmpStructureChecker::OmpStructureChecker(SemanticsContext &context)
+ : DirectiveStructureChecker(context,
+#define GEN_FLANG_DIRECTIVE_CLAUSE_MAP
+#include "llvm/Frontend/OpenMP/OMP.inc"
+ ) {
+ scopeStack_.push_back(&context.globalScope());
+}
+
+bool OmpStructureChecker::Enter(const parser::MainProgram &x) {
+ using StatementProgramStmt = parser::Statement<parser::ProgramStmt>;
+ if (auto &stmt{std::get<std::optional<StatementProgramStmt>>(x.t)}) {
+ scopeStack_.push_back(stmt->statement.v.symbol->scope());
+ } else {
+ for (const Scope &scope : context_.globalScope().children()) {
+ // There can only be one main program.
+ if (scope.kind() == Scope::Kind::MainProgram) {
+ scopeStack_.push_back(&scope);
+ break;
+ }
+ }
+ }
+ return true;
+}
+
+void OmpStructureChecker::Leave(const parser::MainProgram &x) {
+ scopeStack_.pop_back();
+}
+
+bool OmpStructureChecker::Enter(const parser::BlockData &x) {
+ // The BLOCK DATA name is optional, so we need to look for the
+ // corresponding scope in the global scope.
+ auto &stmt{std::get<parser::Statement<parser::BlockDataStmt>>(x.t)};
+ if (auto &name{stmt.statement.v}) {
+ scopeStack_.push_back(name->symbol->scope());
+ } else {
+ for (const Scope &scope : context_.globalScope().children()) {
+ if (scope.kind() == Scope::Kind::BlockData) {
+ if (scope.symbol()->name().empty()) {
+ scopeStack_.push_back(&scope);
+ break;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+void OmpStructureChecker::Leave(const parser::BlockData &x) {
+ scopeStack_.pop_back();
+}
+
+bool OmpStructureChecker::Enter(const parser::Module &x) {
+ auto &stmt{std::get<parser::Statement<parser::ModuleStmt>>(x.t)};
+ const Symbol *sym{stmt.statement.v.symbol};
+ scopeStack_.push_back(sym->scope());
+ return true;
+}
+
+void OmpStructureChecker::Leave(const parser::Module &x) {
+ scopeStack_.pop_back();
+}
+
+bool OmpStructureChecker::Enter(const parser::Submodule &x) {
+ auto &stmt{std::get<parser::Statement<parser::SubmoduleStmt>>(x.t)};
+ const Symbol *sym{std::get<parser::Name>(stmt.statement.t).symbol};
+ scopeStack_.push_back(sym->scope());
+ return true;
+}
+
+void OmpStructureChecker::Leave(const parser::Submodule &x) {
+ scopeStack_.pop_back();
+}
+
+// Function/subroutine subprogram nodes don't appear in INTERFACEs, but
+// the subprogram/end statements do.
+bool OmpStructureChecker::Enter(const parser::SubroutineStmt &x) {
+ const Symbol *sym{std::get<parser::Name>(x.t).symbol};
+ scopeStack_.push_back(sym->scope());
+ return true;
+}
+
+bool OmpStructureChecker::Enter(const parser::EndSubroutineStmt &x) {
+ scopeStack_.pop_back();
+ return true;
+}
+
+bool OmpStructureChecker::Enter(const parser::FunctionStmt &x) {
+ const Symbol *sym{std::get<parser::Name>(x.t).symbol};
+ scopeStack_.push_back(sym->scope());
+ return true;
+}
+
+bool OmpStructureChecker::Enter(const parser::EndFunctionStmt &x) {
+ scopeStack_.pop_back();
+ return true;
+}
+
+bool OmpStructureChecker::Enter(const parser::BlockConstruct &x) {
+ auto &specPart{std::get<parser::BlockSpecificationPart>(x.t)};
+ auto &execPart{std::get<parser::Block>(x.t)};
+ if (auto &&source{parser::GetSource(specPart)}) {
+ scopeStack_.push_back(&context_.FindScope(*source));
+ } else if (auto &&source{parser::GetSource(execPart)}) {
+ scopeStack_.push_back(&context_.FindScope(*source));
+ }
+ return true;
+}
+
+void OmpStructureChecker::Leave(const parser::BlockConstruct &x) {
+ auto &specPart{std::get<parser::BlockSpecificationPart>(x.t)};
+ auto &execPart{std::get<parser::Block>(x.t)};
+ if (auto &&source{parser::GetSource(specPart)}) {
+ scopeStack_.push_back(&context_.FindScope(*source));
+ } else if (auto &&source{parser::GetSource(execPart)}) {
+ scopeStack_.push_back(&context_.FindScope(*source));
+ }
+}
+
// Use when clause falls under 'struct OmpClause' in 'parse-tree.h'.
#define CHECK_SIMPLE_CLAUSE(X, Y) \
void OmpStructureChecker::Enter(const parser::OmpClause::X &) { \
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 4cb0b743107d2..a09d8bad6b4cd 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -57,21 +57,32 @@ using SymbolSourceMap = std::multimap<const Symbol *, parser::CharBlock>;
using DirectivesClauseTriple = std::multimap<llvm::omp::Directive,
std::pair<llvm::omp::Directive, const OmpClauseSet>>;
-class OmpStructureChecker
- : public DirectiveStructureChecker<llvm::omp::Directive, llvm::omp::Clause,
- parser::OmpClause, llvm::omp::Clause_enumSize> {
+using OmpStructureCheckerBase = DirectiveStructureChecker<llvm::omp::Directive,
+ llvm::omp::Clause, parser::OmpClause, llvm::omp::Clause_enumSize>;
+
+class OmpStructureChecker : public OmpStructureCheckerBase {
public:
- using Base = DirectiveStructureChecker<llvm::omp::Directive,
- llvm::omp::Clause, parser::OmpClause, llvm::omp::Clause_enumSize>;
+ using Base = OmpStructureCheckerBase;
+
+ OmpStructureChecker(SemanticsContext &context);
- OmpStructureChecker(SemanticsContext &context)
- : DirectiveStructureChecker(context,
-#define GEN_FLANG_DIRECTIVE_CLAUSE_MAP
-#include "llvm/Frontend/OpenMP/OMP.inc"
- ) {
- }
using llvmOmpClause = const llvm::omp::Clause;
+ bool Enter(const parser::MainProgram &);
+ void Leave(const parser::MainProgram &);
+ bool Enter(const parser::BlockData &);
+ void Leave(const parser::BlockData &);
+ bool Enter(const parser::Module &);
+ void Leave(const parser::Module &);
+ bool Enter(const parser::Submodule &);
+ void Leave(const parser::Submodule &);
+ bool Enter(const parser::SubroutineStmt &);
+ bool Enter(const parser::EndSubroutineStmt &);
+ bool Enter(const parser::FunctionStmt &);
+ bool Enter(const parser::EndFunctionStmt &);
+ bool Enter(const parser::BlockConstruct &);
+ void Leave(const parser::BlockConstruct &);
+
void Enter(const parser::OpenMPConstruct &);
void Leave(const parser::OpenMPConstruct &);
void Enter(const parser::OpenMPInteropConstruct &);
@@ -374,6 +385,8 @@ class OmpStructureChecker
using LoopConstruct = std::variant<const parser::DoConstruct *,
const parser::OpenMPLoopConstruct *>;
std::vector<LoopConstruct> loopStack_;
+ // Scopes for scoping units.
+ std::vector<const Scope *> scopeStack_;
};
/// Find a duplicate entry in the range, and return an iterator to it.
More information about the flang-commits
mailing list