[OPENMP50]Do not allow several scan directives in the same parent

region.

According to OpenMP 5.0, exactly one scan directive must appear in the loop body of an enclosing worksharing-loop, worksharing-loop SIMD, or simd construct on which a reduction clause with the inscan modifier is present.
This commit is contained in:
Alexey Bataev 2020-03-20 15:27:16 -04:00
parent 7ec2444880
commit 9b95929a26
3 changed files with 37 additions and 6 deletions

View File

@ -9833,6 +9833,10 @@ def err_omp_prohibited_region_critical_same_name : Error<
"cannot nest 'critical' regions having the same name %0">; "cannot nest 'critical' regions having the same name %0">;
def note_omp_previous_critical_region : Note< def note_omp_previous_critical_region : Note<
"previous 'critical' region starts here">; "previous 'critical' region starts here">;
def err_omp_several_scan_directives_in_region : Error<
"exactly one 'scan' directive must appear in the loop body of an enclosing directive">;
def note_omp_previous_scan_directive : Note<
"previous 'scan' directive used here">;
def err_omp_sections_not_compound_stmt : Error< def err_omp_sections_not_compound_stmt : Error<
"the statement for '#pragma omp sections' must be a compound statement">; "the statement for '#pragma omp sections' must be a compound statement">;
def err_omp_parallel_sections_not_compound_stmt : Error< def err_omp_parallel_sections_not_compound_stmt : Error<

View File

@ -154,6 +154,7 @@ private:
bool CancelRegion = false; bool CancelRegion = false;
bool LoopStart = false; bool LoopStart = false;
bool BodyComplete = false; bool BodyComplete = false;
SourceLocation PrevScanLocation;
SourceLocation InnerTeamsRegionLoc; SourceLocation InnerTeamsRegionLoc;
/// Reference to the taskgroup task_reduction reference expression. /// Reference to the taskgroup task_reduction reference expression.
Expr *TaskgroupReductionRef = nullptr; Expr *TaskgroupReductionRef = nullptr;
@ -781,6 +782,22 @@ public:
return Top ? Top->CancelRegion : false; return Top ? Top->CancelRegion : false;
} }
/// Mark that parent region already has scan directive.
void setParentHasScanDirective(SourceLocation Loc) {
if (SharingMapTy *Parent = getSecondOnStackOrNull())
Parent->PrevScanLocation = Loc;
}
/// Return true if current region has inner cancel construct.
bool doesParentHasScanDirective() const {
const SharingMapTy *Top = getSecondOnStackOrNull();
return Top ? Top->PrevScanLocation.isValid() : false;
}
/// Return true if current region has inner cancel construct.
SourceLocation getParentScanDirectiveLoc() const {
const SharingMapTy *Top = getSecondOnStackOrNull();
return Top ? Top->PrevScanLocation : SourceLocation();
}
/// Set collapse value for the region. /// Set collapse value for the region.
void setAssociatedLoops(unsigned Val) { void setAssociatedLoops(unsigned Val) {
getTopOfStack().AssociatedLoops = Val; getTopOfStack().AssociatedLoops = Val;
@ -8795,11 +8812,21 @@ StmtResult Sema::ActOnOpenMPDepobjDirective(ArrayRef<OMPClause *> Clauses,
StmtResult Sema::ActOnOpenMPScanDirective(ArrayRef<OMPClause *> Clauses, StmtResult Sema::ActOnOpenMPScanDirective(ArrayRef<OMPClause *> Clauses,
SourceLocation StartLoc, SourceLocation StartLoc,
SourceLocation EndLoc) { SourceLocation EndLoc) {
// Check that exactly one clause is specified.
if (Clauses.size() != 1) { if (Clauses.size() != 1) {
Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(), Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
diag::err_omp_scan_single_clause_expected); diag::err_omp_scan_single_clause_expected);
return StmtError(); return StmtError();
} }
// Check that only one instance of scan directives is used in the same outer
// region.
if (DSAStack->doesParentHasScanDirective()) {
Diag(StartLoc, diag::err_omp_several_scan_directives_in_region);
Diag(DSAStack->getParentScanDirectiveLoc(),
diag::note_omp_previous_scan_directive);
return StmtError();
}
DSAStack->setParentHasScanDirective(StartLoc);
return OMPScanDirective::Create(Context, StartLoc, EndLoc, Clauses); return OMPScanDirective::Create(Context, StartLoc, EndLoc, Clauses);
} }

View File

@ -54,12 +54,12 @@ T tmain(T argc) {
#pragma omp simd #pragma omp simd
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
switch (argc) { switch (argc) {
#pragma omp scan inclusive(argc) #pragma omp scan inclusive(argc) // expected-note 2 {{previous 'scan' directive used here}}
case 1: case 1:
#pragma omp scan inclusive(argc) #pragma omp scan inclusive(argc) // expected-error {{exactly one 'scan' directive must appear in the loop body of an enclosing directive}}
break; break;
default: { default: {
#pragma omp scan inclusive(argc) #pragma omp scan inclusive(argc) // expected-error {{exactly one 'scan' directive must appear in the loop body of an enclosing directive}}
} break; } break;
} }
#pragma omp simd #pragma omp simd
@ -133,12 +133,12 @@ int main(int argc, char **argv) {
#pragma omp simd #pragma omp simd
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
switch (argc) { switch (argc) {
#pragma omp scan inclusive(argc) #pragma omp scan inclusive(argc) // expected-note 2 {{previous 'scan' directive used here}}
case 1: case 1:
#pragma omp scan inclusive(argc) #pragma omp scan inclusive(argc) // expected-error {{exactly one 'scan' directive must appear in the loop body of an enclosing directive}}
break; break;
default: { default: {
#pragma omp scan inclusive(argc) #pragma omp scan inclusive(argc) // expected-error {{exactly one 'scan' directive must appear in the loop body of an enclosing directive}}
} break; } break;
} }
#pragma omp simd #pragma omp simd