From 95b64a982694b183890d902bc5cc76827fb09679 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Tue, 30 May 2017 16:00:04 +0000 Subject: [PATCH] [OPENMP] Allow 'use_device_ptr' clause in 'target data' alone. According to OpenMP 5.0 at least one 'map' or 'use_device_ptr' clause must be specified for 'target data' construct. Patch adds support for this feature. llvm-svn: 304216 --- .../clang/Basic/DiagnosticSemaKinds.td | 4 +- clang/lib/Sema/SemaOpenMP.cpp | 43 +++++++++---------- clang/test/OpenMP/target_data_messages.c | 2 +- .../OpenMP/target_enter_data_map_messages.c | 2 +- .../target_enter_data_nowait_messages.cpp | 2 +- .../OpenMP/target_exit_data_map_messages.c | 2 +- .../target_exit_data_nowait_messages.cpp | 2 +- clang/test/OpenMP/target_map_messages.cpp | 2 +- .../test/OpenMP/target_teams_map_messages.cpp | 2 +- 9 files changed, 29 insertions(+), 32 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index f86874dee714..629e8b837f59 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -8749,8 +8749,8 @@ def err_omp_not_mappable_type : Error< "type %0 is not mappable to target">; def err_omp_invalid_map_type_for_directive : Error< "%select{map type '%1' is not allowed|map type must be specified}0 for '#pragma omp %2'">; -def err_omp_no_map_for_directive : Error< - "expected at least one map clause for '#pragma omp %0'">; +def err_omp_no_clause_for_directive : Error< + "expected at least one %0 clause for '#pragma omp %1'">; def note_omp_polymorphic_in_target : Note< "mappable type cannot be polymorphic">; def note_omp_static_member_in_target : Note< diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 43fd055bbc56..2b7733d2adbd 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -5929,16 +5929,17 @@ StmtResult Sema::ActOnOpenMPTargetParallelForDirective( B, DSAStack->isCancelRegion()); } -/// \brief Check for existence of a map clause in the list of clauses. -static bool HasMapClause(ArrayRef Clauses) { - for (ArrayRef::iterator I = Clauses.begin(), E = Clauses.end(); - I != E; ++I) { - if (*I != nullptr && (*I)->getClauseKind() == OMPC_map) { - return true; - } - } +/// Check for existence of a map clause in the list of clauses. +static bool hasClauses(ArrayRef Clauses, + const OpenMPClauseKind K) { + return llvm::any_of( + Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; }); +} - return false; +template +static bool hasClauses(ArrayRef Clauses, const OpenMPClauseKind K, + const Params... ClauseTypes) { + return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...); } StmtResult Sema::ActOnOpenMPTargetDataDirective(ArrayRef Clauses, @@ -5952,8 +5953,9 @@ StmtResult Sema::ActOnOpenMPTargetDataDirective(ArrayRef Clauses, // OpenMP [2.10.1, Restrictions, p. 97] // At least one map clause must appear on the directive. - if (!HasMapClause(Clauses)) { - Diag(StartLoc, diag::err_omp_no_map_for_directive) + if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr)) { + Diag(StartLoc, diag::err_omp_no_clause_for_directive) + << "'map' or 'use_device_ptr'" << getOpenMPDirectiveName(OMPD_target_data); return StmtError(); } @@ -5970,9 +5972,9 @@ Sema::ActOnOpenMPTargetEnterDataDirective(ArrayRef Clauses, SourceLocation EndLoc) { // OpenMP [2.10.2, Restrictions, p. 99] // At least one map clause must appear on the directive. - if (!HasMapClause(Clauses)) { - Diag(StartLoc, diag::err_omp_no_map_for_directive) - << getOpenMPDirectiveName(OMPD_target_enter_data); + if (!hasClauses(Clauses, OMPC_map)) { + Diag(StartLoc, diag::err_omp_no_clause_for_directive) + << "'map'" << getOpenMPDirectiveName(OMPD_target_enter_data); return StmtError(); } @@ -5986,9 +5988,9 @@ Sema::ActOnOpenMPTargetExitDataDirective(ArrayRef Clauses, SourceLocation EndLoc) { // OpenMP [2.10.3, Restrictions, p. 102] // At least one map clause must appear on the directive. - if (!HasMapClause(Clauses)) { - Diag(StartLoc, diag::err_omp_no_map_for_directive) - << getOpenMPDirectiveName(OMPD_target_exit_data); + if (!hasClauses(Clauses, OMPC_map)) { + Diag(StartLoc, diag::err_omp_no_clause_for_directive) + << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data); return StmtError(); } @@ -5998,12 +6000,7 @@ Sema::ActOnOpenMPTargetExitDataDirective(ArrayRef Clauses, StmtResult Sema::ActOnOpenMPTargetUpdateDirective(ArrayRef Clauses, SourceLocation StartLoc, SourceLocation EndLoc) { - bool seenMotionClause = false; - for (auto *C : Clauses) { - if (C->getClauseKind() == OMPC_to || C->getClauseKind() == OMPC_from) - seenMotionClause = true; - } - if (!seenMotionClause) { + if (!hasClauses(Clauses, OMPC_to, OMPC_from)) { Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required); return StmtError(); } diff --git a/clang/test/OpenMP/target_data_messages.c b/clang/test/OpenMP/target_data_messages.c index 153b4377290c..fd41e7df2a4c 100644 --- a/clang/test/OpenMP/target_data_messages.c +++ b/clang/test/OpenMP/target_data_messages.c @@ -4,7 +4,7 @@ void foo() { } int main(int argc, char **argv) { int a; - #pragma omp target data // expected-error {{expected at least one map clause for '#pragma omp target data'}} + #pragma omp target data // expected-error {{expected at least one 'map' or 'use_device_ptr' clause for '#pragma omp target data'}} {} L1: foo(); diff --git a/clang/test/OpenMP/target_enter_data_map_messages.c b/clang/test/OpenMP/target_enter_data_map_messages.c index 6f5aad1ef650..8a7de3b96eff 100644 --- a/clang/test/OpenMP/target_enter_data_map_messages.c +++ b/clang/test/OpenMP/target_enter_data_map_messages.c @@ -4,7 +4,7 @@ int main(int argc, char **argv) { int r; - #pragma omp target enter data // expected-error {{expected at least one map clause for '#pragma omp target enter data'}} + #pragma omp target enter data // expected-error {{expected at least one 'map' clause for '#pragma omp target enter data'}} #pragma omp target enter data map(r) // expected-error {{map type must be specified for '#pragma omp target enter data'}} #pragma omp target enter data map(tofrom: r) // expected-error {{map type 'tofrom' is not allowed for '#pragma omp target enter data'}} diff --git a/clang/test/OpenMP/target_enter_data_nowait_messages.cpp b/clang/test/OpenMP/target_enter_data_nowait_messages.cpp index e682e8c47d70..508b1b254906 100644 --- a/clang/test/OpenMP/target_enter_data_nowait_messages.cpp +++ b/clang/test/OpenMP/target_enter_data_nowait_messages.cpp @@ -6,7 +6,7 @@ int main(int argc, char **argv) { #pragma omp nowait target enter data map(to: i) // expected-error {{expected an OpenMP directive}} #pragma omp target nowait enter data map(to: i) // expected-warning {{extra tokens at the end of '#pragma omp target' are ignored}} #pragma omp target enter nowait data map(to: i) // expected-error {{expected an OpenMP directive}} - #pragma omp target enter data nowait() map(to: i) // expected-warning {{extra tokens at the end of '#pragma omp target enter data' are ignored}} expected-error {{expected at least one map clause for '#pragma omp target enter data'}} + #pragma omp target enter data nowait() map(to: i) // expected-warning {{extra tokens at the end of '#pragma omp target enter data' are ignored}} expected-error {{expected at least one 'map' clause for '#pragma omp target enter data'}} #pragma omp target enter data map(to: i) nowait( // expected-warning {{extra tokens at the end of '#pragma omp target enter data' are ignored}} #pragma omp target enter data map(to: i) nowait (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target enter data' are ignored}} #pragma omp target enter data map(to: i) nowait device (-10u) diff --git a/clang/test/OpenMP/target_exit_data_map_messages.c b/clang/test/OpenMP/target_exit_data_map_messages.c index a9953fbbb4c6..84bd7e79fd03 100644 --- a/clang/test/OpenMP/target_exit_data_map_messages.c +++ b/clang/test/OpenMP/target_exit_data_map_messages.c @@ -4,7 +4,7 @@ int main(int argc, char **argv) { int r; - #pragma omp target exit data // expected-error {{expected at least one map clause for '#pragma omp target exit data'}} + #pragma omp target exit data // expected-error {{expected at least one 'map' clause for '#pragma omp target exit data'}} #pragma omp target exit data map(r) // expected-error {{map type must be specified for '#pragma omp target exit data'}} #pragma omp target exit data map(tofrom: r) // expected-error {{map type 'tofrom' is not allowed for '#pragma omp target exit data'}} diff --git a/clang/test/OpenMP/target_exit_data_nowait_messages.cpp b/clang/test/OpenMP/target_exit_data_nowait_messages.cpp index cd743d89278e..d0286031f362 100644 --- a/clang/test/OpenMP/target_exit_data_nowait_messages.cpp +++ b/clang/test/OpenMP/target_exit_data_nowait_messages.cpp @@ -6,7 +6,7 @@ int main(int argc, char **argv) { #pragma omp nowait target exit data map(from: i) // expected-error {{expected an OpenMP directive}} #pragma omp target nowait exit data map(from: i) // expected-warning {{extra tokens at the end of '#pragma omp target' are ignored}} #pragma omp target exit nowait data map(from: i) // expected-error {{expected an OpenMP directive}} - #pragma omp target exit data nowait() map(from: i) // expected-warning {{extra tokens at the end of '#pragma omp target exit data' are ignored}} expected-error {{expected at least one map clause for '#pragma omp target exit data'}} + #pragma omp target exit data nowait() map(from: i) // expected-warning {{extra tokens at the end of '#pragma omp target exit data' are ignored}} expected-error {{expected at least one 'map' clause for '#pragma omp target exit data'}} #pragma omp target exit data map(from: i) nowait( // expected-warning {{extra tokens at the end of '#pragma omp target exit data' are ignored}} #pragma omp target exit data map(from: i) nowait (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target exit data' are ignored}} #pragma omp target exit data map(from: i) nowait device (-10u) diff --git a/clang/test/OpenMP/target_map_messages.cpp b/clang/test/OpenMP/target_map_messages.cpp index 9d166ae9a1d9..b9640b965d50 100644 --- a/clang/test/OpenMP/target_map_messages.cpp +++ b/clang/test/OpenMP/target_map_messages.cpp @@ -467,7 +467,7 @@ int main(int argc, char **argv) { int y; int to, tofrom, always; const int (&l)[5] = da; -#pragma omp target data map // expected-error {{expected '(' after 'map'}} expected-error {{expected at least one map clause for '#pragma omp target data'}} +#pragma omp target data map // expected-error {{expected '(' after 'map'}} expected-error {{expected at least one 'map' or 'use_device_ptr' clause for '#pragma omp target data'}} #pragma omp target data map( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} #pragma omp target data map() // expected-error {{expected expression}} #pragma omp target data map(alloc) // expected-error {{use of undeclared identifier 'alloc'}} diff --git a/clang/test/OpenMP/target_teams_map_messages.cpp b/clang/test/OpenMP/target_teams_map_messages.cpp index 15839b848532..89425d622c10 100644 --- a/clang/test/OpenMP/target_teams_map_messages.cpp +++ b/clang/test/OpenMP/target_teams_map_messages.cpp @@ -464,7 +464,7 @@ int main(int argc, char **argv) { int y; int to, tofrom, always; const int (&l)[5] = da; -#pragma omp target data map // expected-error {{expected '(' after 'map'}} expected-error {{expected at least one map clause for '#pragma omp target data'}} +#pragma omp target data map // expected-error {{expected '(' after 'map'}} expected-error {{expected at least one 'map' or 'use_device_ptr' clause for '#pragma omp target data'}} #pragma omp target data map( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} #pragma omp target data map() // expected-error {{expected expression}} #pragma omp target data map(alloc) // expected-error {{use of undeclared identifier 'alloc'}}