From 80c2289a03f8a993b2377993a873242a62116c58 Mon Sep 17 00:00:00 2001 From: Alexander Musman Date: Thu, 17 Jul 2014 08:54:58 +0000 Subject: [PATCH] [OPENMP] Parsing/Sema analysis of directive 'master' llvm-svn: 213237 --- clang/include/clang-c/Index.h | 6 +- clang/include/clang/AST/DataRecursiveASTVisitor.h | 3 + clang/include/clang/AST/RecursiveASTVisitor.h | 3 + clang/include/clang/AST/StmtOpenMP.h | 47 ++++ clang/include/clang/Basic/OpenMPKinds.def | 1 + clang/include/clang/Basic/StmtNodes.td | 1 + clang/include/clang/Sema/Sema.h | 4 + clang/include/clang/Serialization/ASTBitCodes.h | 1 + clang/lib/AST/Stmt.cpp | 20 ++ clang/lib/AST/StmtPrinter.cpp | 5 + clang/lib/AST/StmtProfile.cpp | 4 + clang/lib/Basic/OpenMPKinds.cpp | 1 + clang/lib/CodeGen/CGStmt.cpp | 3 + clang/lib/CodeGen/CGStmtOpenMP.cpp | 4 + clang/lib/CodeGen/CodeGenFunction.h | 1 + clang/lib/Parse/ParseOpenMP.cpp | 6 +- clang/lib/Sema/SemaOpenMP.cpp | 64 +++++- clang/lib/Sema/TreeTransform.h | 11 + clang/lib/Serialization/ASTReaderStmt.cpp | 9 + clang/lib/Serialization/ASTWriterStmt.cpp | 6 + clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 1 + clang/test/OpenMP/master_ast_print.cpp | 32 +++ clang/test/OpenMP/master_messages.cpp | 64 ++++++ clang/test/OpenMP/nesting_of_regions.cpp | 257 ++++++++++++++++++++++ clang/tools/libclang/CIndex.cpp | 7 + clang/tools/libclang/CXCursor.cpp | 3 + 26 files changed, 554 insertions(+), 10 deletions(-) create mode 100644 clang/test/OpenMP/master_ast_print.cpp create mode 100644 clang/test/OpenMP/master_messages.cpp diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 7f3f248..c514fb0 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2167,9 +2167,13 @@ enum CXCursorKind { */ CXCursor_OMPTaskDirective = 240, + /** \brief OpenMP master directive. + */ + CXCursor_OMPMasterDirective = 241, + /** \brief Windows Structured Exception Handling's leave statement. */ - CXCursor_SEHLeaveStmt = 241, + CXCursor_SEHLeaveStmt = 242, CXCursor_LastStmt = CXCursor_SEHLeaveStmt, diff --git a/clang/include/clang/AST/DataRecursiveASTVisitor.h b/clang/include/clang/AST/DataRecursiveASTVisitor.h index 70bf06b..e47e99b 100644 --- a/clang/include/clang/AST/DataRecursiveASTVisitor.h +++ b/clang/include/clang/AST/DataRecursiveASTVisitor.h @@ -2297,6 +2297,9 @@ DEF_TRAVERSE_STMT(OMPSectionDirective, DEF_TRAVERSE_STMT(OMPSingleDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPMasterDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPParallelForDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 833cfbe..208d0f5 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2319,6 +2319,9 @@ DEF_TRAVERSE_STMT(OMPSectionDirective, DEF_TRAVERSE_STMT(OMPSingleDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPMasterDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPParallelForDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) diff --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h index e74febe..1c09785 100644 --- a/clang/include/clang/AST/StmtOpenMP.h +++ b/clang/include/clang/AST/StmtOpenMP.h @@ -527,6 +527,53 @@ public: } }; +/// \brief This represents '#pragma omp master' directive. +/// +/// \code +/// #pragma omp master +/// \endcode +/// +class OMPMasterDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// + OMPMasterDirective(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPExecutableDirective(this, OMPMasterDirectiveClass, OMPD_master, + StartLoc, EndLoc, 0, 1) {} + + /// \brief Build an empty directive. + /// + explicit OMPMasterDirective() + : OMPExecutableDirective(this, OMPMasterDirectiveClass, OMPD_master, + SourceLocation(), SourceLocation(), 0, 1) {} + +public: + /// \brief Creates directive. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param AssociatedStmt Statement, associated with the directive. + /// + static OMPMasterDirective *Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + Stmt *AssociatedStmt); + + /// \brief Creates an empty directive. + /// + /// \param C AST context. + /// + static OMPMasterDirective *CreateEmpty(const ASTContext &C, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPMasterDirectiveClass; + } +}; + /// \brief This represents '#pragma omp parallel for' directive. /// /// \code diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def index ff08b14..61d23d4 100644 --- a/clang/include/clang/Basic/OpenMPKinds.def +++ b/clang/include/clang/Basic/OpenMPKinds.def @@ -64,6 +64,7 @@ OPENMP_DIRECTIVE(for) OPENMP_DIRECTIVE(sections) OPENMP_DIRECTIVE(section) OPENMP_DIRECTIVE(single) +OPENMP_DIRECTIVE(master) OPENMP_DIRECTIVE_EXT(parallel_for, "parallel for") OPENMP_DIRECTIVE_EXT(parallel_sections, "parallel sections") diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td index 71b5629..9d56783 100644 --- a/clang/include/clang/Basic/StmtNodes.td +++ b/clang/include/clang/Basic/StmtNodes.td @@ -184,6 +184,7 @@ def OMPForDirective : DStmt; def OMPSectionsDirective : DStmt; def OMPSectionDirective : DStmt; def OMPSingleDirective : DStmt; +def OMPMasterDirective : DStmt; def OMPParallelForDirective : DStmt; def OMPParallelSectionsDirective : DStmt; def OMPTaskDirective : DStmt; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index bb8887a..f647920 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -7347,6 +7347,10 @@ public: StmtResult ActOnOpenMPSingleDirective(ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc); + /// \brief Called on well-formed '\#pragma omp master' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPMasterDirective(Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); /// \brief Called on well-formed '\#pragma omp parallel for' after parsing /// of the associated statement. StmtResult ActOnOpenMPParallelForDirective( diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 1b1cd0a..d1d32ac 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1346,6 +1346,7 @@ namespace clang { STMT_OMP_SECTIONS_DIRECTIVE, STMT_OMP_SECTION_DIRECTIVE, STMT_OMP_SINGLE_DIRECTIVE, + STMT_OMP_MASTER_DIRECTIVE, STMT_OMP_PARALLEL_FOR_DIRECTIVE, STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE, STMT_OMP_TASK_DIRECTIVE, diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index b415e92..9185e48 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -1478,6 +1478,26 @@ OMPSingleDirective *OMPSingleDirective::CreateEmpty(const ASTContext &C, return new (Mem) OMPSingleDirective(NumClauses); } +OMPMasterDirective *OMPMasterDirective::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + Stmt *AssociatedStmt) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPMasterDirective), + llvm::alignOf()); + void *Mem = C.Allocate(Size + sizeof(Stmt *)); + OMPMasterDirective *Dir = new (Mem) OMPMasterDirective(StartLoc, EndLoc); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPMasterDirective *OMPMasterDirective::CreateEmpty(const ASTContext &C, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPMasterDirective), + llvm::alignOf()); + void *Mem = C.Allocate(Size + sizeof(Stmt *)); + return new (Mem) OMPMasterDirective(); +} + OMPParallelForDirective * OMPParallelForDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 5958dac..fd511ef 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -821,6 +821,11 @@ void StmtPrinter::VisitOMPSingleDirective(OMPSingleDirective *Node) { PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPMasterDirective(OMPMasterDirective *Node) { + Indent() << "#pragma omp master"; + PrintOMPExecutableDirective(Node); +} + void StmtPrinter::VisitOMPParallelForDirective(OMPParallelForDirective *Node) { Indent() << "#pragma omp parallel for "; PrintOMPExecutableDirective(Node); diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index d0c39a5..c45281f 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -385,6 +385,10 @@ void StmtProfiler::VisitOMPSingleDirective(const OMPSingleDirective *S) { VisitOMPExecutableDirective(S); } +void StmtProfiler::VisitOMPMasterDirective(const OMPMasterDirective *S) { + VisitOMPExecutableDirective(S); +} + void StmtProfiler::VisitOMPParallelForDirective(const OMPParallelForDirective *S) { VisitOMPExecutableDirective(S); diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index 056d358..31b571c 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -252,6 +252,7 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, case OMPD_unknown: case OMPD_threadprivate: case OMPD_section: + case OMPD_master: break; } return false; diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 39adf9b..788fd06 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -194,6 +194,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { case Stmt::OMPSingleDirectiveClass: EmitOMPSingleDirective(cast(*S)); break; + case Stmt::OMPMasterDirectiveClass: + EmitOMPMasterDirective(cast(*S)); + break; case Stmt::OMPParallelForDirectiveClass: EmitOMPParallelForDirective(cast(*S)); break; diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 3d36dbb..f086146 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -90,6 +90,10 @@ void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &) { llvm_unreachable("CodeGen for 'omp single' is not supported yet."); } +void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &) { + llvm_unreachable("CodeGen for 'omp master' is not supported yet."); +} + void CodeGenFunction::EmitOMPParallelForDirective(const OMPParallelForDirective &) { llvm_unreachable("CodeGen for 'omp parallel for' is not supported yet."); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index f6dd39f..d6675f3 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -1916,6 +1916,7 @@ public: void EmitOMPSectionsDirective(const OMPSectionsDirective &S); void EmitOMPSectionDirective(const OMPSectionDirective &S); void EmitOMPSingleDirective(const OMPSingleDirective &S); + void EmitOMPMasterDirective(const OMPMasterDirective &S); void EmitOMPParallelForDirective(const OMPParallelForDirective &S); void EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &S); void EmitOMPTaskDirective(const OMPTaskDirective &S); diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index e50f471..172aef8 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -87,6 +87,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { case OMPD_sections: case OMPD_section: case OMPD_single: + case OMPD_master: case OMPD_parallel_for: case OMPD_parallel_sections: Diag(Tok, diag::err_omp_unexpected_directive) @@ -105,8 +106,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { /// /// executable-directive: /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' | -/// 'section' | 'single' | 'parallel for' | 'parallel sections' | 'task' -/// {clause} annot_pragma_openmp_end +/// 'section' | 'single' | 'master' | 'parallel for' | +/// 'parallel sections' | 'task' {clause} annot_pragma_openmp_end /// StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() { assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); @@ -146,6 +147,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() { case OMPD_sections: case OMPD_single: case OMPD_section: + case OMPD_master: case OMPD_parallel_for: case OMPD_parallel_sections: case OMPD_task: { diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 58f9bbe..ef36e7e 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -1000,6 +1000,14 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { Params); break; } + case OMPD_master: { + Sema::CapturedParamNameType Params[] = { + std::make_pair(StringRef(), QualType()) // __context with shared vars + }; + ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, + Params); + break; + } case OMPD_parallel_for: { QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1); QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty); @@ -1044,9 +1052,10 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // +------------------+-----------------+------------------------------------+ // | parallel | parallel | * | // | parallel | for | * | + // | parallel | master | * | // | parallel | simd | * | // | parallel | sections | * | - // | parallel | section | + | + // | parallel | section | + | // | parallel | single | * | // | parallel | parallel for | * | // | parallel |parallel sections| * | @@ -1054,6 +1063,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // +------------------+-----------------+------------------------------------+ // | for | parallel | * | // | for | for | + | + // | for | master | + | // | for | simd | * | // | for | sections | + | // | for | section | + | @@ -1062,8 +1072,20 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | for |parallel sections| * | // | for | task | * | // +------------------+-----------------+------------------------------------+ + // | master | parallel | * | + // | master | for | + | + // | master | master | * | + // | master | simd | * | + // | master | sections | + | + // | master | section | + | + // | master | single | + | + // | master | parallel for | * | + // | master |parallel sections| * | + // | master | task | * | + // +------------------+-----------------+------------------------------------+ // | simd | parallel | | // | simd | for | | + // | simd | master | | // | simd | simd | | // | simd | sections | | // | simd | section | | @@ -1074,6 +1096,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // +------------------+-----------------+------------------------------------+ // | sections | parallel | * | // | sections | for | + | + // | sections | master | + | // | sections | simd | * | // | sections | sections | + | // | sections | section | * | @@ -1084,6 +1107,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // +------------------+-----------------+------------------------------------+ // | section | parallel | * | // | section | for | + | + // | section | master | + | // | section | simd | * | // | section | sections | + | // | section | section | + | @@ -1094,6 +1118,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // +------------------+-----------------+------------------------------------+ // | single | parallel | * | // | single | for | + | + // | single | master | + | // | single | simd | * | // | single | sections | + | // | single | section | + | @@ -1104,6 +1129,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // +------------------+-----------------+------------------------------------+ // | parallel for | parallel | * | // | parallel for | for | + | + // | parallel for | master | + | // | parallel for | simd | * | // | parallel for | sections | + | // | parallel for | section | + | @@ -1114,6 +1140,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // +------------------+-----------------+------------------------------------+ // | parallel sections| parallel | * | // | parallel sections| for | + | + // | parallel sections| master | + | // | parallel sections| simd | * | // | parallel sections| sections | + | // | parallel sections| section | * | @@ -1124,9 +1151,10 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // +------------------+-----------------+------------------------------------+ // | task | parallel | * | // | task | for | + | + // | task | master | + | // | task | simd | * | // | task | sections | + | - // | task | section | + | + // | task | section | + | // | task | single | + | // | task | parallel for | * | // | task |parallel sections| * | @@ -1157,16 +1185,23 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, } return false; } - if (isOpenMPWorksharingDirective(CurrentRegion) && - !isOpenMPParallelDirective(CurrentRegion) && - !isOpenMPSimdDirective(CurrentRegion)) { + if (CurrentRegion == OMPD_master) { + // OpenMP [2.16, Nesting of Regions] + // A master region may not be closely nested inside a worksharing, + // atomic (TODO), or explicit task region. + NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) || + ParentRegion == OMPD_task; + } else if (isOpenMPWorksharingDirective(CurrentRegion) && + !isOpenMPParallelDirective(CurrentRegion) && + !isOpenMPSimdDirective(CurrentRegion)) { // OpenMP [2.16, Nesting of Regions] // A worksharing region may not be closely nested inside a worksharing, // explicit task, critical, ordered, atomic, or master region. // TODO NestingProhibited = (isOpenMPWorksharingDirective(ParentRegion) && !isOpenMPSimdDirective(ParentRegion)) || - ParentRegion == OMPD_task; + ParentRegion == OMPD_task || + ParentRegion == OMPD_master; ShouldBeInParallelRegion = true; } if (NestingProhibited) { @@ -1231,13 +1266,18 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, break; case OMPD_section: assert(ClausesWithImplicit.empty() && - "No clauses is allowed for 'omp section' directive"); + "No clauses are allowed for 'omp section' directive"); Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc); break; case OMPD_single: Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); break; + case OMPD_master: + assert(ClausesWithImplicit.empty() && + "No clauses are allowed for 'omp master' directive"); + Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc); + break; case OMPD_parallel_for: Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); @@ -1906,6 +1946,16 @@ StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef Clauses, return OMPSingleDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt); } +StmtResult Sema::ActOnOpenMPMasterDirective(Stmt *AStmt, + SourceLocation StartLoc, + SourceLocation EndLoc) { + assert(AStmt && isa(AStmt) && "Captured statement expected"); + + getCurFunction()->setHasBranchProtectedScope(); + + return OMPMasterDirective::Create(Context, StartLoc, EndLoc, AStmt); +} + StmtResult Sema::ActOnOpenMPParallelForDirective( ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index f9775c1..6eb18e8 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -6509,6 +6509,17 @@ TreeTransform::TransformOMPSingleDirective(OMPSingleDirective *D) { } template +StmtResult +TreeTransform::TransformOMPMasterDirective(OMPMasterDirective *D) { + DeclarationNameInfo DirName; + getDerived().getSema().StartOpenMPDSABlock(OMPD_master, DirName, nullptr, + D->getLocStart()); + StmtResult Res = getDerived().TransformOMPExecutableDirective(D); + getDerived().getSema().EndOpenMPDSABlock(Res.get()); + return Res; +} + +template StmtResult TreeTransform::TransformOMPParallelForDirective( OMPParallelForDirective *D) { DeclarationNameInfo DirName; diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index e719bbb..e6c71b4 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1952,6 +1952,11 @@ void ASTStmtReader::VisitOMPSingleDirective(OMPSingleDirective *D) { VisitOMPExecutableDirective(D); } +void ASTStmtReader::VisitOMPMasterDirective(OMPMasterDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); +} + void ASTStmtReader::VisitOMPParallelForDirective(OMPParallelForDirective *D) { VisitStmt(D); // Two fields (NumClauses and CollapsedNum) were read in ReadStmtFromStream. @@ -2486,6 +2491,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { Context, Record[ASTStmtReader::NumStmtFields], Empty); break; + case STMT_OMP_MASTER_DIRECTIVE: + S = OMPMasterDirective::CreateEmpty(Context, Empty); + break; + case STMT_OMP_PARALLEL_FOR_DIRECTIVE: { unsigned NumClauses = Record[ASTStmtReader::NumStmtFields]; unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index cacb2ec..e8027e7 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1857,6 +1857,12 @@ void ASTStmtWriter::VisitOMPSingleDirective(OMPSingleDirective *D) { Code = serialization::STMT_OMP_SINGLE_DIRECTIVE; } +void ASTStmtWriter::VisitOMPMasterDirective(OMPMasterDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_MASTER_DIRECTIVE; +} + void ASTStmtWriter::VisitOMPParallelForDirective(OMPParallelForDirective *D) { VisitStmt(D); Record.push_back(D->getNumClauses()); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index dec4d46..58b3357 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -737,6 +737,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::OMPSectionsDirectiveClass: case Stmt::OMPSectionDirectiveClass: case Stmt::OMPSingleDirectiveClass: + case Stmt::OMPMasterDirectiveClass: case Stmt::OMPParallelForDirectiveClass: case Stmt::OMPParallelSectionsDirectiveClass: case Stmt::OMPTaskDirectiveClass: diff --git a/clang/test/OpenMP/master_ast_print.cpp b/clang/test/OpenMP/master_ast_print.cpp new file mode 100644 index 0000000..7ce4c10 --- /dev/null +++ b/clang/test/OpenMP/master_ast_print.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp=libiomp5 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER + +void foo() {} + +int main (int argc, char **argv) { + int b = argc, c, d, e, f, g; + static int a; +// CHECK: static int a; +#pragma omp parallel +{ +#pragma omp master +{ + a=2; +} +} +// CHECK-NEXT: #pragma omp parallel +// CHECK-NEXT: { +// CHECK-NEXT: #pragma omp master +// CHECK-NEXT: { +// CHECK-NEXT: a = 2; +// CHECK-NEXT: } +// CHECK-NEXT: } + return (0); +} + +#endif diff --git a/clang/test/OpenMP/master_messages.cpp b/clang/test/OpenMP/master_messages.cpp new file mode 100644 index 0000000..fbe35ac --- /dev/null +++ b/clang/test/OpenMP/master_messages.cpp @@ -0,0 +1,64 @@ +// RUN: %clang_cc1 -verify -fopenmp=libiomp5 %s + +int foo(); + +int main() { + #pragma omp master + ; + #pragma omp master nowait // expected-error {{unexpected OpenMP clause 'nowait' in directive '#pragma omp master'}} + #pragma omp master unknown // expected-warning {{extra tokens at the end of '#pragma omp master' are ignored}} + foo(); + { + #pragma omp master + } // expected-error {{expected statement}} + #pragma omp for + for (int i = 0; i < 10; ++i) { + foo(); + #pragma omp master // expected-error {{region cannot be closely nested inside 'for' region}} + foo(); + } + #pragma omp sections + { + foo(); + #pragma omp master // expected-error {{region cannot be closely nested inside 'sections' region}} + foo(); + } + #pragma omp single + for (int i = 0; i < 10; ++i) { + foo(); + #pragma omp master // expected-error {{region cannot be closely nested inside 'single' region}} + foo(); + } + #pragma omp master + for (int i = 0; i < 10; ++i) { + foo(); + #pragma omp master + foo(); + } + #pragma omp for ordered + for (int i = 0; i < 10; ++i) + #pragma omp master // expected-error {{region cannot be closely nested inside 'for' region}} + { + foo(); + } + + return 0; +} + +int foo() { + L1: + foo(); + #pragma omp master + { + foo(); + goto L1; // expected-error {{use of undeclared label 'L1'}} + } + goto L2; // expected-error {{use of undeclared label 'L2'}} + #pragma omp master + { + L2: + foo(); + } + + return 0; +} diff --git a/clang/test/OpenMP/nesting_of_regions.cpp b/clang/test/OpenMP/nesting_of_regions.cpp index c2e2526..d61ac3f 100644 --- a/clang/test/OpenMP/nesting_of_regions.cpp +++ b/clang/test/OpenMP/nesting_of_regions.cpp @@ -26,6 +26,12 @@ void foo() { #pragma omp parallel #pragma omp single bar(); + +#pragma omp parallel +#pragma omp master + { + bar(); + } #pragma omp parallel #pragma omp parallel for for (int i = 0; i < 10; ++i) @@ -83,6 +89,13 @@ void foo() { } #pragma omp simd for (int i = 0; i < 10; ++i) { +#pragma omp master // expected-error {{OpenMP constructs may not be nested inside a simd region}} + { + bar(); + } + } +#pragma omp simd + for (int i = 0; i < 10; ++i) { #pragma omp parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}} for (int i = 0; i < 10; ++i) ; @@ -142,6 +155,15 @@ void foo() { bar(); } } + +#pragma omp for + for (int i = 0; i < 10; ++i) { +#pragma omp master // expected-error {{region cannot be closely nested inside 'for' region}} + { + bar(); + } + } + #pragma omp for for (int i = 0; i < 10; ++i) { #pragma omp parallel @@ -232,6 +254,25 @@ void foo() { } #pragma omp sections { +#pragma omp parallel + { +#pragma omp master // OK + { + bar(); + } +#pragma omp for // OK + for (int i = 0; i < 10; ++i) + ; +#pragma omp master // OK + { + bar(); + } + } +#pragma omp master // expected-error {{region cannot be closely nested inside 'sections' region}} + bar(); + } +#pragma omp sections + { #pragma omp parallel for for (int i = 0; i < 10; ++i) ; @@ -309,6 +350,8 @@ void foo() { { #pragma omp single // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}} bar(); +#pragma omp master // expected-error {{region cannot be closely nested inside 'section' region}} + bar(); } } #pragma omp sections @@ -389,6 +432,13 @@ void foo() { } #pragma omp single { +#pragma omp master // expected-error {{region cannot be closely nested inside 'single' region}} + { + bar(); + } + } +#pragma omp single + { #pragma omp sections // expected-error {{region cannot be closely nested inside 'single' region; perhaps you forget to enclose 'omp sections' directive into a parallel region?}} { bar(); @@ -432,6 +482,84 @@ void foo() { } } +// MASTER DIRECTIVE +#pragma omp master + { +#pragma omp for // expected-error {{region cannot be closely nested inside 'master' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp master + { +#pragma omp simd + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp master + { +#pragma omp parallel + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp master + { +#pragma omp single // expected-error {{region cannot be closely nested inside 'master' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}} + { + bar(); + } + } +#pragma omp master + { +#pragma omp master // OK, though second 'master' is redundant + { + bar(); + } + } +#pragma omp master + { +#pragma omp sections // expected-error {{region cannot be closely nested inside 'master' region; perhaps you forget to enclose 'omp sections' directive into a parallel region?}} + { + bar(); + } + } +#pragma omp master + { +#pragma omp parallel + { +#pragma omp master // OK + { + bar(); + } +#pragma omp for // OK + for (int i = 0; i < 10; ++i) + ; +#pragma omp sections // OK + { + bar(); + } + } + } +#pragma omp master + { +#pragma omp parallel for + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp master + { +#pragma omp parallel sections + { + bar(); + } + } +#pragma omp master + { +#pragma omp task + { + bar(); + } + } + // PARALLEL FOR DIRECTIVE #pragma omp parallel for for (int i = 0; i < 10; ++i) { @@ -472,6 +600,15 @@ void foo() { bar(); } } + +#pragma omp parallel for + for (int i = 0; i < 10; ++i) { +#pragma omp master // expected-error {{region cannot be closely nested inside 'parallel for' region}} + { + bar(); + } + } + #pragma omp parallel for for (int i = 0; i < 10; ++i) { #pragma omp parallel @@ -553,6 +690,14 @@ void foo() { } #pragma omp parallel sections { +#pragma omp section + { +#pragma omp master // expected-error {{region cannot be closely nested inside 'section' region}} + bar(); + } + } +#pragma omp parallel sections + { #pragma omp parallel { #pragma omp single // OK @@ -612,6 +757,9 @@ void foo() { #pragma omp single // expected-error {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}} bar(); #pragma omp task +#pragma omp master // expected-error {{region cannot be closely nested inside 'task' region}} + bar(); +#pragma omp task #pragma omp parallel for for (int i = 0; i < 10; ++i) ; @@ -625,6 +773,7 @@ void foo() { { bar(); } + } void foo() { @@ -656,6 +805,9 @@ void foo() { #pragma omp single bar(); #pragma omp parallel +#pragma omp master + bar(); +#pragma omp parallel #pragma omp parallel for for (int i = 0; i < 10; ++i) ; @@ -707,6 +859,8 @@ void foo() { for (int i = 0; i < 10; ++i) { #pragma omp single // expected-error {{OpenMP constructs may not be nested inside a simd region}} bar(); +#pragma omp master // expected-error {{OpenMP constructs may not be nested inside a simd region}} + bar(); } #pragma omp simd for (int i = 0; i < 10; ++i) { @@ -766,6 +920,8 @@ void foo() { for (int i = 0; i < 10; ++i) { #pragma omp single // expected-error {{region cannot be closely nested inside 'for' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}} bar(); +#pragma omp master // expected-error {{region cannot be closely nested inside 'for' region}} + bar(); } #pragma omp for for (int i = 0; i < 10; ++i) { @@ -842,6 +998,8 @@ void foo() { { #pragma omp single // expected-error {{region cannot be closely nested inside 'sections' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}} bar(); +#pragma omp master // expected-error {{region cannot be closely nested inside 'sections' region}} + bar(); } #pragma omp sections { @@ -939,6 +1097,8 @@ void foo() { { #pragma omp single // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}} bar(); +#pragma omp master // expected-error {{region cannot be closely nested inside 'section' region}} + bar(); } } #pragma omp sections @@ -1016,6 +1176,8 @@ void foo() { { bar(); } +#pragma omp master // expected-error {{region cannot be closely nested inside 'single' region}} + bar(); } #pragma omp single { @@ -1062,6 +1224,84 @@ void foo() { } } +// MASTER DIRECTIVE +#pragma omp master + { +#pragma omp for // expected-error {{region cannot be closely nested inside 'master' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp master + { +#pragma omp simd + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp master + { +#pragma omp parallel + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp master + { +#pragma omp single // expected-error {{region cannot be closely nested inside 'master' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}} + { + bar(); + } + } +#pragma omp master + { +#pragma omp master // OK, though second 'master' is redundant + { + bar(); + } + } +#pragma omp master + { +#pragma omp sections // expected-error {{region cannot be closely nested inside 'master' region; perhaps you forget to enclose 'omp sections' directive into a parallel region?}} + { + bar(); + } + } +#pragma omp master + { +#pragma omp parallel + { +#pragma omp master // OK + { + bar(); + } +#pragma omp for // OK + for (int i = 0; i < 10; ++i) + ; +#pragma omp sections // OK + { + bar(); + } + } + } +#pragma omp master + { +#pragma omp parallel for + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp master + { +#pragma omp parallel sections + { + bar(); + } + } +#pragma omp master + { +#pragma omp task + { + bar(); + } + } + // PARALLEL FOR DIRECTIVE #pragma omp parallel for for (int i = 0; i < 10; ++i) { @@ -1101,6 +1341,10 @@ void foo() { { bar(); } +#pragma omp master // expected-error {{region cannot be closely nested inside 'parallel for' region}} + { + bar(); + } } #pragma omp parallel for for (int i = 0; i < 10; ++i) { @@ -1110,6 +1354,10 @@ void foo() { { bar(); } +#pragma omp master // OK + { + bar(); + } #pragma omp for // OK for (int i = 0; i < 10; ++i) ; @@ -1179,6 +1427,8 @@ void foo() { { #pragma omp single // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}} bar(); +#pragma omp master // expected-error {{region cannot be closely nested inside 'section' region}} + bar(); } } #pragma omp parallel sections @@ -1189,6 +1439,10 @@ void foo() { { bar(); } +#pragma omp master // OK + { + bar(); + } #pragma omp for // OK for (int i = 0; i < 10; ++i) ; @@ -1242,6 +1496,9 @@ void foo() { #pragma omp single // expected-error {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}} bar(); #pragma omp task +#pragma omp master // expected-error {{region cannot be closely nested inside 'task' region}} + bar(); +#pragma omp task #pragma omp parallel for for (int i = 0; i < 10; ++i) ; diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 4502017..75438e2 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -1860,6 +1860,7 @@ public: void VisitOMPSectionsDirective(const OMPSectionsDirective *D); void VisitOMPSectionDirective(const OMPSectionDirective *D); void VisitOMPSingleDirective(const OMPSingleDirective *D); + void VisitOMPMasterDirective(const OMPMasterDirective *D); void VisitOMPParallelForDirective(const OMPParallelForDirective *D); void VisitOMPParallelSectionsDirective(const OMPParallelSectionsDirective *D); void VisitOMPTaskDirective(const OMPTaskDirective *D); @@ -2318,6 +2319,10 @@ void EnqueueVisitor::VisitOMPSingleDirective(const OMPSingleDirective *D) { VisitOMPExecutableDirective(D); } +void EnqueueVisitor::VisitOMPMasterDirective(const OMPMasterDirective *D) { + VisitOMPExecutableDirective(D); +} + void EnqueueVisitor::VisitOMPParallelForDirective(const OMPParallelForDirective *D) { VisitOMPExecutableDirective(D); @@ -4016,6 +4021,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return cxstring::createRef("OMPSectionDirective"); case CXCursor_OMPSingleDirective: return cxstring::createRef("OMPSingleDirective"); + case CXCursor_OMPMasterDirective: + return cxstring::createRef("OMPMasterDirective"); case CXCursor_OMPParallelForDirective: return cxstring::createRef("OMPParallelForDirective"); case CXCursor_OMPParallelSectionsDirective: diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index 6875f5a..e50a156a 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -535,6 +535,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent, case Stmt::OMPSingleDirectiveClass: K = CXCursor_OMPSingleDirective; break; + case Stmt::OMPMasterDirectiveClass: + K = CXCursor_OMPMasterDirective; + break; case Stmt::OMPParallelForDirectiveClass: K = CXCursor_OMPParallelForDirective; break; -- 2.7.4