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 @@ -10781,6 +10781,8 @@ def err_omp_unroll_full_variable_trip_count : Error< "loop to be fully unrolled must have a constant trip count">; def note_omp_directive_here : Note<"'%0' directive found here">; +def err_openmp_vla_in_task_untied : Error< + "variable length arrays are not supported in OpenMP tasking regions with 'untied' clause">; } // end of OpenMP category let CategoryName = "Related Result Type Issue" in { diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -10542,6 +10542,10 @@ void finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, const FunctionDecl *Callee, SourceLocation Loc); + + /// Return true if currently in OpenMP task with untied clause context. + bool isInOpenMPTaskUntiedContext() const; + /// Return true inside OpenMP declare target region. bool isInOpenMPDeclareTargetContext() const { return !DeclareTargetNesting.empty(); 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 @@ -174,6 +174,7 @@ bool HasMutipleLoops = false; const Decl *PossiblyLoopCounter = nullptr; bool NowaitRegion = false; + bool UntiedRegion = false; bool CancelRegion = false; bool LoopStart = false; bool BodyComplete = false; @@ -841,6 +842,15 @@ return Parent->NowaitRegion; return false; } + /// Marks current region as untied (it has a 'untied' clause). + void setUntiedRegion(bool IsUntied = true) { + getTopOfStack().UntiedRegion = IsUntied; + } + /// Return true if current region is untied. + bool isUntiedRegion() const { + const SharingMapTy *Top = getTopOfStackOrNull(); + return Top ? Top->UntiedRegion : false; + } /// Marks parent region as cancel region. void setParentCancelRegion(bool Cancel = true) { if (SharingMapTy *Parent = getSecondOnStackOrNull()) @@ -2154,6 +2164,11 @@ return DSAStack->getNestingLevel(); } +bool Sema::isInOpenMPTaskUntiedContext() const { + return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) && + DSAStack->isUntiedRegion(); +} + bool Sema::isInOpenMPTargetExecutionDirective() const { return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) && !DSAStack->isClauseParsingMode()) || @@ -15046,6 +15061,7 @@ OMPClause *Sema::ActOnOpenMPUntiedClause(SourceLocation StartLoc, SourceLocation EndLoc) { + DSAStack->setUntiedRegion(); return new (Context) OMPUntiedClause(StartLoc, EndLoc); } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -2443,6 +2443,9 @@ } else if (isSFINAEContext()) { VLADiag = diag::err_vla_in_sfinae; VLAIsError = true; + } else if (getLangOpts().OpenMP && isInOpenMPTaskUntiedContext()) { + VLADiag = diag::err_openmp_vla_in_task_untied; + VLAIsError = true; } else { VLADiag = diag::ext_vla; VLAIsError = false; diff --git a/clang/test/OpenMP/task_messages.cpp b/clang/test/OpenMP/task_messages.cpp --- a/clang/test/OpenMP/task_messages.cpp +++ b/clang/test/OpenMP/task_messages.cpp @@ -173,7 +173,7 @@ int &b = a; S sa; S &sb = sa; - int r; + int r; // expected-note {{declared here}} #pragma omp task { // expected-warning {{extra tokens at the end of '#pragma omp task' are ignored}} foo(); #pragma omp task( // expected-warning {{extra tokens at the end of '#pragma omp task' are ignored}} @@ -330,6 +330,12 @@ // expected-error@+1 {{directive '#pragma omp task' cannot contain more than one 'mergeable' clause}} #pragma omp task mergeable mergeable ++r; +// expected-error@+4 {{variable length arrays are not supported in OpenMP tasking regions with 'untied' clause}} +// expected-note@+3 {{read of non-const variable 'r' is not allowed in a constant expression}} +#pragma omp task untied + { + int array[r]; + } volatile omp_event_handle_t evt; omp_event_handle_t sevt; const omp_event_handle_t cevt = evt; diff --git a/clang/test/OpenMP/taskloop_loop_messages.cpp b/clang/test/OpenMP/taskloop_loop_messages.cpp --- a/clang/test/OpenMP/taskloop_loop_messages.cpp +++ b/clang/test/OpenMP/taskloop_loop_messages.cpp @@ -691,7 +691,7 @@ void test_loop_eh() { const int N = 100; - float a[N], b[N], c[N]; + float a[N], b[N], c[N]; // expected-note {{declared here}} #pragma omp parallel #pragma omp taskloop for (int i = 0; i < 10; i++) { @@ -729,6 +729,13 @@ void g() { throw 0; } }; } +// expected-error@+5 {{variable length arrays are not supported in OpenMP tasking regions with 'untied' clause}} +// expected-note@+4 {{read of non-constexpr variable 'c' is not allowed in a constant expression}} +#pragma omp taskloop untied + { + for (int i = 0; i < 10; ++i) + int array[(int)c[0]]; + } } void test_loop_firstprivate_lastprivate() {