Index: clang/include/clang-c/Index.h =================================================================== --- clang/include/clang-c/Index.h +++ clang/include/clang-c/Index.h @@ -2626,7 +2626,11 @@ */ CXCursor_OMPTargetParallelGenericLoopDirective = 299, - CXCursor_LastStmt = CXCursor_OMPTargetParallelGenericLoopDirective, + /** OpenMP parallel masked directive. + */ + CXCursor_OMPParallelMaskedDirective = 300, + + CXCursor_LastStmt = CXCursor_OMPParallelMaskedDirective, /** * Cursor that represents the translation unit itself. @@ -2634,7 +2638,7 @@ * The translation unit cursor exists primarily to act as the root * cursor for traversing the contents of a translation unit. */ - CXCursor_TranslationUnit = 300, + CXCursor_TranslationUnit = 350, /* Attributes */ CXCursor_FirstAttr = 400, Index: clang/include/clang/AST/RecursiveASTVisitor.h =================================================================== --- clang/include/clang/AST/RecursiveASTVisitor.h +++ clang/include/clang/AST/RecursiveASTVisitor.h @@ -2989,6 +2989,9 @@ DEF_TRAVERSE_STMT(OMPParallelMasterDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPParallelMaskedDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPParallelSectionsDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) Index: clang/include/clang/AST/StmtOpenMP.h =================================================================== --- clang/include/clang/AST/StmtOpenMP.h +++ clang/include/clang/AST/StmtOpenMP.h @@ -2304,6 +2304,69 @@ } }; +/// This represents '#pragma omp parallel masked' directive. +/// +/// \code +/// #pragma omp parallel masked filter(tid) +/// \endcode +/// In this example directive '#pragma omp parallel masked' has a clause +/// 'filter' with the variable tid +/// +class OMPParallelMaskedDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + friend class OMPExecutableDirective; + + OMPParallelMaskedDirective(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPExecutableDirective(OMPParallelMaskedDirectiveClass, + llvm::omp::OMPD_parallel_masked, StartLoc, + EndLoc) {} + + explicit OMPParallelMaskedDirective() + : OMPExecutableDirective(OMPParallelMaskedDirectiveClass, + llvm::omp::OMPD_parallel_masked, + SourceLocation(), SourceLocation()) {} + + /// Sets special task reduction descriptor. + void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; } + +public: + /// Creates directive with a list of \a Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param TaskRedRef Task reduction special reference expression to handle + /// taskgroup descriptor. + /// + static OMPParallelMaskedDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef); + + /// Creates an empty directive with the place for \a NumClauses + /// clauses. + /// + /// \param C AST context. + /// \param NumClauses Number of clauses. + /// + static OMPParallelMaskedDirective * + CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell); + + /// Returns special task reduction reference expression. + Expr *getTaskReductionRefExpr() { + return cast_or_null(Data->getChildren()[0]); + } + const Expr *getTaskReductionRefExpr() const { + return const_cast(this) + ->getTaskReductionRefExpr(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPParallelMaskedDirectiveClass; + } +}; + /// This represents '#pragma omp parallel sections' directive. /// /// \code Index: clang/include/clang/Basic/StmtNodes.td =================================================================== --- clang/include/clang/Basic/StmtNodes.td +++ clang/include/clang/Basic/StmtNodes.td @@ -282,6 +282,7 @@ def OMPInteropDirective : StmtNode; def OMPDispatchDirective : StmtNode; def OMPMaskedDirective : StmtNode; +def OMPParallelMaskedDirective : StmtNode; def OMPGenericLoopDirective : StmtNode; def OMPTeamsGenericLoopDirective : StmtNode; def OMPTargetTeamsGenericLoopDirective : StmtNode; Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -10906,6 +10906,12 @@ Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp parallel masked' after + /// parsing of the associated statement. + StmtResult ActOnOpenMPParallelMaskedDirective(ArrayRef Clauses, + Stmt *AStmt, + SourceLocation StartLoc, + SourceLocation EndLoc); /// Called on well-formed '\#pragma omp parallel sections' after /// parsing of the associated statement. StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef Clauses, Index: clang/include/clang/Serialization/ASTBitCodes.h =================================================================== --- clang/include/clang/Serialization/ASTBitCodes.h +++ clang/include/clang/Serialization/ASTBitCodes.h @@ -1922,6 +1922,7 @@ STMT_OMP_PARALLEL_FOR_DIRECTIVE, STMT_OMP_PARALLEL_FOR_SIMD_DIRECTIVE, STMT_OMP_PARALLEL_MASTER_DIRECTIVE, + STMT_OMP_PARALLEL_MASKED_DIRECTIVE, STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE, STMT_OMP_TASK_DIRECTIVE, STMT_OMP_TASKYIELD_DIRECTIVE, Index: clang/lib/AST/StmtOpenMP.cpp =================================================================== --- clang/lib/AST/StmtOpenMP.cpp +++ clang/lib/AST/StmtOpenMP.cpp @@ -682,6 +682,22 @@ C, NumClauses, /*HasAssociatedStmt=*/true, /*NumChildren=*/1); } +OMPParallelMaskedDirective *OMPParallelMaskedDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef) { + auto *Dir = createDirective( + C, Clauses, AssociatedStmt, /*NumChildren=*/1, StartLoc, EndLoc); + Dir->setTaskReductionRefExpr(TaskRedRef); + return Dir; +} + +OMPParallelMaskedDirective * +OMPParallelMaskedDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell) { + return createEmptyDirective( + C, NumClauses, /*HasAssociatedStmt=*/true, /*NumChildren=*/1); +} + OMPParallelSectionsDirective *OMPParallelSectionsDirective::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, Index: clang/lib/AST/StmtPrinter.cpp =================================================================== --- clang/lib/AST/StmtPrinter.cpp +++ clang/lib/AST/StmtPrinter.cpp @@ -749,6 +749,12 @@ PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPParallelMaskedDirective( + OMPParallelMaskedDirective *Node) { + Indent() << "#pragma omp parallel masked"; + PrintOMPExecutableDirective(Node); +} + void StmtPrinter::VisitOMPParallelSectionsDirective( OMPParallelSectionsDirective *Node) { Indent() << "#pragma omp parallel sections"; Index: clang/lib/AST/StmtProfile.cpp =================================================================== --- clang/lib/AST/StmtProfile.cpp +++ clang/lib/AST/StmtProfile.cpp @@ -988,6 +988,11 @@ VisitOMPExecutableDirective(S); } +void StmtProfiler::VisitOMPParallelMaskedDirective( + const OMPParallelMaskedDirective *S) { + VisitOMPExecutableDirective(S); +} + void StmtProfiler::VisitOMPParallelSectionsDirective( const OMPParallelSectionsDirective *S) { VisitOMPExecutableDirective(S); Index: clang/lib/Basic/OpenMPKinds.cpp =================================================================== --- clang/lib/Basic/OpenMPKinds.cpp +++ clang/lib/Basic/OpenMPKinds.cpp @@ -535,7 +535,7 @@ DKind == OMPD_teams_distribute_parallel_for_simd || DKind == OMPD_target_teams_distribute_parallel_for || DKind == OMPD_target_teams_distribute_parallel_for_simd || - DKind == OMPD_parallel_master || + DKind == OMPD_parallel_master || DKind == OMPD_parallel_masked || DKind == OMPD_parallel_master_taskloop || DKind == OMPD_parallel_master_taskloop_simd || DKind == OMPD_parallel_loop || DKind == OMPD_target_parallel_loop; @@ -652,6 +652,7 @@ case OMPD_parallel_for: case OMPD_parallel_for_simd: case OMPD_parallel_master: + case OMPD_parallel_masked: case OMPD_parallel_sections: case OMPD_distribute_parallel_for: case OMPD_distribute_parallel_for_simd: Index: clang/lib/CodeGen/CGStmt.cpp =================================================================== --- clang/lib/CodeGen/CGStmt.cpp +++ clang/lib/CodeGen/CGStmt.cpp @@ -408,6 +408,9 @@ case Stmt::OMPTargetParallelGenericLoopDirectiveClass: llvm_unreachable("target parallel loop directive not supported yet."); break; + case Stmt::OMPParallelMaskedDirectiveClass: + llvm_unreachable("parallel masked directive not supported yet."); + break; } } Index: clang/lib/Parse/ParseOpenMP.cpp =================================================================== --- clang/lib/Parse/ParseOpenMP.cpp +++ clang/lib/Parse/ParseOpenMP.cpp @@ -180,6 +180,7 @@ {OMPD_master, OMPD_taskloop, OMPD_master_taskloop}, {OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd}, {OMPD_parallel, OMPD_master, OMPD_parallel_master}, + {OMPD_parallel, OMPD_masked, OMPD_parallel_masked}, {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop}, {OMPD_parallel_master_taskloop, OMPD_simd, OMPD_parallel_master_taskloop_simd}}; @@ -2367,6 +2368,7 @@ case OMPD_parallel_for_simd: case OMPD_parallel_sections: case OMPD_parallel_master: + case OMPD_parallel_masked: case OMPD_atomic: case OMPD_target: case OMPD_teams: @@ -2762,6 +2764,7 @@ case OMPD_parallel_for_simd: case OMPD_parallel_sections: case OMPD_parallel_master: + case OMPD_parallel_masked: case OMPD_task: case OMPD_ordered: case OMPD_atomic: Index: clang/lib/Sema/SemaExceptionSpec.cpp =================================================================== --- clang/lib/Sema/SemaExceptionSpec.cpp +++ clang/lib/Sema/SemaExceptionSpec.cpp @@ -1460,6 +1460,7 @@ case Stmt::OMPParallelForDirectiveClass: case Stmt::OMPParallelForSimdDirectiveClass: case Stmt::OMPParallelMasterDirectiveClass: + case Stmt::OMPParallelMaskedDirectiveClass: case Stmt::OMPParallelMasterTaskLoopDirectiveClass: case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass: case Stmt::OMPParallelSectionsDirectiveClass: Index: clang/lib/Sema/SemaOpenMP.cpp =================================================================== --- clang/lib/Sema/SemaOpenMP.cpp +++ clang/lib/Sema/SemaOpenMP.cpp @@ -3971,6 +3971,7 @@ case OMPD_parallel_for_simd: case OMPD_parallel_sections: case OMPD_parallel_master: + case OMPD_parallel_masked: case OMPD_parallel_loop: case OMPD_teams: case OMPD_teams_distribute: @@ -6116,6 +6117,11 @@ StartLoc, EndLoc); AllowedNameModifiers.push_back(OMPD_parallel); break; + case OMPD_parallel_masked: + Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt, + StartLoc, EndLoc); + AllowedNameModifiers.push_back(OMPD_parallel); + break; case OMPD_parallel_sections: Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); @@ -10697,6 +10703,29 @@ DSAStack->getTaskgroupReductionRef()); } +StmtResult +Sema::ActOnOpenMPParallelMaskedDirective(ArrayRef Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc) { + if (!AStmt) + return StmtError(); + + assert(isa(AStmt) && "Captured statement expected"); + auto *CS = cast(AStmt); + // 1.2.2 OpenMP Language Terminology + // Structured block - An executable statement with a single entry at the + // top and a single exit at the bottom. + // The point of exit cannot be a branch out of the structured block. + // longjmp() and throw() must not violate the entry/exit criteria. + CS->getCapturedDecl()->setNothrow(); + + setFunctionHasBranchProtectedScope(); + + return OMPParallelMaskedDirective::Create( + Context, StartLoc, EndLoc, Clauses, AStmt, + DSAStack->getTaskgroupReductionRef()); +} + StmtResult Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, @@ -14808,6 +14837,7 @@ case OMPD_cancel: case OMPD_parallel: case OMPD_parallel_master: + case OMPD_parallel_masked: case OMPD_parallel_sections: case OMPD_parallel_for: case OMPD_parallel_loop: @@ -14883,6 +14913,7 @@ break; case OMPD_parallel: case OMPD_parallel_master: + case OMPD_parallel_masked: case OMPD_parallel_sections: case OMPD_parallel_for: case OMPD_parallel_for_simd: @@ -14989,6 +15020,7 @@ case OMPD_cancel: case OMPD_parallel: case OMPD_parallel_master: + case OMPD_parallel_masked: case OMPD_parallel_sections: case OMPD_parallel_for: case OMPD_parallel_for_simd: @@ -15075,6 +15107,7 @@ case OMPD_cancel: case OMPD_parallel: case OMPD_parallel_master: + case OMPD_parallel_masked: case OMPD_parallel_sections: case OMPD_parallel_for: case OMPD_parallel_for_simd: @@ -15167,6 +15200,7 @@ case OMPD_cancel: case OMPD_parallel: case OMPD_parallel_master: + case OMPD_parallel_masked: case OMPD_parallel_sections: case OMPD_threadprivate: case OMPD_allocate: @@ -15253,6 +15287,7 @@ case OMPD_cancel: case OMPD_parallel: case OMPD_parallel_master: + case OMPD_parallel_masked: case OMPD_parallel_sections: case OMPD_threadprivate: case OMPD_allocate: @@ -15340,6 +15375,7 @@ case OMPD_cancel: case OMPD_parallel: case OMPD_parallel_master: + case OMPD_parallel_masked: case OMPD_parallel_sections: case OMPD_parallel_for: case OMPD_parallel_for_simd: @@ -15426,6 +15462,7 @@ case OMPD_cancel: case OMPD_parallel: case OMPD_parallel_master: + case OMPD_parallel_masked: case OMPD_parallel_sections: case OMPD_parallel_for: case OMPD_parallel_for_simd: Index: clang/lib/Sema/TreeTransform.h =================================================================== --- clang/lib/Sema/TreeTransform.h +++ clang/lib/Sema/TreeTransform.h @@ -8772,6 +8772,17 @@ return Res; } +template +StmtResult TreeTransform::TransformOMPParallelMaskedDirective( + OMPParallelMaskedDirective *D) { + DeclarationNameInfo DirName; + getDerived().getSema().StartOpenMPDSABlock(OMPD_parallel_masked, DirName, + nullptr, D->getBeginLoc()); + StmtResult Res = getDerived().TransformOMPExecutableDirective(D); + getDerived().getSema().EndOpenMPDSABlock(Res.get()); + return Res; +} + template StmtResult TreeTransform::TransformOMPParallelSectionsDirective( OMPParallelSectionsDirective *D) { Index: clang/lib/Serialization/ASTReaderStmt.cpp =================================================================== --- clang/lib/Serialization/ASTReaderStmt.cpp +++ clang/lib/Serialization/ASTReaderStmt.cpp @@ -2371,6 +2371,12 @@ VisitOMPExecutableDirective(D); } +void ASTStmtReader::VisitOMPParallelMaskedDirective( + OMPParallelMaskedDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); +} + void ASTStmtReader::VisitOMPParallelSectionsDirective( OMPParallelSectionsDirective *D) { VisitStmt(D); @@ -3296,6 +3302,11 @@ Context, Record[ASTStmtReader::NumStmtFields], Empty); break; + case STMT_OMP_PARALLEL_MASKED_DIRECTIVE: + S = OMPParallelMaskedDirective::CreateEmpty( + Context, Record[ASTStmtReader::NumStmtFields], Empty); + break; + case STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE: S = OMPParallelSectionsDirective::CreateEmpty( Context, Record[ASTStmtReader::NumStmtFields], Empty); Index: clang/lib/Serialization/ASTWriterStmt.cpp =================================================================== --- clang/lib/Serialization/ASTWriterStmt.cpp +++ clang/lib/Serialization/ASTWriterStmt.cpp @@ -2298,6 +2298,13 @@ Code = serialization::STMT_OMP_PARALLEL_MASTER_DIRECTIVE; } +void ASTStmtWriter::VisitOMPParallelMaskedDirective( + OMPParallelMaskedDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_PARALLEL_MASKED_DIRECTIVE; +} + void ASTStmtWriter::VisitOMPParallelSectionsDirective( OMPParallelSectionsDirective *D) { VisitStmt(D); Index: clang/lib/StaticAnalyzer/Core/ExprEngine.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1244,6 +1244,7 @@ case Stmt::OMPParallelForSimdDirectiveClass: case Stmt::OMPParallelSectionsDirectiveClass: case Stmt::OMPParallelMasterDirectiveClass: + case Stmt::OMPParallelMaskedDirectiveClass: case Stmt::OMPTaskDirectiveClass: case Stmt::OMPTaskyieldDirectiveClass: case Stmt::OMPBarrierDirectiveClass: Index: clang/test/OpenMP/parallel_masked_ast_print.cpp =================================================================== --- /dev/null +++ clang/test/OpenMP/parallel_masked_ast_print.cpp @@ -0,0 +1,224 @@ +// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s + +// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER + +void foo() {} + +struct S1 { + S1(): a(0) {} + S1(int v) : a(v) {} + int a; + typedef int type; + S1& operator +(const S1&); + S1& operator *(const S1&); + S1& operator &&(const S1&); + S1& operator ^(const S1&); +}; + +template +class S7 : public T { +protected: + T a; + T b[100]; + S7() : a(0) {} + +public: + S7(typename T::type v) : a(v) { + int tid = 0; +// CHECK: #pragma omp parallel masked filter(tid) private(this->a) private(this->a) private(T::a) +#pragma omp parallel masked filter(tid) private(a) private(this->a) private(T::a) + for (int k = 0; k < a.a; ++k) + ++this->a.a; +// CHECK: #pragma omp parallel masked filter(tid) firstprivate(this->a) firstprivate(this->a) firstprivate(T::a) +#pragma omp parallel masked filter(tid) firstprivate(a) firstprivate(this->a) firstprivate(T::a) + for (int k = 0; k < a.a; ++k) + ++this->a.a; +// CHECK: #pragma omp parallel masked filter(tid) shared(this->a) shared(this->a) shared(T::a) +#pragma omp parallel masked filter(tid) shared(a) shared(this->a) shared(T::a) + for (int k = 0; k < a.a; ++k) + ++this->a.a; +// CHECK: #pragma omp parallel masked filter(tid) reduction(+: this->a) reduction(*: this->b[:]) +#pragma omp parallel masked filter(tid) reduction(+ : a) reduction(*: b[:]) + for (int k = 0; k < a.a; ++k) + ++this->a.a; + } + S7 &operator=(S7 &s) { + int tid = 0; +// CHECK: #pragma omp parallel masked filter(tid) private(this->a) private(this->a) +#pragma omp parallel masked filter(tid) private(a) private(this->a) + for (int k = 0; k < s.a.a; ++k) + ++s.a.a; +// CHECK: #pragma omp parallel masked filter(tid) firstprivate(this->a) firstprivate(this->a) +#pragma omp parallel masked filter(tid) firstprivate(a) firstprivate(this->a) + for (int k = 0; k < s.a.a; ++k) + ++s.a.a; +// CHECK: #pragma omp parallel masked filter(tid) shared(this->a) shared(this->a) +#pragma omp parallel masked filter(tid) shared(a) shared(this->a) + for (int k = 0; k < s.a.a; ++k) + ++s.a.a; +// CHECK: #pragma omp parallel masked filter(tid) reduction(&&: this->a) reduction(^: this->b[s.a.a]) +#pragma omp parallel masked filter(tid) reduction(&& : this->a) reduction(^: b[s.a.a]) + for (int k = 0; k < s.a.a; ++k) + ++s.a.a; + return *this; + } +}; + +// CHECK: #pragma omp parallel masked filter(tid) private(this->a) private(this->a) private(this->S1::a) +// CHECK: #pragma omp parallel masked filter(tid) firstprivate(this->a) firstprivate(this->a) firstprivate(this->S1::a) +// CHECK: #pragma omp parallel masked filter(tid) shared(this->a) shared(this->a) shared(this->S1::a) +// CHECK: #pragma omp parallel masked filter(tid) reduction(+: this->a) reduction(*: this->b[:]) + +class S8 : public S7 { + S8() {} + +public: + S8(int v) : S7(v){ +// CHECK: #pragma omp parallel masked private(this->a) private(this->a) private(this->S7::a) +#pragma omp parallel masked private(a) private(this->a) private(S7 < S1 > ::a) + for (int k = 0; k < a.a; ++k) + ++this->a.a; +// CHECK: #pragma omp parallel masked firstprivate(this->a) firstprivate(this->a) firstprivate(this->S7::a) +#pragma omp parallel masked firstprivate(a) firstprivate(this->a) firstprivate(S7 < S1 > ::a) + for (int k = 0; k < a.a; ++k) + ++this->a.a; +// CHECK: #pragma omp parallel masked shared(this->a) shared(this->a) shared(this->S7::a) +#pragma omp parallel masked shared(a) shared(this->a) shared(S7 < S1 > ::a) + for (int k = 0; k < a.a; ++k) + ++this->a.a; +// CHECK: #pragma omp parallel masked reduction(^: this->S7::a) reduction(+: this->S7::b[:this->S7::a.a]) +#pragma omp parallel masked reduction(^ : S7 < S1 > ::a) reduction(+ : S7 < S1 > ::b[ : S7 < S1 > ::a.a]) + for (int k = 0; k < a.a; ++k) + ++this->a.a; + } + S8 &operator=(S8 &s) { +// CHECK: #pragma omp parallel masked private(this->a) private(this->a) +#pragma omp parallel masked private(a) private(this->a) + for (int k = 0; k < s.a.a; ++k) + ++s.a.a; +// CHECK: #pragma omp parallel masked firstprivate(this->a) firstprivate(this->a) +#pragma omp parallel masked firstprivate(a) firstprivate(this->a) + for (int k = 0; k < s.a.a; ++k) + ++s.a.a; +// CHECK: #pragma omp parallel masked shared(this->a) shared(this->a) +#pragma omp parallel masked shared(a) shared(this->a) + for (int k = 0; k < s.a.a; ++k) + ++s.a.a; +// CHECK: #pragma omp parallel masked reduction(*: this->a) reduction(&&: this->b[this->a.a:]) +#pragma omp parallel masked reduction(* : this->a) reduction(&&:this->b[a.a:]) + for (int k = 0; k < s.a.a; ++k) + ++s.a.a; + return *this; + } +}; + + +template +struct S { + operator T() {return T();} + static T TS; + #pragma omp threadprivate(TS) +}; + +// CHECK: template struct S { +// CHECK: static T TS; +// CHECK-NEXT: #pragma omp threadprivate(S::TS) +// CHECK: }; +// CHECK: template<> struct S { +// CHECK: static int TS; +// CHECK-NEXT: #pragma omp threadprivate(S::TS) +// CHECK-NEXT: } +// CHECK: template<> struct S { +// CHECK: static long TS; +// CHECK-NEXT: #pragma omp threadprivate(S::TS) +// CHECK-NEXT: } + +int thrp; +#pragma omp threadprivate(thrp) + +template +T tmain(T argc, T *argv) { + T b = argc, c, d, e, f, g; + static T a; + S s; + T arr[C][10], arr1[C]; +#pragma omp parallel masked + a=2; +#pragma omp parallel masked default(none), private(argc,b) firstprivate(argv) shared (d) if (parallel:argc > 0) num_threads(C) copyin(S::TS, thrp) proc_bind(master) reduction(+:c, arr1[argc]) reduction(max:e, arr[:C][0:10]) + foo(); +#pragma omp parallel masked if (C) num_threads(s) proc_bind(close) reduction(^:e, f, arr[0:C][:argc]) reduction(task, && : g) + foo(); + return 0; +} + +// CHECK: template T tmain(T argc, T *argv) { +// CHECK-NEXT: T b = argc, c, d, e, f, g; +// CHECK-NEXT: static T a; +// CHECK-NEXT: S s; +// CHECK-NEXT: T arr[C][10], arr1[C]; +// CHECK-NEXT: #pragma omp parallel masked +// CHECK-NEXT: a = 2; +// CHECK-NEXT: #pragma omp parallel masked default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(C) copyin(S::TS,thrp) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:C][0:10]) +// CHECK-NEXT: foo() +// CHECK-NEXT: #pragma omp parallel masked if(C) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:C][:argc]) reduction(task, &&: g) +// CHECK-NEXT: foo() +// CHECK: template<> int tmain(int argc, int *argv) { +// CHECK-NEXT: int b = argc, c, d, e, f, g; +// CHECK-NEXT: static int a; +// CHECK-NEXT: S s; +// CHECK-NEXT: int arr[5][10], arr1[5]; +// CHECK-NEXT: #pragma omp parallel masked +// CHECK-NEXT: a = 2; +// CHECK-NEXT: #pragma omp parallel masked default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(5) copyin(S::TS,thrp) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:5][0:10]) +// CHECK-NEXT: foo() +// CHECK-NEXT: #pragma omp parallel masked if(5) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:5][:argc]) reduction(task, &&: g) +// CHECK-NEXT: foo() +// CHECK: template<> long tmain(long argc, long *argv) { +// CHECK-NEXT: long b = argc, c, d, e, f, g; +// CHECK-NEXT: static long a; +// CHECK-NEXT: S s; +// CHECK-NEXT: long arr[1][10], arr1[1]; +// CHECK-NEXT: #pragma omp parallel masked +// CHECK-NEXT: a = 2; +// CHECK-NEXT: #pragma omp parallel masked default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(1) copyin(S::TS,thrp) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:1][0:10]) +// CHECK-NEXT: foo() +// CHECK-NEXT: #pragma omp parallel masked if(1) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:1][:argc]) reduction(task, &&: g) +// CHECK-NEXT: foo() + +enum Enum { }; + +int main (int argc, char **argv) { + long x; + int b = argc, c, d, e, f, g; + static int a; + #pragma omp threadprivate(a) + int arr[10][argc], arr1[2]; + Enum ee; +// CHECK: Enum ee; +#pragma omp parallel masked +// CHECK-NEXT: #pragma omp parallel masked + a=2; +// CHECK-NEXT: a = 2; +#pragma omp parallel masked default(none), private(argc,b) firstprivate(argv) if (parallel: argc > 0) num_threads(ee) copyin(a) proc_bind(spread) reduction(| : c, d, arr1[argc]) reduction(* : e, arr[:10][0:argc]) allocate(e) +// CHECK-NEXT: #pragma omp parallel masked default(none) private(argc,b) firstprivate(argv) if(parallel: argc > 0) num_threads(ee) copyin(a) proc_bind(spread) reduction(|: c,d,arr1[argc]) reduction(*: e,arr[:10][0:argc]) allocate(e) + foo(); +// CHECK-NEXT: foo(); +// CHECK-NEXT: #pragma omp parallel masked allocate(e) if(b) num_threads(c) proc_bind(close) reduction(^: e,f) reduction(&&: g,arr[0:argc][:10]) +// CHECK-NEXT: foo() +#pragma omp parallel masked allocate(e) if (b) num_threads(c) proc_bind(close) reduction(^:e, f) reduction(&& : g, arr[0:argc][:10]) + foo(); + return tmain(b, &b) + tmain(x, &x); +} + +template +T S::TS = 0; + +#endif Index: clang/tools/libclang/CIndex.cpp =================================================================== --- clang/tools/libclang/CIndex.cpp +++ clang/tools/libclang/CIndex.cpp @@ -2152,6 +2152,7 @@ void VisitOMPParallelForDirective(const OMPParallelForDirective *D); void VisitOMPParallelForSimdDirective(const OMPParallelForSimdDirective *D); void VisitOMPParallelMasterDirective(const OMPParallelMasterDirective *D); + void VisitOMPParallelMaskedDirective(const OMPParallelMaskedDirective *D); void VisitOMPParallelSectionsDirective(const OMPParallelSectionsDirective *D); void VisitOMPTaskDirective(const OMPTaskDirective *D); void VisitOMPTaskyieldDirective(const OMPTaskyieldDirective *D); @@ -3073,6 +3074,11 @@ VisitOMPExecutableDirective(D); } +void EnqueueVisitor::VisitOMPParallelMaskedDirective( + const OMPParallelMaskedDirective *D) { + VisitOMPExecutableDirective(D); +} + void EnqueueVisitor::VisitOMPParallelSectionsDirective( const OMPParallelSectionsDirective *D) { VisitOMPExecutableDirective(D); @@ -5766,6 +5772,8 @@ return cxstring::createRef("OMPParallelForSimdDirective"); case CXCursor_OMPParallelMasterDirective: return cxstring::createRef("OMPParallelMasterDirective"); + case CXCursor_OMPParallelMaskedDirective: + return cxstring::createRef("OMPParallelMaskedDirective"); case CXCursor_OMPParallelSectionsDirective: return cxstring::createRef("OMPParallelSectionsDirective"); case CXCursor_OMPTaskDirective: Index: clang/tools/libclang/CXCursor.cpp =================================================================== --- clang/tools/libclang/CXCursor.cpp +++ clang/tools/libclang/CXCursor.cpp @@ -694,6 +694,9 @@ case Stmt::OMPParallelMasterDirectiveClass: K = CXCursor_OMPParallelMasterDirective; break; + case Stmt::OMPParallelMaskedDirectiveClass: + K = CXCursor_OMPParallelMaskedDirective; + break; case Stmt::OMPParallelSectionsDirectiveClass: K = CXCursor_OMPParallelSectionsDirective; break; Index: llvm/include/llvm/Frontend/OpenMP/OMP.td =================================================================== --- llvm/include/llvm/Frontend/OpenMP/OMP.td +++ llvm/include/llvm/Frontend/OpenMP/OMP.td @@ -861,6 +861,21 @@ VersionedClause ]; } +def OMP_ParallelMasked : Directive<"parallel masked"> { + let allowedClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; +} def OMP_ParallelSections : Directive<"parallel sections"> { let allowedClauses = [ VersionedClause,