From 4d1dfeabc969093847dce13a2c959c30544c79d2 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Fri, 18 Jul 2014 09:11:51 +0000 Subject: [PATCH] [OPENMP] Initial parsing and sema analysis for 'barrier' directive. llvm-svn: 213360 --- 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 | 44 +++++++++ clang/include/clang/Basic/OpenMPKinds.def | 1 + clang/include/clang/Basic/StmtNodes.td | 1 + clang/include/clang/Sema/Sema.h | 6 +- clang/include/clang/Serialization/ASTBitCodes.h | 1 + clang/lib/AST/Stmt.cpp | 14 +++ 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 | 4 +- clang/lib/Sema/SemaOpenMP.cpp | 38 ++++++++ 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/barrier_ast_print.cpp | 32 +++++++ clang/test/OpenMP/barrier_messages.cpp | 110 ++++++++++++++++++++++ clang/test/OpenMP/nesting_of_regions.cpp | 104 +++++++++++++++++++- clang/tools/libclang/CIndex.cpp | 7 ++ clang/tools/libclang/CXCursor.cpp | 3 + 26 files changed, 417 insertions(+), 5 deletions(-) create mode 100644 clang/test/OpenMP/barrier_ast_print.cpp create mode 100644 clang/test/OpenMP/barrier_messages.cpp diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index a467f7d..22882bb 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2175,9 +2175,13 @@ enum CXCursorKind { */ CXCursor_OMPTaskyieldDirective = 242, + /** \brief OpenMP barrier directive. + */ + CXCursor_OMPBarrierDirective = 243, + /** \brief Windows Structured Exception Handling's leave statement. */ - CXCursor_SEHLeaveStmt = 243, + CXCursor_SEHLeaveStmt = 244, CXCursor_LastStmt = CXCursor_SEHLeaveStmt, diff --git a/clang/include/clang/AST/DataRecursiveASTVisitor.h b/clang/include/clang/AST/DataRecursiveASTVisitor.h index 09c83ed..2eb05a5c 100644 --- a/clang/include/clang/AST/DataRecursiveASTVisitor.h +++ b/clang/include/clang/AST/DataRecursiveASTVisitor.h @@ -2312,6 +2312,9 @@ DEF_TRAVERSE_STMT(OMPTaskDirective, DEF_TRAVERSE_STMT(OMPTaskyieldDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPBarrierDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + // OpenMP clauses. template bool RecursiveASTVisitor::TraverseOMPClause(OMPClause *C) { diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index a10962e..c5ec976 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2334,6 +2334,9 @@ DEF_TRAVERSE_STMT(OMPTaskDirective, DEF_TRAVERSE_STMT(OMPTaskyieldDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPBarrierDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + // OpenMP clauses. template bool RecursiveASTVisitor::TraverseOMPClause(OMPClause *C) { diff --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h index acecf43..f4445b6 100644 --- a/clang/include/clang/AST/StmtOpenMP.h +++ b/clang/include/clang/AST/StmtOpenMP.h @@ -818,6 +818,50 @@ public: } }; +/// \brief This represents '#pragma omp barrier' directive. +/// +/// \code +/// #pragma omp barrier +/// \endcode +/// +class OMPBarrierDirective : 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. + /// + OMPBarrierDirective(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPExecutableDirective(this, OMPBarrierDirectiveClass, OMPD_barrier, + StartLoc, EndLoc, 0, 0) {} + + /// \brief Build an empty directive. + /// + explicit OMPBarrierDirective() + : OMPExecutableDirective(this, OMPBarrierDirectiveClass, OMPD_barrier, + SourceLocation(), SourceLocation(), 0, 0) {} + +public: + /// \brief Creates directive. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// + static OMPBarrierDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc); + + /// \brief Creates an empty directive. + /// + /// \param C AST context. + /// + static OMPBarrierDirective *CreateEmpty(const ASTContext &C, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPBarrierDirectiveClass; + } +}; + } // end namespace clang #endif diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def index 8e93f73..12d0674 100644 --- a/clang/include/clang/Basic/OpenMPKinds.def +++ b/clang/include/clang/Basic/OpenMPKinds.def @@ -66,6 +66,7 @@ OPENMP_DIRECTIVE(section) OPENMP_DIRECTIVE(single) OPENMP_DIRECTIVE(master) OPENMP_DIRECTIVE(taskyield) +OPENMP_DIRECTIVE(barrier) 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 ab3a0ab..88a166a 100644 --- a/clang/include/clang/Basic/StmtNodes.td +++ b/clang/include/clang/Basic/StmtNodes.td @@ -189,3 +189,4 @@ def OMPParallelForDirective : DStmt; def OMPParallelSectionsDirective : DStmt; def OMPTaskDirective : DStmt; def OMPTaskyieldDirective : DStmt; +def OMPBarrierDirective : DStmt; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 7e3b383..bfe6b2d 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -7368,10 +7368,12 @@ public: StmtResult ActOnOpenMPTaskDirective(ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed '\#pragma omp taskyield' after parsing of the - /// associated statement. + /// \brief Called on well-formed '\#pragma omp taskyield'. StmtResult ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc, SourceLocation EndLoc); + /// \brief Called on well-formed '\#pragma omp barrier'. + StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc, + SourceLocation EndLoc); OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 6d5b4cc..f567925 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1351,6 +1351,7 @@ namespace clang { STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE, STMT_OMP_TASK_DIRECTIVE, STMT_OMP_TASKYIELD_DIRECTIVE, + STMT_OMP_BARRIER_DIRECTIVE, // ARC EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index 53c48cc..2328d27 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -1589,3 +1589,17 @@ OMPTaskyieldDirective *OMPTaskyieldDirective::CreateEmpty(const ASTContext &C, return new (Mem) OMPTaskyieldDirective(); } +OMPBarrierDirective *OMPBarrierDirective::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc) { + void *Mem = C.Allocate(sizeof(OMPBarrierDirective)); + OMPBarrierDirective *Dir = new (Mem) OMPBarrierDirective(StartLoc, EndLoc); + return Dir; +} + +OMPBarrierDirective *OMPBarrierDirective::CreateEmpty(const ASTContext &C, + EmptyShell) { + void *Mem = C.Allocate(sizeof(OMPBarrierDirective)); + return new (Mem) OMPBarrierDirective(); +} + diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index dfecc34..02f09c4 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -855,6 +855,11 @@ void StmtPrinter::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *Node) { PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPBarrierDirective(OMPBarrierDirective *Node) { + Indent() << "#pragma omp barrier"; + PrintOMPExecutableDirective(Node); +} + //===----------------------------------------------------------------------===// // Expr printing methods. //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index a4943bf..ae3be8d 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -411,6 +411,10 @@ void StmtProfiler::VisitOMPTaskyieldDirective(const OMPTaskyieldDirective *S) { VisitOMPExecutableDirective(S); } +void StmtProfiler::VisitOMPBarrierDirective(const OMPBarrierDirective *S) { + VisitOMPExecutableDirective(S); +} + void StmtProfiler::VisitExpr(const Expr *S) { VisitStmt(S); } diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index 543bdb3..ec2e6b4 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -258,6 +258,7 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, case OMPD_section: case OMPD_master: case OMPD_taskyield: + case OMPD_barrier: break; } return false; diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 3a8e71c..5da1222 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -209,6 +209,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { case Stmt::OMPTaskyieldDirectiveClass: EmitOMPTaskyieldDirective(cast(*S)); break; + case Stmt::OMPBarrierDirectiveClass: + EmitOMPBarrierDirective(cast(*S)); + break; } } diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index fbf5274..db9daef 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -112,3 +112,7 @@ void CodeGenFunction::EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &) { llvm_unreachable("CodeGen for 'omp taskyield' is not supported yet."); } +void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &) { + llvm_unreachable("CodeGen for 'omp barrier' is not supported yet."); +} + diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 3dc30d3..f0541f5 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -1932,6 +1932,7 @@ public: void EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &S); void EmitOMPTaskDirective(const OMPTaskDirective &S); void EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &S); + void EmitOMPBarrierDirective(const OMPBarrierDirective &S); //===--------------------------------------------------------------------===// // LValue Expression Emission diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 06fe1ad..b3f13b8 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -84,6 +84,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { case OMPD_simd: case OMPD_task: case OMPD_taskyield: + case OMPD_barrier: case OMPD_for: case OMPD_sections: case OMPD_section: @@ -108,7 +109,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { /// executable-directive: /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' | /// 'section' | 'single' | 'master' | 'parallel for' | -/// 'parallel sections' | 'task' | 'taskyield' {clause} +/// 'parallel sections' | 'task' | 'taskyield' | 'barrier' {clause} /// annot_pragma_openmp_end /// StmtResult @@ -146,6 +147,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { SkipUntil(tok::annot_pragma_openmp_end); break; case OMPD_taskyield: + case OMPD_barrier: if (!StandAloneAllowed) { Diag(Tok, diag::err_omp_immediate_directive) << getOpenMPDirectiveName(DKind); diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 67f9eb9..eeb4fbd 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -1044,6 +1044,14 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { Params); break; } + case OMPD_barrier: { + Sema::CapturedParamNameType Params[] = { + std::make_pair(StringRef(), QualType()) // __context with shared vars + }; + ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, + Params); + break; + } case OMPD_threadprivate: llvm_unreachable("OpenMP Directive is not allowed"); case OMPD_unknown: @@ -1069,6 +1077,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel |parallel sections| * | // | parallel | task | * | // | parallel | taskyield | * | + // | parallel | barrier | * | // +------------------+-----------------+------------------------------------+ // | for | parallel | * | // | for | for | + | @@ -1081,6 +1090,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | for |parallel sections| * | // | for | task | * | // | for | taskyield | * | + // | for | barrier | + | // +------------------+-----------------+------------------------------------+ // | master | parallel | * | // | master | for | + | @@ -1093,6 +1103,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | master |parallel sections| * | // | master | task | * | // | master | taskyield | * | + // | master | barrier | + | // +------------------+-----------------+------------------------------------+ // | simd | parallel | | // | simd | for | | @@ -1105,6 +1116,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | simd |parallel sections| | // | simd | task | | // | simd | taskyield | | + // | simd | barrier | | // +------------------+-----------------+------------------------------------+ // | sections | parallel | * | // | sections | for | + | @@ -1117,6 +1129,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | sections |parallel sections| * | // | sections | task | * | // | sections | taskyield | * | + // | sections | barrier | + | // +------------------+-----------------+------------------------------------+ // | section | parallel | * | // | section | for | + | @@ -1129,6 +1142,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | section |parallel sections| * | // | section | task | * | // | section | taskyield | * | + // | section | barrier | + | // +------------------+-----------------+------------------------------------+ // | single | parallel | * | // | single | for | + | @@ -1141,6 +1155,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | single |parallel sections| * | // | single | task | * | // | single | taskyield | * | + // | single | barrier | + | // +------------------+-----------------+------------------------------------+ // | parallel for | parallel | * | // | parallel for | for | + | @@ -1153,6 +1168,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel for |parallel sections| * | // | parallel for | task | * | // | parallel for | taskyield | * | + // | parallel for | barrier | + | // +------------------+-----------------+------------------------------------+ // | parallel sections| parallel | * | // | parallel sections| for | + | @@ -1165,6 +1181,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel sections|parallel sections| * | // | parallel sections| task | * | // | parallel sections| taskyield | * | + // | parallel sections| barrier | + | // +------------------+-----------------+------------------------------------+ // | task | parallel | * | // | task | for | + | @@ -1177,6 +1194,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | task |parallel sections| * | // | task | task | * | // | task | taskyield | * | + // | task | barrier | + | // +------------------+-----------------+------------------------------------+ if (Stack->getCurScope()) { auto ParentRegion = Stack->getParentDirective(); @@ -1209,6 +1227,14 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // atomic (TODO), or explicit task region. NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) || ParentRegion == OMPD_task; + } else if (CurrentRegion == OMPD_barrier) { + // OpenMP [2.16, Nesting of Regions] + // A barrier region may not be closely nested inside a worksharing, + // explicit task, critical(TODO), ordered(TODO), atomic(TODO), or master + // region. + NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) || + ParentRegion == OMPD_task || + ParentRegion == OMPD_master; } else if (isOpenMPWorksharingDirective(CurrentRegion) && !isOpenMPParallelDirective(CurrentRegion) && !isOpenMPSimdDirective(CurrentRegion)) { @@ -1318,6 +1344,13 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, "No associated statement allowed for 'omp taskyield' directive"); Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc); break; + case OMPD_barrier: + assert(ClausesWithImplicit.empty() && + "No clauses are allowed for 'omp barrier' directive"); + assert(AStmt == nullptr && + "No associated statement allowed for 'omp barrier' directive"); + Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc); + break; case OMPD_threadprivate: llvm_unreachable("OpenMP Directive is not allowed"); case OMPD_unknown: @@ -2066,6 +2099,11 @@ StmtResult Sema::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc, return OMPTaskyieldDirective::Create(Context, StartLoc, EndLoc); } +StmtResult Sema::ActOnOpenMPBarrierDirective(SourceLocation StartLoc, + SourceLocation EndLoc) { + return OMPBarrierDirective::Create(Context, StartLoc, EndLoc); +} + OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 741abb9..a562bfd 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -6568,6 +6568,17 @@ StmtResult TreeTransform::TransformOMPTaskyieldDirective( return Res; } +template +StmtResult +TreeTransform::TransformOMPBarrierDirective(OMPBarrierDirective *D) { + DeclarationNameInfo DirName; + getDerived().getSema().StartOpenMPDSABlock(OMPD_barrier, DirName, nullptr, + D->getLocStart()); + StmtResult Res = getDerived().TransformOMPExecutableDirective(D); + getDerived().getSema().EndOpenMPDSABlock(Res.get()); + return Res; +} + //===----------------------------------------------------------------------===// // OpenMP clause transformation //===----------------------------------------------------------------------===// diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index c9ecebb..9c6707a 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1995,6 +1995,11 @@ void ASTStmtReader::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *D) { VisitOMPExecutableDirective(D); } +void ASTStmtReader::VisitOMPBarrierDirective(OMPBarrierDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); +} + //===----------------------------------------------------------------------===// // ASTReader Implementation //===----------------------------------------------------------------------===// @@ -2533,6 +2538,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = OMPTaskyieldDirective::CreateEmpty(Context, Empty); break; + case STMT_OMP_BARRIER_DIRECTIVE: + S = OMPBarrierDirective::CreateEmpty(Context, Empty); + break; + case EXPR_CXX_OPERATOR_CALL: S = new (Context) CXXOperatorCallExpr(Context, Empty); break; diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 4ea0fd7..204c18a 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1897,6 +1897,12 @@ void ASTStmtWriter::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *D) { Code = serialization::STMT_OMP_TASKYIELD_DIRECTIVE; } +void ASTStmtWriter::VisitOMPBarrierDirective(OMPBarrierDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_BARRIER_DIRECTIVE; +} + //===----------------------------------------------------------------------===// // ASTWriter Implementation //===----------------------------------------------------------------------===// diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index b91f8e6..5b26f4e 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -742,6 +742,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::OMPParallelSectionsDirectiveClass: case Stmt::OMPTaskDirectiveClass: case Stmt::OMPTaskyieldDirectiveClass: + case Stmt::OMPBarrierDirectiveClass: llvm_unreachable("Stmt should not be in analyzer evaluation loop"); case Stmt::ObjCSubscriptRefExprClass: diff --git a/clang/test/OpenMP/barrier_ast_print.cpp b/clang/test/OpenMP/barrier_ast_print.cpp new file mode 100644 index 0000000..0ce344f --- /dev/null +++ b/clang/test/OpenMP/barrier_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() {} + +template +T tmain(T argc) { + static T a; +#pragma omp barrier + return a + argc; +} +// CHECK: static int a; +// CHECK-NEXT: #pragma omp barrier +// CHECK: static char a; +// CHECK-NEXT: #pragma omp barrier +// CHECK: static T a; +// CHECK-NEXT: #pragma omp barrier + +int main(int argc, char **argv) { + static int a; +// CHECK: static int a; +#pragma omp barrier + // CHECK-NEXT: #pragma omp barrier + return tmain(argc) + tmain(argv[0][0]) + a; +} + +#endif diff --git a/clang/test/OpenMP/barrier_messages.cpp b/clang/test/OpenMP/barrier_messages.cpp new file mode 100644 index 0000000..81ff84e --- /dev/null +++ b/clang/test/OpenMP/barrier_messages.cpp @@ -0,0 +1,110 @@ +// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ferror-limit 100 %s + +template +T tmain(T argc) { +#pragma omp barrier + ; +#pragma omp barrier untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp barrier'}} +#pragma omp barrier unknown // expected-warning {{extra tokens at the end of '#pragma omp barrier' are ignored}} + if (argc) +#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}} + if (argc) { +#pragma omp barrier + } + while (argc) +#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}} + while (argc) { +#pragma omp barrier + } + do +#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}} + while (argc) + ; + do { +#pragma omp barrier + } while (argc); + switch (argc) +#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}} + switch (argc) + case 1: +#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}} + switch (argc) + case 1: { +#pragma omp barrier + } + switch (argc) { +#pragma omp barrier + case 1: +#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}} + break; + default: { +#pragma omp barrier + } break; + } + for (;;) +#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}} + for (;;) { +#pragma omp barrier + } +label: +#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}} +label1 : { +#pragma omp barrier +} + + return T(); +} + +int main(int argc, char **argv) { +#pragma omp barrier + ; +#pragma omp barrier untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp barrier'}} +#pragma omp barrier unknown // expected-warning {{extra tokens at the end of '#pragma omp barrier' are ignored}} + if (argc) +#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}} + if (argc) { +#pragma omp barrier + } + while (argc) +#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}} + while (argc) { +#pragma omp barrier + } + do +#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}} + while (argc) + ; + do { +#pragma omp barrier + } while (argc); + switch (argc) +#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}} + switch (argc) + case 1: +#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}} + switch (argc) + case 1: { +#pragma omp barrier + } + switch (argc) { +#pragma omp barrier + case 1: +#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}} + break; + default: { +#pragma omp barrier + } break; + } + for (;;) +#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}} + for (;;) { +#pragma omp barrier + } +label: +#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}} +label1 : { +#pragma omp barrier +} + + return tmain(argc); +} diff --git a/clang/test/OpenMP/nesting_of_regions.cpp b/clang/test/OpenMP/nesting_of_regions.cpp index 84f3936..3ebd9ae 100644 --- a/clang/test/OpenMP/nesting_of_regions.cpp +++ b/clang/test/OpenMP/nesting_of_regions.cpp @@ -51,6 +51,11 @@ void foo() { #pragma omp taskyield bar(); } +#pragma omp parallel + { +#pragma omp barrier + bar(); + } // SIMD DIRECTIVE #pragma omp simd @@ -124,6 +129,11 @@ void foo() { #pragma omp taskyield // 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 barrier // expected-error {{OpenMP constructs may not be nested inside a simd region}} + bar(); + } // FOR DIRECTIVE #pragma omp for @@ -216,6 +226,11 @@ void foo() { #pragma omp taskyield bar(); } +#pragma omp for + for (int i = 0; i < 10; ++i) { +#pragma omp barrier // expected-error {{region cannot be closely nested inside 'for' region}} + bar(); + } // SECTIONS DIRECTIVE #pragma omp sections @@ -310,6 +325,10 @@ void foo() { { #pragma omp taskyield } +#pragma omp sections + { +#pragma omp barrier // expected-error {{region cannot be closely nested inside 'sections' region}} + } // SECTION DIRECTIVE #pragma omp section // expected-error {{orphaned 'omp section' directives are prohibited, it must be closely nested to a sections region}} @@ -430,6 +449,14 @@ void foo() { bar(); } } +#pragma omp sections + { +#pragma omp section + { +#pragma omp barrier // expected-error {{region cannot be closely nested inside 'section' region}} + bar(); + } + } // SINGLE DIRECTIVE #pragma omp single @@ -513,6 +540,11 @@ void foo() { #pragma omp taskyield bar(); } +#pragma omp single + { +#pragma omp barrier // expected-error {{region cannot be closely nested inside 'single' region}} + bar(); + } // MASTER DIRECTIVE #pragma omp master @@ -596,6 +628,11 @@ void foo() { #pragma omp taskyield bar(); } +#pragma omp master + { +#pragma omp barrier // expected-error {{region cannot be closely nested inside 'master' region}} + bar(); + } // PARALLEL FOR DIRECTIVE #pragma omp parallel for @@ -688,6 +725,11 @@ void foo() { #pragma omp taskyield bar(); } +#pragma omp parallel for + for (int i = 0; i < 10; ++i) { +#pragma omp barrier // expected-error {{region cannot be closely nested inside 'parallel for' region}} + bar(); + } // PARALLEL SECTIONS DIRECTIVE #pragma omp parallel sections @@ -779,6 +821,10 @@ void foo() { { #pragma omp taskyield } +#pragma omp parallel sections + { +#pragma omp barrier // expected-error {{region cannot be closely nested inside 'parallel sections' region}} + } // TASK DIRECTIVE #pragma omp task @@ -824,6 +870,11 @@ void foo() { #pragma omp taskyield bar(); } +#pragma omp task + { +#pragma omp barrier // expected-error {{region cannot be closely nested inside 'task' region}} + bar(); + } } void foo() { @@ -876,6 +927,11 @@ void foo() { #pragma omp taskyield bar(); } +#pragma omp parallel + { +#pragma omp barrier + bar(); + } // SIMD DIRECTIVE #pragma omp simd @@ -942,6 +998,11 @@ void foo() { #pragma omp taskyield // 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 barrier // expected-error {{OpenMP constructs may not be nested inside a simd region}} + bar(); + } // FOR DIRECTIVE #pragma omp for @@ -1025,6 +1086,11 @@ void foo() { #pragma omp taskyield bar(); } +#pragma omp for + for (int i = 0; i < 10; ++i) { +#pragma omp barrier // expected-error {{region cannot be closely nested inside 'for' region}} + bar(); + } // SECTIONS DIRECTIVE #pragma omp sections @@ -1105,7 +1171,11 @@ void foo() { } #pragma omp sections { -#pragma omp task +#pragma omp taskyield + } +#pragma omp sections + { +#pragma omp barrier // expected-error {{region cannot be closely nested inside 'sections' region}} bar(); } @@ -1228,6 +1298,14 @@ void foo() { bar(); } } +#pragma omp sections + { +#pragma omp section + { +#pragma omp barrier // expected-error {{region cannot be closely nested inside 'section' region}} + bar(); + } + } // SINGLE DIRECTIVE #pragma omp single @@ -1306,6 +1384,11 @@ void foo() { #pragma omp taskyield bar(); } +#pragma omp single + { +#pragma omp barrier // expected-error {{region cannot be closely nested inside 'single' region}} + bar(); + } // MASTER DIRECTIVE #pragma omp master @@ -1389,6 +1472,11 @@ void foo() { #pragma omp taskyield bar(); } +#pragma omp master + { +#pragma omp barrier // expected-error {{region cannot be closely nested inside 'master' region}} + bar(); + } // PARALLEL FOR DIRECTIVE #pragma omp parallel for @@ -1480,6 +1568,11 @@ void foo() { #pragma omp taskyield bar(); } +#pragma omp parallel for + for (int i = 0; i < 10; ++i) { +#pragma omp barrier // expected-error {{region cannot be closely nested inside 'parallel for' region}} + bar(); + } // PARALLEL SECTIONS DIRECTIVE #pragma omp parallel sections @@ -1569,6 +1662,10 @@ void foo() { { #pragma omp taskyield } +#pragma omp parallel sections + { +#pragma omp barrier // expected-error {{region cannot be closely nested inside 'parallel sections' region}} + } // TASK DIRECTIVE #pragma omp task @@ -1614,6 +1711,11 @@ void foo() { #pragma omp taskyield bar(); } +#pragma omp task + { +#pragma omp barrier // expected-error {{region cannot be closely nested inside 'task' region}} + bar(); + } return foo(); } diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index b22d925..fe46e3b 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -1865,6 +1865,7 @@ public: void VisitOMPParallelSectionsDirective(const OMPParallelSectionsDirective *D); void VisitOMPTaskDirective(const OMPTaskDirective *D); void VisitOMPTaskyieldDirective(const OMPTaskyieldDirective *D); + void VisitOMPBarrierDirective(const OMPBarrierDirective *D); private: void AddDeclarationNameInfo(const Stmt *S); @@ -2347,6 +2348,10 @@ EnqueueVisitor::VisitOMPTaskyieldDirective(const OMPTaskyieldDirective *D) { VisitOMPExecutableDirective(D); } +void EnqueueVisitor::VisitOMPBarrierDirective(const OMPBarrierDirective *D) { + VisitOMPExecutableDirective(D); +} + void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, const Stmt *S) { EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU,RegionOfInterest)).Visit(S); } @@ -4041,6 +4046,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return cxstring::createRef("OMPTaskDirective"); case CXCursor_OMPTaskyieldDirective: return cxstring::createRef("OMPTaskyieldDirective"); + case CXCursor_OMPBarrierDirective: + return cxstring::createRef("OMPBarrierDirective"); } llvm_unreachable("Unhandled CXCursorKind"); diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index f96e17f..634918c 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -550,6 +550,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent, case Stmt::OMPTaskyieldDirectiveClass: K = CXCursor_OMPTaskyieldDirective; break; + case Stmt::OMPBarrierDirectiveClass: + K = CXCursor_OMPBarrierDirective; + break; } CXCursor C = { K, 0, { Parent, S, TU } }; -- 2.7.4