diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h --- a/clang/include/clang/AST/OpenMPClause.h +++ b/clang/include/clang/AST/OpenMPClause.h @@ -1139,6 +1139,62 @@ } }; +/// New Work in progress +class OMPOtherWiseClause final : public OMPClause { + friend class OMPClauseReader; + + Stmt *Directive; + + /// Location of '('. + SourceLocation LParenLoc; + +public: + + OMPOtherWiseClause (Stmt *D, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : OMPClause(llvm::omp::OMPC_otherwise, StartLoc, EndLoc), + Directive(D), LParenLoc(LParenLoc) {} + + /// Build an empty clause. + OMPOtherWiseClause() + : OMPClause(llvm::omp::OMPC_otherwise, SourceLocation(), SourceLocation()) { + } + + /// Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + + /// Returns the location of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// Returns the associated OpenMP directive + Stmt *getDirective() const { return Directive; } + + /// Set the associated OpenMP directive + void setDirective(Stmt *S) { Directive = S; } + + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == llvm::omp::OMPC_otherwise; + } + +}; + +/// New work in progress here + /// This represents 'default' clause in the '#pragma omp ...' directive. /// /// \code 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 @@ -11229,6 +11229,11 @@ OMPClause *ActOnOpenMPWhenClause(OMPTraitInfo &TI, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); + /// Called on well-formed 'otherwise' clause. + OMPClause *ActOnOpenMPOtherWiseClause(StmtResult Directive, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'default' clause. OMPClause *ActOnOpenMPDefaultClause(llvm::omp::DefaultKind Kind, SourceLocation KindLoc, diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -201,6 +201,7 @@ case OMPC_uses_allocators: case OMPC_affinity: case OMPC_when: + case OMPC_otherwise: case OMPC_append_args: break; default: @@ -467,6 +468,7 @@ case OMPC_uses_allocators: case OMPC_affinity: case OMPC_when: + case OMPC_otherwise: case OMPC_append_args: break; default: diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -6081,6 +6081,7 @@ bool IsXLHSInRHSPart, bool IsCompareCapture, SourceLocation Loc) { switch (Kind) { + case OMPC_otherwise: case OMPC_read: emitOMPAtomicReadExpr(CGF, AO, X, V, Loc); break; diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -2486,12 +2486,6 @@ DeclarationNameInfo DirName; StmtResult Directive = StmtError(); bool HasAssociatedStatement = true; - - // - if (DKind == OMPD_target){ - llvm::errs() << " We have target " << PP.getSpelling(Tok) << "\n"; - } else {llvm::errs() << " We have " << PP.getSpelling(Tok) << "\n";} - // switch (DKind) { case OMPD_metadirective: { @@ -2835,7 +2829,6 @@ // If we are parsing for a directive within a metadirective, the directive // ends with a ')'. if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) { - llvm::errs() << "We are reading meta directive\n"; while (Tok.isNot(tok::annot_pragma_openmp_end)) ConsumeAnyToken(); break; diff --git a/clang/test/OpenMP/metadirective_otherwise_ast_print.c b/clang/test/OpenMP/metadirective_otherwise_ast_print.c new file mode 100644 --- /dev/null +++ b/clang/test/OpenMP/metadirective_otherwise_ast_print.c @@ -0,0 +1,87 @@ +// RUN: %clang_cc1 -verify -fopenmp -triple x86_64-unknown-linux-gnu -x c -std=c99 -ast-print %s -o - | FileCheck %s + +// RUN: %clang_cc1 -verify -fopenmp-simd -triple x86_64-unknown-linux-gnu -x c -std=c99 -ast-print %s -o - | FileCheck %s +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER + +void bar(void); + +#define N 10 +void foo(void) { +#pragma omp metadirective when(device = {kind(cpu)} \ + : parallel) otherwise() + bar(); +#pragma omp metadirective when(implementation = {vendor(score(0) \ + : llvm)}, \ + device = {kind(cpu)} \ + : parallel) otherwise (target teams) + bar(); +#pragma omp metadirective when(device = {kind(gpu)} \ + : target teams) when(implementation = {vendor(llvm)} \ + : parallel) otherwise () + bar(); +#pragma omp metadirective otherwise (target) when(implementation = {vendor(score(5) \ + : llvm)}, \ + device = {kind(cpu, host)} \ + : parallel) + bar(); +#pragma omp metadirective when(user = {condition(N > 10)} \ + : target) when(user = {condition(N == 10)} \ + : parallel) + bar(); +#pragma omp metadirective when(device = {kind(host)} \ + : parallel for) + for (int i = 0; i < 100; i++) + ; +#pragma omp metadirective when(implementation = {extension(match_all)} \ + : parallel) otherwise(parallel for) + for (int i = 0; i < 100; i++) + ; +#pragma omp metadirective when(implementation = {extension(match_any)} \ + : parallel) otherwise(parallel for) + for (int i = 0; i < 100; i++) + ; +#pragma omp metadirective when(implementation = {extension(match_none)} \ + : parallel) otherwise(parallel for) + for (int i = 0; i < 100; i++) + ; + +// Test metadirective with nested OpenMP directive. + int array[16]; + #pragma omp metadirective when(user = {condition(1)} \ + : parallel for) + for (int i = 0; i < 16; i++) { + #pragma omp simd + for (int j = 0; j < 16; j++) + array[i] = i; + } +} + +// CHECK: void bar(void); +// CHECK: void foo(void) +// CHECK-NEXT: #pragma omp parallel +// CHECK-NEXT: bar() +// CHECK-NEXT: #pragma omp parallel +// CHECK-NEXT: bar() +// CHECK-NEXT: #pragma omp parallel +// CHECK-NEXT: bar() +// CHECK-NEXT: #pragma omp parallel +// CHECK-NEXT: bar() +// CHECK-NEXT: #pragma omp parallel +// CHECK-NEXT: bar() +// CHECK-NEXT: #pragma omp parallel for +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK: #pragma omp parallel +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK: #pragma omp parallel for +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK: #pragma omp parallel +// CHECK-NEXT: for (int i = 0; i < 100; i++) +// CHECK: #pragma omp parallel for +// CHECK-NEXT: for (int i = 0; i < 16; i++) { +// CHECK-NEXT: #pragma omp simd +// CHECK-NEXT: for (int j = 0; j < 16; j++) + +#endif diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td --- a/llvm/include/llvm/Frontend/OpenMP/OMP.td +++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td @@ -367,7 +367,12 @@ def OMPC_Align : Clause<"align"> { let clangClass = "OMPAlignClause"; } -def OMPC_When: Clause<"when"> {} +def OMPC_When: Clause<"when"> { + //let clangClass = "OMPWhenClause"; +} + +def OMPC_Otherwise: Clause<"otherwise">{} + def OMPC_Bind : Clause<"bind"> { let clangClass = "OMPBindClause"; @@ -1858,6 +1863,7 @@ def OMP_Metadirective : Directive<"metadirective"> { let allowedClauses = [VersionedClause]; let allowedOnceClauses = [VersionedClause]; + let allowedOnceClauses = [VersionedClause]; } def OMP_Unknown : Directive<"unknown"> { let isDefault = true;