Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions flang/include/flang/Semantics/openmp-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ template <typename T, typename U = std::remove_const_t<T>> U AsRvalue(T &t) {
template <typename T> T &&AsRvalue(T &&t) { return std::move(t); }

const Scope &GetScopingUnit(const Scope &scope);
const Scope &GetProgramUnit(const Scope &scope);

// There is no consistent way to get the source of an ActionStmt, but there
// is "source" in Statement<T>. This structure keeps the ActionStmt with the
Expand Down
23 changes: 22 additions & 1 deletion flang/lib/Semantics/openmp-utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "flang/Semantics/openmp-utils.h"

#include "flang/Common/Fortran-consts.h"
#include "flang/Common/idioms.h"
#include "flang/Common/indirection.h"
#include "flang/Common/reference.h"
#include "flang/Common/visit.h"
Expand Down Expand Up @@ -59,6 +60,26 @@ const Scope &GetScopingUnit(const Scope &scope) {
return *iter;
}

const Scope &GetProgramUnit(const Scope &scope) {
const Scope *unit{nullptr};
for (const Scope *iter{&scope}; !iter->IsTopLevel(); iter = &iter->parent()) {
switch (iter->kind()) {
case Scope::Kind::BlockData:
case Scope::Kind::MainProgram:
case Scope::Kind::Module:
return *iter;
case Scope::Kind::Subprogram:
// Ignore subprograms that are nested.
unit = iter;
break;
default:
break;
}
}
assert(unit && "Scope not in a program unit");
return *unit;
}

SourcedActionStmt GetActionStmt(const parser::ExecutionPartConstruct *x) {
if (x == nullptr) {
return SourcedActionStmt{};
Expand Down Expand Up @@ -202,7 +223,7 @@ std::optional<SomeExpr> GetEvaluateExpr(const parser::Expr &parserExpr) {
// ForwardOwningPointer typedExpr
// `- GenericExprWrapper ^.get()
// `- std::optional<Expr> ^->v
return typedExpr.get()->v;
return DEREF(typedExpr.get()).v;
}

std::optional<evaluate::DynamicType> GetDynamicType(
Expand Down
60 changes: 29 additions & 31 deletions flang/lib/Semantics/resolve-directives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3549,40 +3549,38 @@ void OmpAttributeVisitor::CheckLabelContext(const parser::CharBlock source,
void OmpAttributeVisitor::AddOmpRequiresToScope(Scope &scope,
WithOmpDeclarative::RequiresFlags flags,
std::optional<common::OmpMemoryOrderType> memOrder) {
Scope *scopeIter = &scope;
do {
if (Symbol * symbol{scopeIter->symbol()}) {
common::visit(
[&](auto &details) {
// Store clauses information into the symbol for the parent and
// enclosing modules, programs, functions and subroutines.
if constexpr (std::is_convertible_v<decltype(&details),
WithOmpDeclarative *>) {
if (flags.any()) {
if (const WithOmpDeclarative::RequiresFlags *
otherFlags{details.ompRequires()}) {
flags |= *otherFlags;
}
details.set_ompRequires(flags);
const Scope &programUnit{omp::GetProgramUnit(scope)};

if (auto *symbol{const_cast<Symbol *>(programUnit.symbol())}) {
common::visit(
[&](auto &details) {
// Store clauses information into the symbol for the parent and
// enclosing modules, programs, functions and subroutines.
if constexpr (std::is_convertible_v<decltype(&details),
WithOmpDeclarative *>) {
if (flags.any()) {
if (const WithOmpDeclarative::RequiresFlags *otherFlags{
details.ompRequires()}) {
flags |= *otherFlags;
}
if (memOrder) {
if (details.has_ompAtomicDefaultMemOrder() &&
*details.ompAtomicDefaultMemOrder() != *memOrder) {
context_.Say(scopeIter->sourceRange(),
"Conflicting '%s' REQUIRES clauses found in compilation "
"unit"_err_en_US,
parser::ToUpperCaseLetters(llvm::omp::getOpenMPClauseName(
llvm::omp::Clause::OMPC_atomic_default_mem_order)
.str()));
}
details.set_ompAtomicDefaultMemOrder(*memOrder);
details.set_ompRequires(flags);
}
if (memOrder) {
if (details.has_ompAtomicDefaultMemOrder() &&
*details.ompAtomicDefaultMemOrder() != *memOrder) {
context_.Say(programUnit.sourceRange(),
"Conflicting '%s' REQUIRES clauses found in compilation "
"unit"_err_en_US,
parser::ToUpperCaseLetters(llvm::omp::getOpenMPClauseName(
llvm::omp::Clause::OMPC_atomic_default_mem_order)
.str()));
}
details.set_ompAtomicDefaultMemOrder(*memOrder);
}
},
symbol->details());
}
scopeIter = &scopeIter->parent();
} while (!scopeIter->IsGlobal());
}
},
symbol->details());
}
}

void OmpAttributeVisitor::IssueNonConformanceWarning(llvm::omp::Directive D,
Expand Down