aboutsummaryrefslogtreecommitdiff
path: root/flang/lib/Semantics/check-omp-structure.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'flang/lib/Semantics/check-omp-structure.cpp')
-rw-r--r--flang/lib/Semantics/check-omp-structure.cpp98
1 files changed, 57 insertions, 41 deletions
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 8264e1d..20a86e9 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -16,7 +16,6 @@
#include "flang/Common/idioms.h"
#include "flang/Common/indirection.h"
#include "flang/Common/visit.h"
-#include "flang/Evaluate/shape.h"
#include "flang/Evaluate/tools.h"
#include "flang/Evaluate/type.h"
#include "flang/Parser/char-block.h"
@@ -782,12 +781,15 @@ void OmpStructureChecker::CheckTargetNest(const parser::OpenMPConstruct &c) {
void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) {
const auto &beginBlockDir{std::get<parser::OmpBeginBlockDirective>(x.t)};
- const auto &endBlockDir{std::get<parser::OmpEndBlockDirective>(x.t)};
+ const auto &endBlockDir{
+ std::get<std::optional<parser::OmpEndBlockDirective>>(x.t)};
const auto &beginDir{std::get<parser::OmpBlockDirective>(beginBlockDir.t)};
- const auto &endDir{std::get<parser::OmpBlockDirective>(endBlockDir.t)};
const parser::Block &block{std::get<parser::Block>(x.t)};
- CheckMatching<parser::OmpBlockDirective>(beginDir, endDir);
+ if (endBlockDir) {
+ const auto &endDir{std::get<parser::OmpBlockDirective>(endBlockDir->t)};
+ CheckMatching<parser::OmpBlockDirective>(beginDir, endDir);
+ }
PushContextAndClauseSets(beginDir.source, beginDir.v);
if (llvm::omp::allTargetSet.test(GetContext().directive)) {
@@ -837,14 +839,14 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) {
bool foundNowait{false};
parser::CharBlock NowaitSource;
- auto catchCopyPrivateNowaitClauses = [&](const auto &dir, bool endDir) {
+ auto catchCopyPrivateNowaitClauses = [&](const auto &dir, bool isEnd) {
for (auto &clause : std::get<parser::OmpClauseList>(dir.t).v) {
if (clause.Id() == llvm::omp::Clause::OMPC_copyprivate) {
for (const auto &ompObject : GetOmpObjectList(clause)->v) {
const auto *name{parser::Unwrap<parser::Name>(ompObject)};
if (Symbol * symbol{name->symbol}) {
if (singleCopyprivateSyms.count(symbol)) {
- if (endDir) {
+ if (isEnd) {
context_.Warn(common::UsageWarning::OpenMPUsage, name->source,
"The COPYPRIVATE clause with '%s' is already used on the SINGLE directive"_warn_en_US,
name->ToString());
@@ -858,7 +860,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) {
"'%s' appears in more than one COPYPRIVATE clause on the END SINGLE directive"_err_en_US,
name->ToString());
} else {
- if (endDir) {
+ if (isEnd) {
endSingleCopyprivateSyms.insert(symbol);
} else {
singleCopyprivateSyms.insert(symbol);
@@ -871,7 +873,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) {
context_.Say(clause.source,
"At most one NOWAIT clause can appear on the SINGLE directive"_err_en_US);
} else {
- foundNowait = !endDir;
+ foundNowait = !isEnd;
}
if (!NowaitSource.ToString().size()) {
NowaitSource = clause.source;
@@ -880,7 +882,9 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) {
}
};
catchCopyPrivateNowaitClauses(beginBlockDir, false);
- catchCopyPrivateNowaitClauses(endBlockDir, true);
+ if (endBlockDir) {
+ catchCopyPrivateNowaitClauses(*endBlockDir, true);
+ }
unsigned version{context_.langOptions().OpenMPVersion};
if (version <= 52 && NowaitSource.ToString().size() &&
(singleCopyprivateSyms.size() || endSingleCopyprivateSyms.size())) {
@@ -1053,10 +1057,11 @@ void OmpStructureChecker::Enter(const parser::OpenMPSectionsConstruct &x) {
PushContextAndClauseSets(beginDir.source, beginDir.v);
AddEndDirectiveClauses(std::get<parser::OmpClauseList>(endSectionsDir.t));
- const auto &sectionBlocks{std::get<parser::OmpSectionBlocks>(x.t)};
- for (const parser::OpenMPConstruct &block : sectionBlocks.v) {
- CheckNoBranching(std::get<parser::OpenMPSectionConstruct>(block.u).v,
- beginDir.v, beginDir.source);
+ const auto &sectionBlocks{std::get<std::list<parser::OpenMPConstruct>>(x.t)};
+ for (const parser::OpenMPConstruct &construct : sectionBlocks) {
+ auto &section{std::get<parser::OpenMPSectionConstruct>(construct.u)};
+ CheckNoBranching(
+ std::get<parser::Block>(section.t), beginDir.v, beginDir.source);
}
HasInvalidWorksharingNesting(
beginDir.source, llvm::omp::nestedWorkshareErrSet);
@@ -1564,9 +1569,10 @@ void OmpStructureChecker::Leave(const parser::OpenMPDeclareTargetConstruct &x) {
},
[&](const parser::OmpClause::Enter &enterClause) {
enterClauseFound = true;
- CheckSymbolNames(dir.source, enterClause.v);
- CheckVarIsNotPartOfAnotherVar(dir.source, enterClause.v);
- CheckThreadprivateOrDeclareTargetVar(enterClause.v);
+ auto &objList{std::get<parser::OmpObjectList>(enterClause.v.t)};
+ CheckSymbolNames(dir.source, objList);
+ CheckVarIsNotPartOfAnotherVar(dir.source, objList);
+ CheckThreadprivateOrDeclareTargetVar(objList);
},
[&](const parser::OmpClause::DeviceType &deviceTypeClause) {
deviceTypeClauseFound = true;
@@ -4024,7 +4030,11 @@ void OmpStructureChecker::Enter(const parser::OmpClause::HasDeviceAddr &x) {
void OmpStructureChecker::Enter(const parser::OmpClause::Enter &x) {
CheckAllowedClause(llvm::omp::Clause::OMPC_enter);
- const parser::OmpObjectList &objList{x.v};
+ if (!OmpVerifyModifiers(
+ x.v, llvm::omp::OMPC_enter, GetContext().clauseSource, context_)) {
+ return;
+ }
+ const parser::OmpObjectList &objList{std::get<parser::OmpObjectList>(x.v.t)};
SymbolSourceMap symbols;
GetSymbolsInObjectList(objList, symbols);
for (const auto &[symbol, source] : symbols) {
@@ -4151,21 +4161,26 @@ void OmpStructureChecker::CheckArraySection(
// Detect this by looking for array accesses on character variables which are
// not arrays.
bool isSubstring{false};
- evaluate::ExpressionAnalyzer ea{context_};
- if (MaybeExpr expr = ea.Analyze(arrayElement.base)) {
- std::optional<evaluate::Shape> shape = evaluate::GetShape(expr);
- // Not an array: rank 0
- if (shape && shape->size() == 0) {
- if (std::optional<evaluate::DynamicType> type = expr->GetType()) {
- if (type->category() == evaluate::TypeCategory::Character) {
- // Substrings are explicitly denied by the standard [6.0:163:9-11].
- // This is supported as an extension. This restriction was added in
- // OpenMP 5.2.
- isSubstring = true;
- context_.Say(GetContext().clauseSource,
- "The use of substrings in OpenMP argument lists has been disallowed since OpenMP 5.2."_port_en_US);
- } else {
- llvm_unreachable("Array indexing on a variable that isn't an array");
+ // Cannot analyze a base of an assumed-size array on its own. If we know
+ // this is an array (assumed-size or not) we can ignore it, since we're
+ // looking for strings.
+ if (!IsAssumedSizeArray(*name.symbol)) {
+ evaluate::ExpressionAnalyzer ea{context_};
+ if (MaybeExpr expr = ea.Analyze(arrayElement.base)) {
+ if (expr->Rank() == 0) {
+ // Not an array: rank 0
+ if (std::optional<evaluate::DynamicType> type = expr->GetType()) {
+ if (type->category() == evaluate::TypeCategory::Character) {
+ // Substrings are explicitly denied by the standard [6.0:163:9-11].
+ // This is supported as an extension. This restriction was added in
+ // OpenMP 5.2.
+ isSubstring = true;
+ context_.Say(GetContext().clauseSource,
+ "The use of substrings in OpenMP argument lists has been disallowed since OpenMP 5.2."_port_en_US);
+ } else {
+ llvm_unreachable(
+ "Array indexing on a variable that isn't an array");
+ }
}
}
}
@@ -4479,17 +4494,18 @@ const parser::OmpObjectList *OmpStructureChecker::GetOmpObjectList(
const parser::OmpClause &clause) {
// Clauses with OmpObjectList as its data member
- using MemberObjectListClauses = std::tuple<parser::OmpClause::Copyprivate,
- parser::OmpClause::Copyin, parser::OmpClause::Enter,
- parser::OmpClause::Firstprivate, parser::OmpClause::Link,
- parser::OmpClause::Private, parser::OmpClause::Shared,
- parser::OmpClause::UseDevicePtr, parser::OmpClause::UseDeviceAddr>;
+ using MemberObjectListClauses =
+ std::tuple<parser::OmpClause::Copyprivate, parser::OmpClause::Copyin,
+ parser::OmpClause::Firstprivate, parser::OmpClause::Link,
+ parser::OmpClause::Private, parser::OmpClause::Shared,
+ parser::OmpClause::UseDevicePtr, parser::OmpClause::UseDeviceAddr>;
// Clauses with OmpObjectList in the tuple
- using TupleObjectListClauses = std::tuple<parser::OmpClause::Aligned,
- parser::OmpClause::Allocate, parser::OmpClause::From,
- parser::OmpClause::Lastprivate, parser::OmpClause::Map,
- parser::OmpClause::Reduction, parser::OmpClause::To>;
+ using TupleObjectListClauses =
+ std::tuple<parser::OmpClause::Aligned, parser::OmpClause::Allocate,
+ parser::OmpClause::From, parser::OmpClause::Lastprivate,
+ parser::OmpClause::Map, parser::OmpClause::Reduction,
+ parser::OmpClause::To, parser::OmpClause::Enter>;
// TODO:: Generate the tuples using TableGen.
// Handle other constructs with OmpObjectList such as OpenMPThreadprivate.