Skip to content

Commit 6409cd9

Browse files
committed
R6: Reworked to add a few more semantic checks and moved checks to check-omp-structure
1 parent 865ca2e commit 6409cd9

File tree

7 files changed

+155
-34
lines changed

7 files changed

+155
-34
lines changed

flang/lib/Semantics/check-directive-structure.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ class DirectiveStructureChecker : public virtual BaseChecker {
201201
ClauseMapTy clauseInfo;
202202
std::list<C> actualClauses;
203203
std::list<C> crtGroup;
204+
std::set<std::string> usedInScanDirective;
205+
206+
using ReductionModifier = parser::OmpReductionClause::ReductionModifier;
207+
std::map<const std::string, ReductionModifier> reductionMod;
204208
Symbol *loopIV{nullptr};
205209
};
206210

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

Lines changed: 130 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,42 @@ void OmpStructureChecker::CheckDistLinear(
974974
}
975975

976976
void OmpStructureChecker::Leave(const parser::OpenMPLoopConstruct &x) {
977+
const auto &beginLoopDir = std::get<parser::OmpBeginLoopDirective>(x.t);
978+
const auto &clauseList{std::get<parser::OmpClauseList>(beginLoopDir.t)};
979+
for (const auto &clause : clauseList.v) {
980+
if (const auto *reductionClause{
981+
std::get_if<parser::OmpClause::Reduction>(&clause.u)}) {
982+
using ReductionModifier = parser::OmpReductionClause::ReductionModifier;
983+
const auto &maybeModifier{
984+
std::get<std::optional<ReductionModifier>>(reductionClause->v.t)};
985+
if (maybeModifier && *maybeModifier == ReductionModifier::Inscan) {
986+
987+
const auto &objectList{
988+
std::get<parser::OmpObjectList>(reductionClause->v.t)};
989+
for (const auto &ompObj : objectList.v) {
990+
common::visit(
991+
common::visitors{
992+
[&](const parser::Designator &designator) {
993+
if (const auto *name{semantics::getDesignatorNameIfDataRef(
994+
designator)}) {
995+
std::string nameStr = name->symbol->name().ToString();
996+
if (GetContext().usedInScanDirective.find(nameStr) ==
997+
GetContext().usedInScanDirective.end()) {
998+
context_.Say(name->source,
999+
"List item %s must appear in 'inclusive' or "
1000+
"'exclusive' clause of an "
1001+
"enclosed scan directive"_err_en_US,
1002+
nameStr);
1003+
}
1004+
}
1005+
},
1006+
[&](const auto &name) {},
1007+
},
1008+
ompObj.u);
1009+
}
1010+
}
1011+
}
1012+
}
9771013
if (llvm::omp::allSimdSet.test(GetContext().directive)) {
9781014
ExitDirectiveNest(SIMDNest);
9791015
}
@@ -1646,19 +1682,32 @@ void OmpStructureChecker::Leave(const parser::OpenMPAllocatorsConstruct &x) {
16461682
dirContext_.pop_back();
16471683
}
16481684

1685+
void OmpStructureChecker::CheckScan(
1686+
const parser::OpenMPSimpleStandaloneConstruct &x) {
1687+
if (std::get<parser::OmpClauseList>(x.t).v.size() != 1) {
1688+
context_.Say(x.source,
1689+
"Exactly one of `exclusive` or `inclusive` clause is expected"_err_en_US);
1690+
}
1691+
if (!CurrentDirectiveIsNested() ||
1692+
!llvm::omp::scanParentAllowedSet.test(GetContextParent().directive)) {
1693+
context_.Say(x.source,
1694+
"Orphaned `omp scan` directives are prohibited; perhaps you forgot "
1695+
"to enclose the directive in to a worksharing loop, a worksharing "
1696+
"loop simd or a simd directive."_err_en_US);
1697+
}
1698+
}
1699+
16491700
void OmpStructureChecker::CheckBarrierNesting(
16501701
const parser::OpenMPSimpleStandaloneConstruct &x) {
16511702
// A barrier region may not be `closely nested` inside a worksharing, loop,
16521703
// task, taskloop, critical, ordered, atomic, or master region.
16531704
// TODO: Expand the check to include `LOOP` construct as well when it is
16541705
// supported.
1655-
if (GetContext().directive == llvm::omp::Directive::OMPD_barrier) {
1656-
if (IsCloselyNestedRegion(llvm::omp::nestedBarrierErrSet)) {
1657-
context_.Say(parser::FindSourceLocation(x),
1658-
"`BARRIER` region may not be closely nested inside of `WORKSHARING`, "
1659-
"`LOOP`, `TASK`, `TASKLOOP`,"
1660-
"`CRITICAL`, `ORDERED`, `ATOMIC` or `MASTER` region."_err_en_US);
1661-
}
1706+
if (IsCloselyNestedRegion(llvm::omp::nestedBarrierErrSet)) {
1707+
context_.Say(parser::FindSourceLocation(x),
1708+
"`BARRIER` region may not be closely nested inside of `WORKSHARING`, "
1709+
"`LOOP`, `TASK`, `TASKLOOP`,"
1710+
"`CRITICAL`, `ORDERED`, `ATOMIC` or `MASTER` region."_err_en_US);
16621711
}
16631712
}
16641713

@@ -1842,7 +1891,16 @@ void OmpStructureChecker::Enter(
18421891
const parser::OpenMPSimpleStandaloneConstruct &x) {
18431892
const auto &dir{std::get<parser::OmpSimpleStandaloneDirective>(x.t)};
18441893
PushContextAndClauseSets(dir.source, dir.v);
1845-
CheckBarrierNesting(x);
1894+
switch (dir.v) {
1895+
case llvm::omp::Directive::OMPD_barrier:
1896+
CheckBarrierNesting(x);
1897+
break;
1898+
case llvm::omp::Directive::OMPD_scan:
1899+
CheckScan(x);
1900+
break;
1901+
default:
1902+
break;
1903+
}
18461904
}
18471905

18481906
void OmpStructureChecker::Leave(
@@ -2674,15 +2732,13 @@ CHECK_SIMPLE_CLAUSE(Depobj, OMPC_depobj)
26742732
CHECK_SIMPLE_CLAUSE(Detach, OMPC_detach)
26752733
CHECK_SIMPLE_CLAUSE(DeviceType, OMPC_device_type)
26762734
CHECK_SIMPLE_CLAUSE(DistSchedule, OMPC_dist_schedule)
2677-
CHECK_SIMPLE_CLAUSE(Exclusive, OMPC_exclusive)
26782735
CHECK_SIMPLE_CLAUSE(Final, OMPC_final)
26792736
CHECK_SIMPLE_CLAUSE(Flush, OMPC_flush)
26802737
CHECK_SIMPLE_CLAUSE(Full, OMPC_full)
26812738
CHECK_SIMPLE_CLAUSE(Grainsize, OMPC_grainsize)
26822739
CHECK_SIMPLE_CLAUSE(Hint, OMPC_hint)
26832740
CHECK_SIMPLE_CLAUSE(Holds, OMPC_holds)
26842741
CHECK_SIMPLE_CLAUSE(InReduction, OMPC_in_reduction)
2685-
CHECK_SIMPLE_CLAUSE(Inclusive, OMPC_inclusive)
26862742
CHECK_SIMPLE_CLAUSE(Match, OMPC_match)
26872743
CHECK_SIMPLE_CLAUSE(Nontemporal, OMPC_nontemporal)
26882744
CHECK_SIMPLE_CLAUSE(NumTasks, OMPC_num_tasks)
@@ -2775,7 +2831,24 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Reduction &x) {
27752831
if (CheckReductionOperators(x)) {
27762832
CheckReductionTypeList(x);
27772833
}
2778-
CheckReductionModifier(x);
2834+
using ReductionModifier = parser::OmpReductionClause::ReductionModifier;
2835+
if (const auto &maybeModifier{
2836+
std::get<std::optional<ReductionModifier>>(x.v.t)}) {
2837+
ReductionModifier modifier{*maybeModifier};
2838+
const auto &ompObjectList{std::get<parser::OmpObjectList>(x.v.t)};
2839+
addModifiertoMap(ompObjectList, modifier);
2840+
CheckReductionModifier(modifier);
2841+
}
2842+
}
2843+
2844+
void OmpStructureChecker::Enter(const parser::OmpClause::Inclusive &x) {
2845+
CheckAllowed(llvm::omp::Clause::OMPC_inclusive);
2846+
checkAndAddSymbolsToUsedInScanList(x.v);
2847+
}
2848+
2849+
void OmpStructureChecker::Enter(const parser::OmpClause::Exclusive &x) {
2850+
CheckAllowed(llvm::omp::Clause::OMPC_exclusive);
2851+
checkAndAddSymbolsToUsedInScanList(x.v);
27792852
}
27802853

27812854
bool OmpStructureChecker::CheckReductionOperators(
@@ -2818,6 +2891,49 @@ bool OmpStructureChecker::CheckReductionOperators(
28182891

28192892
return ok;
28202893
}
2894+
2895+
void OmpStructureChecker::addModifiertoMap(const parser::OmpObjectList &x,
2896+
parser::OmpReductionClause::ReductionModifier &modifier) {
2897+
for (const auto &ompObject : x.v) {
2898+
if (const auto *name{parser::Unwrap<parser::Name>(ompObject)}) {
2899+
if (const auto *symbol{name->symbol}) {
2900+
GetContext().reductionMod[symbol->name().ToString()] = modifier;
2901+
}
2902+
}
2903+
}
2904+
}
2905+
2906+
void OmpStructureChecker::checkAndAddSymbolsToUsedInScanList(
2907+
const parser::OmpObjectList &x) {
2908+
for (const auto &ompObj : x.v) {
2909+
common::visit(
2910+
common::visitors{
2911+
[&](const parser::Designator &designator) {
2912+
if (const auto *name{
2913+
semantics::getDesignatorNameIfDataRef(designator)}) {
2914+
if (name->symbol) {
2915+
if (CurrentDirectiveIsNested()) {
2916+
std::string nameStr = name->symbol->name().ToString();
2917+
if (GetContextParent().reductionMod.find(nameStr) ==
2918+
GetContextParent().reductionMod.end()) {
2919+
2920+
context_.Say(name->source,
2921+
"List item %s must appear in 'reduction' clause "
2922+
"with the 'inscan' modifier of the parent "
2923+
"directive"_err_en_US,
2924+
nameStr);
2925+
}
2926+
GetContextParent().usedInScanDirective.insert(nameStr);
2927+
}
2928+
}
2929+
}
2930+
},
2931+
[&](const auto &name) {},
2932+
},
2933+
ompObj.u);
2934+
}
2935+
}
2936+
28212937
bool OmpStructureChecker::CheckIntrinsicOperator(
28222938
const parser::DefinedOperator::IntrinsicOperator &op) {
28232939

@@ -2952,14 +3068,12 @@ void OmpStructureChecker::CheckReductionTypeList(
29523068
}
29533069

29543070
void OmpStructureChecker::CheckReductionModifier(
2955-
const parser::OmpClause::Reduction &x) {
3071+
const parser::OmpReductionClause::ReductionModifier &modifier) {
29563072
using ReductionModifier = parser::OmpReductionClause::ReductionModifier;
2957-
const auto &maybeModifier{std::get<std::optional<ReductionModifier>>(x.v.t)};
2958-
if (!maybeModifier || *maybeModifier == ReductionModifier::Default) {
2959-
// No modifier, or the default one is always ok.
3073+
if (modifier == ReductionModifier::Default) {
3074+
// the default one is always ok.
29603075
return;
29613076
}
2962-
ReductionModifier modifier{*maybeModifier};
29633077
const DirectiveContext &dirCtx{GetContext()};
29643078
if (dirCtx.directive == llvm::omp::Directive::OMPD_loop) {
29653079
// [5.2:257:33-34]

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,10 +227,12 @@ class OmpStructureChecker
227227
bool CheckIntrinsicOperator(
228228
const parser::DefinedOperator::IntrinsicOperator &);
229229
void CheckReductionTypeList(const parser::OmpClause::Reduction &);
230-
void CheckReductionModifier(const parser::OmpClause::Reduction &);
230+
void CheckReductionModifier(
231+
const parser::OmpReductionClause::ReductionModifier &);
231232
void CheckMasterNesting(const parser::OpenMPBlockConstruct &x);
232233
void ChecksOnOrderedAsBlock();
233234
void CheckBarrierNesting(const parser::OpenMPSimpleStandaloneConstruct &x);
235+
void CheckScan(const parser::OpenMPSimpleStandaloneConstruct &x);
234236
void ChecksOnOrderedAsStandalone();
235237
void CheckOrderedDependClause(std::optional<std::int64_t> orderedValue);
236238
void CheckReductionArraySection(const parser::OmpObjectList &ompObjectList);
@@ -247,6 +249,9 @@ class OmpStructureChecker
247249
const parser::OmpObjectList &ompObjectList);
248250
void CheckPredefinedAllocatorRestriction(
249251
const parser::CharBlock &source, const parser::Name &name);
252+
void checkAndAddSymbolsToUsedInScanList(const parser::OmpObjectList &x);
253+
void addModifiertoMap(const parser::OmpObjectList &x,
254+
parser::OmpReductionClause::ReductionModifier &modifier);
250255
bool isPredefinedAllocator{false};
251256

252257
void CheckAllowedRequiresClause(llvmOmpClause clause);

flang/lib/Semantics/resolve-directives.cpp

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1623,7 +1623,6 @@ bool OmpAttributeVisitor::Pre(
16231623
const parser::OpenMPSimpleStandaloneConstruct &x) {
16241624
const auto &standaloneDir{
16251625
std::get<parser::OmpSimpleStandaloneDirective>(x.t)};
1626-
const auto &parentContext{GetContextIf()};
16271626
switch (standaloneDir.v) {
16281627
case llvm::omp::Directive::OMPD_barrier:
16291628
case llvm::omp::Directive::OMPD_ordered:
@@ -1638,19 +1637,6 @@ bool OmpAttributeVisitor::Pre(
16381637
default:
16391638
break;
16401639
}
1641-
if (standaloneDir.v == llvm::omp::Directive::OMPD_scan) {
1642-
if (std::get<parser::OmpClauseList>(x.t).v.size() != 1) {
1643-
context_.Say(standaloneDir.source,
1644-
"Exactly one of `exclusive` or `inclusive` clause is expected"_err_en_US);
1645-
}
1646-
if (!parentContext ||
1647-
!llvm::omp::scanParentAllowedSet.test(parentContext->directive)) {
1648-
context_.Say(standaloneDir.source,
1649-
"Orphaned `omp scan` directives are prohibited; perhaps you forgot "
1650-
"to enclose the directive in to a worksharing loop, a worksharing "
1651-
"loop simd or a simd directive."_err_en_US);
1652-
}
1653-
}
16541640
ClearDataSharingAttributeObjects();
16551641
return true;
16561642
}

flang/test/Lower/OpenMP/Todo/reduction-modifiers.f90

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ subroutine foo()
88
j = 0
99
!$omp do reduction (inscan, *: j)
1010
do i = 1, 10
11+
!$omp scan inclusive(j)
1112
j = j + 1
1213
end do
1314
end subroutine

flang/test/Semantics/OpenMP/reduction-modifiers.f90

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ subroutine mod_inscan1(x)
3939
!Correct: worksharing-loop directive
4040
!$omp do reduction(inscan, +:x)
4141
do i = 1, 100
42+
!$omp scan inclusive(x)
4243
x = foo(i)
4344
enddo
4445
!$omp end do
@@ -50,6 +51,7 @@ subroutine mod_inscan2(x)
5051
!Correct: worksharing-loop simd directive
5152
!$omp do simd reduction(inscan, +:x)
5253
do i = 1, 100
54+
!$omp scan inclusive(x)
5355
x = foo(i)
5456
enddo
5557
!$omp end do simd
@@ -61,6 +63,7 @@ subroutine mod_inscan3(x)
6163
!Correct: "simd" directive
6264
!$omp simd reduction(inscan, +:x)
6365
do i = 1, 100
66+
!$omp scan inclusive(x)
6467
x = foo(i)
6568
enddo
6669
!$omp end simd

flang/test/Semantics/OpenMP/scan.f90

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp
22

33
subroutine test_scan()
4-
integer x, y, k
4+
integer x, y, k, z
55

66
!ERROR: Orphaned `omp scan` directives are prohibited; perhaps you forgot to enclose the directive in to a worksharing loop, a worksharing loop simd or a simd directive.
77
!$omp scan inclusive(x)
8-
!$omp parallel do simd reduction(inscan,+: x)
8+
!$omp parallel do simd
99
do k = 1, n
1010
!ERROR: UNTIED clause is not allowed on the SCAN directive
1111
!$omp scan untied
1212
end do
1313

14-
!$omp parallel do simd reduction(inscan,+: x)
14+
!$omp parallel do simd
1515
do k = 1, n
1616
!ERROR: Exactly one of `exclusive` or `inclusive` clause is expected
1717
!$omp scan
@@ -22,4 +22,12 @@ subroutine test_scan()
2222
!ERROR: Exactly one of `exclusive` or `inclusive` clause is expected
2323
!$omp scan inclusive(x) exclusive(y)
2424
end do
25+
26+
!ERROR: List item y must appear in 'inclusive' or 'exclusive' clause of an enclosed scan directive
27+
!$omp parallel do simd reduction(inscan,+: x, y)
28+
do k = 1, n
29+
!ERROR: Exactly one of `exclusive` or `inclusive` clause is expected
30+
!ERROR: List item z must appear in 'reduction' clause with the 'inscan' modifier of the parent directive
31+
!$omp scan inclusive(x) exclusive(z)
32+
end do
2533
end subroutine

0 commit comments

Comments
 (0)