Skip to content

Commit 5520e16

Browse files
authored
[flang][OpenMP] Parse ORDERED as standalone when DEPEND/DOACROSS is p… (#156693)
…resent The OpenMP spec 4.5-5.1 defines ORDERED as standalone when a DEPEND clause is present (with either SOURCE or SINK as argument). The OpenMP spec 5.2+ defines ORDERED as standalone when a DOACROSS clause is present.
1 parent 4931c3a commit 5520e16

File tree

6 files changed

+36
-38
lines changed

6 files changed

+36
-38
lines changed

flang/lib/Parser/openmp-parsers.cpp

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,6 +1281,16 @@ static bool IsFortranBlockConstruct(const ExecutionPartConstruct &epc) {
12811281
}
12821282
}
12831283

1284+
static bool IsStandaloneOrdered(const OmpDirectiveSpecification &dirSpec) {
1285+
// An ORDERED construct is standalone if it has DOACROSS or DEPEND clause.
1286+
return dirSpec.DirId() == llvm::omp::Directive::OMPD_ordered &&
1287+
llvm::any_of(dirSpec.Clauses().v, [](const OmpClause &clause) {
1288+
llvm::omp::Clause id{clause.Id()};
1289+
return id == llvm::omp::Clause::OMPC_depend ||
1290+
id == llvm::omp::Clause::OMPC_doacross;
1291+
});
1292+
}
1293+
12841294
struct StrictlyStructuredBlockParser {
12851295
using resultType = Block;
12861296

@@ -1464,6 +1474,9 @@ struct OmpBlockConstructParser {
14641474

14651475
std::optional<resultType> Parse(ParseState &state) const {
14661476
if (auto &&begin{OmpBeginDirectiveParser(dir_).Parse(state)}) {
1477+
if (IsStandaloneOrdered(*begin)) {
1478+
return std::nullopt;
1479+
}
14671480
if (auto &&body{attempt(StrictlyStructuredBlockParser{}).Parse(state)}) {
14681481
// Try strictly-structured block with an optional end-directive
14691482
auto end{maybe(OmpEndDirectiveParser{dir_}).Parse(state)};
@@ -1475,17 +1488,6 @@ struct OmpBlockConstructParser {
14751488
attempt(LooselyStructuredBlockParser{}).Parse(state)}) {
14761489
// Try loosely-structured block with a mandatory end-directive.
14771490
auto end{maybe(OmpEndDirectiveParser{dir_}).Parse(state)};
1478-
// Dereference outer optional (maybe() always succeeds) and look at the
1479-
// inner optional.
1480-
bool endPresent{end->has_value()};
1481-
1482-
// ORDERED is special. We do need to return failure here so that the
1483-
// standalone ORDERED construct can be distinguished from the block
1484-
// associated construct.
1485-
if (!endPresent && dir_ == llvm::omp::Directive::OMPD_ordered) {
1486-
return std::nullopt;
1487-
}
1488-
14891491
// Delay the error for a missing end-directive until semantics so that
14901492
// we have better control over the output.
14911493
return OmpBlockConstruct{OmpBeginDirective(std::move(*begin)),
@@ -1642,7 +1644,6 @@ TYPE_PARSER(sourced( //
16421644
static bool IsSimpleStandalone(const OmpDirectiveName &name) {
16431645
switch (name.v) {
16441646
case llvm::omp::Directive::OMPD_barrier:
1645-
case llvm::omp::Directive::OMPD_ordered:
16461647
case llvm::omp::Directive::OMPD_scan:
16471648
case llvm::omp::Directive::OMPD_target_enter_data:
16481649
case llvm::omp::Directive::OMPD_target_exit_data:
@@ -1658,7 +1659,9 @@ static bool IsSimpleStandalone(const OmpDirectiveName &name) {
16581659
TYPE_PARSER(sourced( //
16591660
construct<OpenMPSimpleStandaloneConstruct>(
16601661
predicated(OmpDirectiveNameParser{}, IsSimpleStandalone) >=
1661-
Parser<OmpDirectiveSpecification>{})))
1662+
Parser<OmpDirectiveSpecification>{}) ||
1663+
construct<OpenMPSimpleStandaloneConstruct>(
1664+
predicated(Parser<OmpDirectiveSpecification>{}, IsStandaloneOrdered))))
16621665

16631666
TYPE_PARSER(sourced( //
16641667
construct<OpenMPFlushConstruct>(

flang/lib/Semantics/check-omp-structure.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -890,8 +890,16 @@ void OmpStructureChecker::Enter(const parser::OmpBlockConstruct &x) {
890890
executableConstruct->u);
891891
}};
892892
if (!endSpec && !isStrictlyStructuredBlock(block)) {
893-
context_.Say(
894-
x.BeginDir().source, "Expected OpenMP end directive"_err_en_US);
893+
llvm::omp::Directive dirId{beginSpec.DirId()};
894+
auto &msg{context_.Say(beginSpec.source,
895+
"Expected OpenMP END %s directive"_err_en_US,
896+
parser::ToUpperCaseLetters(getDirectiveName(dirId)))};
897+
// ORDERED has two variants, so be explicit about which variant we think
898+
// this is.
899+
if (dirId == llvm::omp::Directive::OMPD_ordered) {
900+
msg.Attach(
901+
beginSpec.source, "The ORDERED directive is block-associated"_en_US);
902+
}
895903
}
896904

897905
if (llvm::omp::allTargetSet.test(GetContext().directive)) {
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
! RUN: not %flang_fc1 -fsyntax-only -fopenmp %s 2>&1 | FileCheck %s
22

3-
!$omp parallel
4-
! CHECK: error: Expected OpenMP end directive
3+
!$omp parallel
4+
! CHECK: error: Expected OpenMP END PARALLEL directive
55
end

flang/test/Parser/OpenMP/ordered-block-vs-standalone.f90

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=45 %s | FileCheck %s
1+
! RUN: %flang_fc1 -fdebug-dump-parse-tree-no-sema -fopenmp -fopenmp-version=45 %s | FileCheck %s
22

33
! Check that standalone ORDERED is successfully distinguished form block associated ORDERED
44

@@ -12,7 +12,7 @@ subroutine standalone
1212
! CHECK-NEXT: | OmpDirectiveName -> llvm::omp::Directive = ordered
1313
! CHECK-NEXT: | OmpClauseList ->
1414
! CHECK-NEXT: | Flags = None
15-
!$omp ordered
15+
!$omp ordered depend(source)
1616
x(i, j) = i + j
1717
end do
1818
end do

flang/test/Semantics/OpenMP/missing-end-directive.f90

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22

33
! Test that we can diagnose missing end directives without an explosion of errors
44

5-
! ERROR: Expected OpenMP end directive
5+
! ERROR: Expected OpenMP END PARALLEL directive
66
!$omp parallel
7-
! ERROR: Expected OpenMP end directive
7+
! ERROR: Expected OpenMP END TASK directive
88
!$omp task
99
! ERROR: Expected OpenMP END SECTIONS directive
1010
!$omp sections
11-
! ERROR: Expected OpenMP end directive
11+
! ERROR: Expected OpenMP END PARALLEL directive
1212
!$omp parallel
13-
! ERROR: Expected OpenMP end directive
13+
! ERROR: Expected OpenMP END TASK directive
1414
!$omp task
1515
! ERROR: Expected OpenMP END SECTIONS directive
1616
!$omp sections

flang/test/Semantics/OpenMP/ordered01.f90

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -52,27 +52,14 @@ program main
5252
end do
5353
!$omp end do
5454

55-
!$omp do ordered(1)
56-
do i = 2, N
57-
!ERROR: DEPEND clauses are not allowed when ORDERED construct is a block construct with an ORDERED region
58-
!$omp ordered depend(source)
59-
arrayA(i) = foo(i)
60-
!$omp end ordered
61-
!ERROR: DEPEND clauses are not allowed when ORDERED construct is a block construct with an ORDERED region
62-
!$omp ordered depend(sink: i - 1)
63-
arrayB(i) = bar(arrayA(i), arrayB(i-1))
64-
!$omp end ordered
65-
end do
66-
!$omp end do
67-
6855
contains
6956
subroutine work1()
70-
!ERROR: THREADS and SIMD clauses are not allowed when ORDERED construct is a standalone construct with no ORDERED region
57+
!ERROR: Expected OpenMP END ORDERED directive
7158
!$omp ordered simd
7259
end subroutine work1
7360

7461
subroutine work2()
75-
!ERROR: THREADS and SIMD clauses are not allowed when ORDERED construct is a standalone construct with no ORDERED region
62+
!ERROR: Expected OpenMP END ORDERED directive
7663
!$omp ordered threads
7764
end subroutine work2
7865

0 commit comments

Comments
 (0)