diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9937,10 +9937,10 @@ "cannot nest 'critical' regions having the same name %0">; def note_omp_previous_critical_region : Note< "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_several_directives_in_region : Error< + "exactly one '%0' directive must appear in the loop body of an enclosing directive">; +def note_omp_previous_directive : Note< + "previous '%0' directive used here">; def err_omp_sections_not_compound_stmt : Error< "the statement for '#pragma omp sections' must be a compound statement">; def err_omp_parallel_sections_not_compound_stmt : Error< diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -169,6 +169,7 @@ bool LoopStart = false; bool BodyComplete = false; SourceLocation PrevScanLocation; + SourceLocation PrevOrderedLocation; SourceLocation InnerTeamsRegionLoc; /// Reference to the taskgroup task_reduction reference expression. Expr *TaskgroupReductionRef = nullptr; @@ -848,6 +849,21 @@ const SharingMapTy *Top = getSecondOnStackOrNull(); return Top ? Top->PrevScanLocation : SourceLocation(); } + /// Mark that parent region already has ordered directive. + void setParentHasOrderedDirective(SourceLocation Loc) { + if (SharingMapTy *Parent = getSecondOnStackOrNull()) + Parent->PrevOrderedLocation = Loc; + } + /// Return true if current region has inner ordered construct. + bool doesParentHasOrderedDirective() const { + const SharingMapTy *Top = getSecondOnStackOrNull(); + return Top ? Top->PrevOrderedLocation.isValid() : false; + } + /// Returns the location of the previously specified ordered directive. + SourceLocation getParentOrderedDirectiveLoc() const { + const SharingMapTy *Top = getSecondOnStackOrNull(); + return Top ? Top->PrevOrderedLocation : SourceLocation(); + } /// Set collapse value for the region. void setAssociatedLoops(unsigned Val) { @@ -9187,9 +9203,10 @@ // 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(StartLoc, diag::err_omp_several_directives_in_region) << "scan"; Diag(DSAStack->getParentScanDirectiveLoc(), - diag::note_omp_previous_scan_directive); + diag::note_omp_previous_directive) + << "scan"; return StmtError(); } DSAStack->setParentHasScanDirective(StartLoc); @@ -9265,6 +9282,22 @@ if ((!AStmt && !DependFound) || ErrorFound) return StmtError(); + // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions. + // During execution of an iteration of a worksharing-loop or a loop nest + // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread + // must not execute more than one ordered region corresponding to an ordered + // construct without a depend clause. + if (!DependFound) { + if (DSAStack->doesParentHasOrderedDirective()) { + Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered"; + Diag(DSAStack->getParentOrderedDirectiveLoc(), + diag::note_omp_previous_directive) + << "ordered"; + return StmtError(); + } + DSAStack->setParentHasOrderedDirective(StartLoc); + } + if (AStmt) { assert(isa(AStmt) && "Captured statement expected"); diff --git a/clang/test/OpenMP/ordered_messages.cpp b/clang/test/OpenMP/ordered_messages.cpp --- a/clang/test/OpenMP/ordered_messages.cpp +++ b/clang/test/OpenMP/ordered_messages.cpp @@ -61,6 +61,17 @@ foo(); } } + #pragma omp for ordered + for (int i = 0; i < 10; ++i) { + #pragma omp ordered // expected-note {{previous 'ordered' directive used here}} + { + foo(); + } + #pragma omp ordered // expected-error {{exactly one 'ordered' directive must appear in the loop body of an enclosing directive}} + { + foo(); + } + } #pragma omp ordered simd simd // expected-error {{directive '#pragma omp ordered' cannot contain more than one 'simd' clause}} { foo(); @@ -79,7 +90,18 @@ foo(); } } - #pragma omp for simd + #pragma omp simd + for (int i = 0; i < 10; ++i) { +#pragma omp ordered simd // expected-note {{previous 'ordered' directive used here}} + { + foo(); + } +#pragma omp ordered simd // expected-error {{exactly one 'ordered' directive must appear in the loop body of an enclosing directive}} + { + foo(); + } + } +#pragma omp for simd for (int i = 0; i < 10; ++i) { #pragma omp ordered // expected-error {{OpenMP constructs may not be nested inside a simd region}} {