diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 825dac9f14c86..8c2f8b2a942ff 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -4729,6 +4729,11 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( if (E) ImplicitFirstprivates.emplace_back(E); } + // OpenMP 5.0, 2.10.1 task Construct + // [detach clause]... The event-handle will be considered as if it was + // specified on a firstprivate clause. + if (auto *DC = dyn_cast(C)) + ImplicitFirstprivates.push_back(DC->getEventHandler()); } if (!ImplicitFirstprivates.empty()) { if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause( @@ -13432,7 +13437,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef VarList, ExprCaptures.push_back(Ref->getDecl()); } } - DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref); + if (!IsImplicitClause) + DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref); Vars.push_back((VD || CurContext->isDependentContext()) ? RefExpr->IgnoreParens() : Ref); @@ -17354,6 +17360,18 @@ OMPClause *Sema::ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc, << 1 << VD->getType() << Evt->getSourceRange(); return nullptr; } + // OpenMP 5.0, 2.10.1 task Construct + // [detach clause]... The event-handle will be considered as if it was + // specified on a firstprivate clause. + DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false); + if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate && + DVar.RefExpr) { + Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa) + << getOpenMPClauseName(DVar.CKind) + << getOpenMPClauseName(OMPC_firstprivate); + reportOriginalDsa(*this, DSAStack, VD, DVar); + return nullptr; + } } return new (Context) OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc); diff --git a/clang/test/AST/ast-dump-openmp-task.c b/clang/test/AST/ast-dump-openmp-task.c index e275d33285842..139524c378323 100644 --- a/clang/test/AST/ast-dump-openmp-task.c +++ b/clang/test/AST/ast-dump-openmp-task.c @@ -1,21 +1,27 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -ast-dump %s | FileCheck --match-full-lines -implicit-check-not=openmp_structured_block %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -fopenmp-version=50 -ast-dump %s | FileCheck --match-full-lines -implicit-check-not=openmp_structured_block %s +typedef unsigned long omp_event_handle_t; void test() { -#pragma omp task + omp_event_handle_t evt; +#pragma omp task detach(evt) ; } // CHECK: TranslationUnitDecl {{.*}} <> -// CHECK: `-FunctionDecl {{.*}} <{{.*}}ast-dump-openmp-task.c:3:1, line:6:1> line:3:6 test 'void ()' -// CHECK-NEXT: `-CompoundStmt {{.*}} -// CHECK-NEXT: `-OMPTaskDirective {{.*}} -// CHECK-NEXT: `-CapturedStmt {{.*}} +// CHECK: `-FunctionDecl {{.*}} line:4:6 test 'void ()' +// CHECK-NEXT: `-CompoundStmt {{.*}} +// CHECK: `-OMPTaskDirective {{.*}} +// CHECK-NEXT: |-OMPDetachClause {{.+}} +// CHECK-NEXT: | `-DeclRefExpr {{.+}} 'omp_event_handle_t':'unsigned long' lvalue Var {{.+}} 'evt' 'omp_event_handle_t':'unsigned long' +// CHECK-NEXT: |-OMPFirstprivateClause {{.+}} <> +// CHECK-NEXT: | `-DeclRefExpr {{.+}} 'omp_event_handle_t':'unsigned long' lvalue Var {{.+}} 'evt' 'omp_event_handle_t':'unsigned long' +// CHECK-NEXT: `-CapturedStmt {{.*}} // CHECK-NEXT: `-CapturedDecl {{.*}} <> nothrow // CHECK-NEXT: |-NullStmt {{.*}} // CHECK-NEXT: |-AlwaysInlineAttr {{.*}} <> Implicit __forceinline -// CHECK-NEXT: |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int' +// CHECK-NEXT: |-ImplicitParamDecl {{.*}} col:1 implicit .global_tid. 'const int' // CHECK-NEXT: |-ImplicitParamDecl {{.*}} col:1 implicit .part_id. 'const int *const restrict' // CHECK-NEXT: |-ImplicitParamDecl {{.*}} col:1 implicit .privates. 'void *const restrict' // CHECK-NEXT: |-ImplicitParamDecl {{.*}} col:1 implicit .copy_fn. 'void (*const restrict)(void *const restrict, ...)' // CHECK-NEXT: |-ImplicitParamDecl {{.*}} col:1 implicit .task_t. 'void *const' -// CHECK-NEXT: `-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (anonymous at {{.*}}ast-dump-openmp-task.c:4:1) *const restrict' +// CHECK-NEXT: `-ImplicitParamDecl {{.*}} col:1 implicit __context 'struct (anonymous at {{.*}}ast-dump-openmp-task.c:6:1) *const restrict' diff --git a/clang/test/OpenMP/task_messages.cpp b/clang/test/OpenMP/task_messages.cpp index cec3bc0c19802..ccead84775734 100644 --- a/clang/test/OpenMP/task_messages.cpp +++ b/clang/test/OpenMP/task_messages.cpp @@ -1,8 +1,8 @@ -// RUN: %clang_cc1 -verify=expected,omp45 -fopenmp-version=45 -fopenmp -ferror-limit 100 -std=c++11 -o - %s -Wuninitialized -// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-version=50 -fopenmp -ferror-limit 100 -std=c++11 -o - %s -Wuninitialized +// RUN: %clang_cc1 -verify=expected,omp45 -fopenmp-version=45 -fopenmp -ferror-limit 200 -std=c++11 -o - %s -Wuninitialized +// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-version=50 -fopenmp -ferror-limit 200 -std=c++11 -o - %s -Wuninitialized -// RUN: %clang_cc1 -verify=expected,omp45 -fopenmp-version=45 -fopenmp-simd -ferror-limit 100 -std=c++11 -o - %s -Wuninitialized -// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-version=50 -fopenmp-simd -ferror-limit 100 -std=c++11 -o - %s -Wuninitialized +// RUN: %clang_cc1 -verify=expected,omp45 -fopenmp-version=45 -fopenmp-simd -ferror-limit 200 -std=c++11 -o - %s -Wuninitialized +// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-version=50 -fopenmp-simd -ferror-limit 200 -std=c++11 -o - %s -Wuninitialized void xxx(int argc) { int x; // expected-note {{initialize the variable 'x' to silence this warning}} @@ -147,6 +147,9 @@ int foo() { #pragma omp task mergeable detach(evt) // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} omp50-error {{'detach' and 'mergeable' clause are mutually exclusive and may not appear on the same directive}} omp50-note {{'mergeable' clause is specified here}} #pragma omp task detach(-evt) // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} omp50-error {{expected variable of the 'omp_event_handle_t' type}} ; +#pragma omp task detach(evt) shared(evt) // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} +#pragma omp task detach(evt) firstprivate(evt) // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} + ; return a + b; } @@ -327,6 +330,9 @@ int main(int argc, char **argv) { #pragma omp task mergeable detach(evt) // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} omp50-error {{'detach' and 'mergeable' clause are mutually exclusive and may not appear on the same directive}} omp50-note {{'mergeable' clause is specified here}} #pragma omp task detach(-evt) // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} omp50-error {{expected variable of the 'omp_event_handle_t' type}} ; +#pragma omp task detach(evt) shared(evt) // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} +#pragma omp task detach(evt) firstprivate(evt) // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} + ; // expected-note@+2 {{in instantiation of function template specialization 'foo' requested here}} // expected-note@+1 {{in instantiation of function template specialization 'foo' requested here}} return foo() + foo();