Skip to content

Commit bd79667

Browse files
authored
[flang][OpenMP] Set REQUIRES flags on program unit symbol (#163448)
REQUIRES clauses apply to the compilation unit, which the OpenMP spec defines as the program unit in Fortran. Don't set REQUIRES flags on all containing scopes, only on the containng program unit, where flags coming from different directives are gathered. If we wanted to set the flags on subprograms, we would need to first accummulate all of them, then propagate them down to all subprograms. That is not done as it is not necessary (the containing program unit is always available).
1 parent c2eed93 commit bd79667

File tree

3 files changed

+52
-32
lines changed

3 files changed

+52
-32
lines changed

flang/include/flang/Semantics/openmp-utils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ template <typename T, typename U = std::remove_const_t<T>> U AsRvalue(T &t) {
3838
template <typename T> T &&AsRvalue(T &&t) { return std::move(t); }
3939

4040
const Scope &GetScopingUnit(const Scope &scope);
41+
const Scope &GetProgramUnit(const Scope &scope);
4142

4243
// There is no consistent way to get the source of an ActionStmt, but there
4344
// is "source" in Statement<T>. This structure keeps the ActionStmt with the

flang/lib/Semantics/openmp-utils.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "flang/Semantics/openmp-utils.h"
1414

1515
#include "flang/Common/Fortran-consts.h"
16+
#include "flang/Common/idioms.h"
1617
#include "flang/Common/indirection.h"
1718
#include "flang/Common/reference.h"
1819
#include "flang/Common/visit.h"
@@ -59,6 +60,26 @@ const Scope &GetScopingUnit(const Scope &scope) {
5960
return *iter;
6061
}
6162

63+
const Scope &GetProgramUnit(const Scope &scope) {
64+
const Scope *unit{nullptr};
65+
for (const Scope *iter{&scope}; !iter->IsTopLevel(); iter = &iter->parent()) {
66+
switch (iter->kind()) {
67+
case Scope::Kind::BlockData:
68+
case Scope::Kind::MainProgram:
69+
case Scope::Kind::Module:
70+
return *iter;
71+
case Scope::Kind::Subprogram:
72+
// Ignore subprograms that are nested.
73+
unit = iter;
74+
break;
75+
default:
76+
break;
77+
}
78+
}
79+
assert(unit && "Scope not in a program unit");
80+
return *unit;
81+
}
82+
6283
SourcedActionStmt GetActionStmt(const parser::ExecutionPartConstruct *x) {
6384
if (x == nullptr) {
6485
return SourcedActionStmt{};
@@ -202,7 +223,7 @@ std::optional<SomeExpr> GetEvaluateExpr(const parser::Expr &parserExpr) {
202223
// ForwardOwningPointer typedExpr
203224
// `- GenericExprWrapper ^.get()
204225
// `- std::optional<Expr> ^->v
205-
return typedExpr.get()->v;
226+
return DEREF(typedExpr.get()).v;
206227
}
207228

208229
std::optional<evaluate::DynamicType> GetDynamicType(

flang/lib/Semantics/resolve-directives.cpp

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3549,40 +3549,38 @@ void OmpAttributeVisitor::CheckLabelContext(const parser::CharBlock source,
35493549
void OmpAttributeVisitor::AddOmpRequiresToScope(Scope &scope,
35503550
WithOmpDeclarative::RequiresFlags flags,
35513551
std::optional<common::OmpMemoryOrderType> memOrder) {
3552-
Scope *scopeIter = &scope;
3553-
do {
3554-
if (Symbol * symbol{scopeIter->symbol()}) {
3555-
common::visit(
3556-
[&](auto &details) {
3557-
// Store clauses information into the symbol for the parent and
3558-
// enclosing modules, programs, functions and subroutines.
3559-
if constexpr (std::is_convertible_v<decltype(&details),
3560-
WithOmpDeclarative *>) {
3561-
if (flags.any()) {
3562-
if (const WithOmpDeclarative::RequiresFlags *
3563-
otherFlags{details.ompRequires()}) {
3564-
flags |= *otherFlags;
3565-
}
3566-
details.set_ompRequires(flags);
3552+
const Scope &programUnit{omp::GetProgramUnit(scope)};
3553+
3554+
if (auto *symbol{const_cast<Symbol *>(programUnit.symbol())}) {
3555+
common::visit(
3556+
[&](auto &details) {
3557+
// Store clauses information into the symbol for the parent and
3558+
// enclosing modules, programs, functions and subroutines.
3559+
if constexpr (std::is_convertible_v<decltype(&details),
3560+
WithOmpDeclarative *>) {
3561+
if (flags.any()) {
3562+
if (const WithOmpDeclarative::RequiresFlags *otherFlags{
3563+
details.ompRequires()}) {
3564+
flags |= *otherFlags;
35673565
}
3568-
if (memOrder) {
3569-
if (details.has_ompAtomicDefaultMemOrder() &&
3570-
*details.ompAtomicDefaultMemOrder() != *memOrder) {
3571-
context_.Say(scopeIter->sourceRange(),
3572-
"Conflicting '%s' REQUIRES clauses found in compilation "
3573-
"unit"_err_en_US,
3574-
parser::ToUpperCaseLetters(llvm::omp::getOpenMPClauseName(
3575-
llvm::omp::Clause::OMPC_atomic_default_mem_order)
3576-
.str()));
3577-
}
3578-
details.set_ompAtomicDefaultMemOrder(*memOrder);
3566+
details.set_ompRequires(flags);
3567+
}
3568+
if (memOrder) {
3569+
if (details.has_ompAtomicDefaultMemOrder() &&
3570+
*details.ompAtomicDefaultMemOrder() != *memOrder) {
3571+
context_.Say(programUnit.sourceRange(),
3572+
"Conflicting '%s' REQUIRES clauses found in compilation "
3573+
"unit"_err_en_US,
3574+
parser::ToUpperCaseLetters(llvm::omp::getOpenMPClauseName(
3575+
llvm::omp::Clause::OMPC_atomic_default_mem_order)
3576+
.str()));
35793577
}
3578+
details.set_ompAtomicDefaultMemOrder(*memOrder);
35803579
}
3581-
},
3582-
symbol->details());
3583-
}
3584-
scopeIter = &scopeIter->parent();
3585-
} while (!scopeIter->IsGlobal());
3580+
}
3581+
},
3582+
symbol->details());
3583+
}
35863584
}
35873585

35883586
void OmpAttributeVisitor::IssueNonConformanceWarning(llvm::omp::Directive D,

0 commit comments

Comments
 (0)