From d9ed09f7a5f149ea3ed7904f83ed70bf12963842 Mon Sep 17 00:00:00 2001 From: Alexander Musman Date: Mon, 21 Jul 2014 09:42:05 +0000 Subject: [PATCH] [OPENMP] Parsing/Sema of the OpenMP directive 'critical'. llvm-svn: 213510 --- clang/include/clang-c/Index.h | 12 +- clang/include/clang/AST/DataRecursiveASTVisitor.h | 5 + clang/include/clang/AST/RecursiveASTVisitor.h | 5 + clang/include/clang/AST/StmtOpenMP.h | 63 ++++ clang/include/clang/Basic/DiagnosticParseKinds.td | 2 + clang/include/clang/Basic/DiagnosticSemaKinds.td | 4 + clang/include/clang/Basic/OpenMPKinds.def | 1 + clang/include/clang/Basic/StmtNodes.td | 1 + clang/include/clang/Sema/Sema.h | 10 +- clang/include/clang/Serialization/ASTBitCodes.h | 1 + clang/lib/AST/Stmt.cpp | 20 ++ clang/lib/AST/StmtPrinter.cpp | 10 + clang/lib/AST/StmtProfile.cpp | 5 + 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 | 25 +- clang/lib/Sema/SemaOpenMP.cpp | 114 ++++++- clang/lib/Sema/TreeTransform.h | 29 +- clang/lib/Serialization/ASTReaderStmt.cpp | 10 + clang/lib/Serialization/ASTWriterStmt.cpp | 7 + clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 1 + clang/test/OpenMP/critical_ast_print.cpp | 29 ++ clang/test/OpenMP/critical_messages.cpp | 72 +++++ clang/test/OpenMP/nesting_of_regions.cpp | 355 +++++++++++++++++++++- clang/tools/libclang/CIndex.cpp | 10 + clang/tools/libclang/CXCursor.cpp | 3 + 28 files changed, 779 insertions(+), 24 deletions(-) create mode 100644 clang/test/OpenMP/critical_ast_print.cpp create mode 100644 clang/test/OpenMP/critical_messages.cpp diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 7b80841..e4d3ebd 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2171,21 +2171,25 @@ enum CXCursorKind { */ CXCursor_OMPMasterDirective = 241, + /** \brief OpenMP critical directive. + */ + CXCursor_OMPCriticalDirective = 242, + /** \brief OpenMP taskyield directive. */ - CXCursor_OMPTaskyieldDirective = 242, + CXCursor_OMPTaskyieldDirective = 243, /** \brief OpenMP barrier directive. */ - CXCursor_OMPBarrierDirective = 243, + CXCursor_OMPBarrierDirective = 244, /** \brief OpenMP taskwait directive. */ - CXCursor_OMPTaskwaitDirective = 244, + CXCursor_OMPTaskwaitDirective = 245, /** \brief Windows Structured Exception Handling's leave statement. */ - CXCursor_SEHLeaveStmt = 245, + CXCursor_SEHLeaveStmt = 246, CXCursor_LastStmt = CXCursor_SEHLeaveStmt, diff --git a/clang/include/clang/AST/DataRecursiveASTVisitor.h b/clang/include/clang/AST/DataRecursiveASTVisitor.h index ea3bb17..072bd7b 100644 --- a/clang/include/clang/AST/DataRecursiveASTVisitor.h +++ b/clang/include/clang/AST/DataRecursiveASTVisitor.h @@ -2300,6 +2300,11 @@ DEF_TRAVERSE_STMT(OMPSingleDirective, DEF_TRAVERSE_STMT(OMPMasterDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPCriticalDirective, { + TRY_TO(TraverseDeclarationNameInfo(S->getDirectiveName())); + 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 e176a5f..2953e7a 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2322,6 +2322,11 @@ DEF_TRAVERSE_STMT(OMPSingleDirective, DEF_TRAVERSE_STMT(OMPMasterDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPCriticalDirective, { + TRY_TO(TraverseDeclarationNameInfo(S->getDirectiveName())); + 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 62af6a2..2c38c16 100644 --- a/clang/include/clang/AST/StmtOpenMP.h +++ b/clang/include/clang/AST/StmtOpenMP.h @@ -585,6 +585,69 @@ public: } }; +/// \brief This represents '#pragma omp critical' directive. +/// +/// \code +/// #pragma omp critical +/// \endcode +/// +class OMPCriticalDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Name of the directive. + DeclarationNameInfo DirName; + /// \brief Build directive with the given start and end location. + /// + /// \param Name Name of the directive. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// + OMPCriticalDirective(const DeclarationNameInfo &Name, SourceLocation StartLoc, + SourceLocation EndLoc) + : OMPExecutableDirective(this, OMPCriticalDirectiveClass, OMPD_critical, + StartLoc, EndLoc, 0, 1), + DirName(Name) {} + + /// \brief Build an empty directive. + /// + explicit OMPCriticalDirective() + : OMPExecutableDirective(this, OMPCriticalDirectiveClass, OMPD_critical, + SourceLocation(), SourceLocation(), 0, 1), + DirName() {} + + /// \brief Set name of the directive. + /// + /// \param Name Name of the directive. + /// + void setDirectiveName(const DeclarationNameInfo &Name) { DirName = Name; } + +public: + /// \brief Creates directive. + /// + /// \param C AST context. + /// \param Name Name of the directive. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param AssociatedStmt Statement, associated with the directive. + /// + static OMPCriticalDirective * + Create(const ASTContext &C, const DeclarationNameInfo &Name, + SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt); + + /// \brief Creates an empty directive. + /// + /// \param C AST context. + /// + static OMPCriticalDirective *CreateEmpty(const ASTContext &C, EmptyShell); + + /// \brief Return name of the directive. + /// + DeclarationNameInfo getDirectiveName() const { return DirName; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPCriticalDirectiveClass; + } +}; + /// \brief This represents '#pragma omp parallel for' directive. /// /// \code diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 1956afc8..34ac6a4 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -910,6 +910,8 @@ def err_omp_more_one_clause : Error< "directive '#pragma omp %0' cannot contain more than one '%1' clause">; def err_omp_immediate_directive : Error< "'#pragma omp %0' cannot be an immediate substatement">; +def err_omp_expected_identifier_for_critical : Error< + "expected identifier specifying the name of the 'omp critical' directive">; // Pragma loop support. def err_pragma_loop_invalid_option : Error< diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 98f08b2..885cf36 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7127,6 +7127,10 @@ def err_omp_prohibited_region : Error< "%select{|; perhaps you forget to enclose 'omp %3' directive into a parallel region?}2">; def err_omp_prohibited_region_simd : Error< "OpenMP constructs may not be nested inside a simd region">; +def err_omp_prohibited_region_critical_same_name : Error< + "cannot nest 'critical' regions having the same name %0">; +def note_omp_previous_critical_region : Note< + "previous 'critical' region starts here">; def err_omp_sections_not_compound_stmt : Error< "the statement for '#pragma omp sections' must be a compound statement">; def err_omp_parallel_sections_not_compound_stmt : Error< diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def index f43a8b5..a871ff2 100644 --- a/clang/include/clang/Basic/OpenMPKinds.def +++ b/clang/include/clang/Basic/OpenMPKinds.def @@ -65,6 +65,7 @@ OPENMP_DIRECTIVE(sections) OPENMP_DIRECTIVE(section) OPENMP_DIRECTIVE(single) OPENMP_DIRECTIVE(master) +OPENMP_DIRECTIVE(critical) OPENMP_DIRECTIVE(taskyield) OPENMP_DIRECTIVE(barrier) OPENMP_DIRECTIVE(taskwait) diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td index fd4546a..28e0f4c 100644 --- a/clang/include/clang/Basic/StmtNodes.td +++ b/clang/include/clang/Basic/StmtNodes.td @@ -185,6 +185,7 @@ def OMPSectionsDirective : DStmt; def OMPSectionDirective : DStmt; def OMPSingleDirective : DStmt; def OMPMasterDirective : DStmt; +def OMPCriticalDirective : 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 bd4493b..6d8b62d 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -7303,14 +7303,15 @@ public: DeclGroupPtrTy ActOnOpenMPThreadprivateDirective( SourceLocation Loc, ArrayRef VarList); - // \brief Builds a new OpenMPThreadPrivateDecl and checks its correctness. + /// \brief Builds a new OpenMPThreadPrivateDecl and checks its correctness. OMPThreadPrivateDecl *CheckOMPThreadPrivateDecl( SourceLocation Loc, ArrayRef VarList); - // brief Initialization of captured region for OpenMP region. + /// \brief Initialization of captured region for OpenMP region. void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope); StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, + const DeclarationNameInfo &DirName, ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, @@ -7351,6 +7352,11 @@ public: /// associated statement. StmtResult ActOnOpenMPMasterDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc); + /// \brief Called on well-formed '\#pragma omp critical' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName, + 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 ae7f44b..8c1b91a 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1347,6 +1347,7 @@ namespace clang { STMT_OMP_SECTION_DIRECTIVE, STMT_OMP_SINGLE_DIRECTIVE, STMT_OMP_MASTER_DIRECTIVE, + STMT_OMP_CRITICAL_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 a5ca49d..b011f9f 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -1496,6 +1496,26 @@ OMPMasterDirective *OMPMasterDirective::CreateEmpty(const ASTContext &C, return new (Mem) OMPMasterDirective(); } +OMPCriticalDirective *OMPCriticalDirective::Create( + const ASTContext &C, const DeclarationNameInfo &Name, + SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPCriticalDirective), + llvm::alignOf()); + void *Mem = C.Allocate(Size + sizeof(Stmt *)); + OMPCriticalDirective *Dir = + new (Mem) OMPCriticalDirective(Name, StartLoc, EndLoc); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPCriticalDirective *OMPCriticalDirective::CreateEmpty(const ASTContext &C, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPCriticalDirective), + llvm::alignOf()); + void *Mem = C.Allocate(Size + sizeof(Stmt *)); + return new (Mem) OMPCriticalDirective(); +} + 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 0267bcc..9c00eea 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -834,6 +834,16 @@ void StmtPrinter::VisitOMPMasterDirective(OMPMasterDirective *Node) { PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPCriticalDirective(OMPCriticalDirective *Node) { + Indent() << "#pragma omp critical"; + if (Node->getDirectiveName().getName()) { + OS << " ("; + Node->getDirectiveName().printName(OS); + OS << ")"; + } + 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 0cd0f62..56827ed 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -393,6 +393,11 @@ void StmtProfiler::VisitOMPMasterDirective(const OMPMasterDirective *S) { VisitOMPExecutableDirective(S); } +void StmtProfiler::VisitOMPCriticalDirective(const OMPCriticalDirective *S) { + VisitOMPExecutableDirective(S); + VisitName(S->getDirectiveName().getName()); +} + void StmtProfiler::VisitOMPParallelForDirective(const OMPParallelForDirective *S) { VisitOMPExecutableDirective(S); diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index f304513..869b00c 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -257,6 +257,7 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, case OMPD_threadprivate: case OMPD_section: case OMPD_master: + case OMPD_critical: case OMPD_taskyield: case OMPD_barrier: case OMPD_taskwait: diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index cd970c7..8256638 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -197,6 +197,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { case Stmt::OMPMasterDirectiveClass: EmitOMPMasterDirective(cast(*S)); break; + case Stmt::OMPCriticalDirectiveClass: + EmitOMPCriticalDirective(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 7731c76..e4ef5a6 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -94,6 +94,10 @@ void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &) { llvm_unreachable("CodeGen for 'omp master' is not supported yet."); } +void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &) { + llvm_unreachable("CodeGen for 'omp critical' 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 3692b02..66bf78f 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -1928,6 +1928,7 @@ public: void EmitOMPSectionDirective(const OMPSectionDirective &S); void EmitOMPSingleDirective(const OMPSingleDirective &S); void EmitOMPMasterDirective(const OMPMasterDirective &S); + void EmitOMPCriticalDirective(const OMPCriticalDirective &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 cf99178..79cf6af 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -91,6 +91,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { case OMPD_section: case OMPD_single: case OMPD_master: + case OMPD_critical: case OMPD_parallel_for: case OMPD_parallel_sections: Diag(Tok, diag::err_omp_unexpected_directive) @@ -109,9 +110,9 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { /// /// executable-directive: /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' | -/// 'section' | 'single' | 'master' | 'parallel for' | -/// 'parallel sections' | 'task' | 'taskyield' | 'barrier' | 'taskwait' -/// {clause} annot_pragma_openmp_end +/// 'section' | 'single' | 'master' | 'critical' [ '(' ')' ] | +/// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' | +/// 'barrier' | 'taskwait' {clause} annot_pragma_openmp_end /// StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { @@ -162,10 +163,26 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { case OMPD_single: case OMPD_section: case OMPD_master: + case OMPD_critical: case OMPD_parallel_for: case OMPD_parallel_sections: case OMPD_task: { ConsumeToken(); + // Parse directive name of the 'critical' directive if any. + if (DKind == OMPD_critical) { + BalancedDelimiterTracker T(*this, tok::l_paren, + tok::annot_pragma_openmp_end); + if (!T.consumeOpen()) { + if (Tok.isAnyIdentifier()) { + DirName = + DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation()); + ConsumeAnyToken(); + } else { + Diag(Tok, diag::err_omp_expected_identifier_for_critical); + } + T.consumeClose(); + } + } if (isOpenMPLoopDirective(DKind)) ScopeFlags |= Scope::OpenMPLoopDirectiveScope; @@ -215,7 +232,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { } if (CreateDirective) Directive = Actions.ActOnOpenMPExecutableDirective( - DKind, Clauses, AssociatedStmt.get(), Loc, EndLoc); + DKind, DirName, Clauses, AssociatedStmt.get(), Loc, EndLoc); // Exit scope. Actions.EndOpenMPDSABlock(Directive.get()); diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index f2421da..c0a6d60 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -155,6 +155,9 @@ public: DSAVarData hasInnermostDSA(VarDecl *D, ClausesPredicate CPred, DirectivesPredicate DPred, bool FromParent); + /// \brief Finds a directive which matches specified \a DPred predicate. + template + bool hasDirective(NamedDirectivesPredicate DPred, bool FromParent); /// \brief Returns currently analyzed directive. OpenMPDirectiveKind getCurrentDirective() const { @@ -493,6 +496,20 @@ DSAStackTy::hasInnermostDSA(VarDecl *D, ClausesPredicate CPred, return DSAVarData(); } +template +bool DSAStackTy::hasDirective(NamedDirectivesPredicate DPred, bool FromParent) { + auto StartI = std::next(Stack.rbegin()); + auto EndI = std::prev(Stack.rend()); + if (FromParent && StartI != EndI) { + StartI = std::next(StartI); + } + for (auto I = StartI, EE = EndI; I != EE; ++I) { + if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc)) + return true; + } + return false; +} + void Sema::InitDataSharingAttributesStack() { VarDataSharingAttributesStack = new DSAStackTy(*this); } @@ -1008,6 +1025,14 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { Params); break; } + case OMPD_critical: { + 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); @@ -1067,9 +1092,10 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { } } -bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, - OpenMPDirectiveKind CurrentRegion, - SourceLocation StartLoc) { +static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, + OpenMPDirectiveKind CurrentRegion, + const DeclarationNameInfo &CurrentName, + SourceLocation StartLoc) { // Allowed nesting of constructs // +------------------+-----------------+------------------------------------+ // | Parent directive | Child directive | Closely (!), No-Closely(+), Both(*)| @@ -1077,6 +1103,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel | parallel | * | // | parallel | for | * | // | parallel | master | * | + // | parallel | critical | * | // | parallel | simd | * | // | parallel | sections | * | // | parallel | section | + | @@ -1091,6 +1118,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | for | parallel | * | // | for | for | + | // | for | master | + | + // | for | critical | * | // | for | simd | * | // | for | sections | + | // | for | section | + | @@ -1105,6 +1133,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | master | parallel | * | // | master | for | + | // | master | master | * | + // | master | critical | * | // | master | simd | * | // | master | sections | + | // | master | section | + | @@ -1116,9 +1145,25 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | master | barrier | + | // | master | taskwait | * | // +------------------+-----------------+------------------------------------+ + // | critical | parallel | * | + // | critical | for | + | + // | critical | master | * | + // | critical | critical | * (should have dirrerent names) | + // | critical | simd | * | + // | critical | sections | + | + // | critical | section | + | + // | critical | single | + | + // | critical | parallel for | * | + // | critical |parallel sections| * | + // | critical | task | * | + // | critical | taskyield | * | + // | critical | barrier | + | + // | critical | taskwait | * | + // +------------------+-----------------+------------------------------------+ // | simd | parallel | | // | simd | for | | // | simd | master | | + // | simd | critical | | // | simd | simd | | // | simd | sections | | // | simd | section | | @@ -1133,6 +1178,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | sections | parallel | * | // | sections | for | + | // | sections | master | + | + // | sections | critical | * | // | sections | simd | * | // | sections | sections | + | // | sections | section | * | @@ -1147,6 +1193,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | section | parallel | * | // | section | for | + | // | section | master | + | + // | section | critical | * | // | section | simd | * | // | section | sections | + | // | section | section | + | @@ -1161,6 +1208,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | single | parallel | * | // | single | for | + | // | single | master | + | + // | single | critical | * | // | single | simd | * | // | single | sections | + | // | single | section | + | @@ -1175,6 +1223,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel for | parallel | * | // | parallel for | for | + | // | parallel for | master | + | + // | parallel for | critical | * | // | parallel for | simd | * | // | parallel for | sections | + | // | parallel for | section | + | @@ -1189,6 +1238,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel sections| parallel | * | // | parallel sections| for | + | // | parallel sections| master | + | + // | parallel sections| critical | + | // | parallel sections| simd | * | // | parallel sections| sections | + | // | parallel sections| section | * | @@ -1203,6 +1253,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | task | parallel | * | // | task | for | + | // | task | master | + | + // | task | critical | * | // | task | simd | * | // | task | sections | + | // | task | section | + | @@ -1245,14 +1296,44 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // atomic (TODO), or explicit task region. NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) || ParentRegion == OMPD_task; + } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) { + // OpenMP [2.16, Nesting of Regions] + // A critical region may not be nested (closely or otherwise) inside a + // critical region with the same name. Note that this restriction is not + // sufficient to prevent deadlock. + SourceLocation PreviousCriticalLoc; + bool DeadLock = + Stack->hasDirective([CurrentName, &PreviousCriticalLoc]( + OpenMPDirectiveKind K, + const DeclarationNameInfo &DNI, + SourceLocation Loc) + ->bool { + if (K == OMPD_critical && + DNI.getName() == CurrentName.getName()) { + PreviousCriticalLoc = Loc; + return true; + } else + return false; + }, + false /* skip top directive */); + if (DeadLock) { + SemaRef.Diag(StartLoc, + diag::err_omp_prohibited_region_critical_same_name) + << CurrentName.getName(); + if (PreviousCriticalLoc.isValid()) + SemaRef.Diag(PreviousCriticalLoc, + diag::note_omp_previous_critical_region); + return true; + } } 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 + // explicit task, critical, ordered(TODO), atomic(TODO), or master // region. NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) || ParentRegion == OMPD_task || - ParentRegion == OMPD_master; + ParentRegion == OMPD_master || + ParentRegion == OMPD_critical; } else if (isOpenMPWorksharingDirective(CurrentRegion) && !isOpenMPParallelDirective(CurrentRegion) && !isOpenMPSimdDirective(CurrentRegion)) { @@ -1263,7 +1344,8 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, NestingProhibited = (isOpenMPWorksharingDirective(ParentRegion) && !isOpenMPSimdDirective(ParentRegion)) || ParentRegion == OMPD_task || - ParentRegion == OMPD_master; + ParentRegion == OMPD_master || + ParentRegion == OMPD_critical; ShouldBeInParallelRegion = true; } if (NestingProhibited) { @@ -1277,12 +1359,13 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, } StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, + const DeclarationNameInfo &DirName, ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { StmtResult Res = StmtError(); - if (CheckNestingOfRegions(*this, DSAStack, Kind, StartLoc)) + if (CheckNestingOfRegions(*this, DSAStack, Kind, DirName, StartLoc)) return StmtError(); llvm::SmallVector ClausesWithImplicit; @@ -1343,6 +1426,11 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, "No clauses are allowed for 'omp master' directive"); Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc); break; + case OMPD_critical: + assert(ClausesWithImplicit.empty() && + "No clauses are allowed for 'omp critical' directive"); + Res = ActOnOpenMPCriticalDirective(DirName, AStmt, StartLoc, EndLoc); + break; case OMPD_parallel_for: Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); @@ -2042,6 +2130,18 @@ StmtResult Sema::ActOnOpenMPMasterDirective(Stmt *AStmt, return OMPMasterDirective::Create(Context, StartLoc, EndLoc, AStmt); } +StmtResult +Sema::ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc) { + assert(AStmt && isa(AStmt) && "Captured statement expected"); + + getCurFunction()->setHasBranchProtectedScope(); + + return OMPCriticalDirective::Create(Context, DirName, 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 1f648d4..ba67df7 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -1298,12 +1298,12 @@ public: /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. StmtResult RebuildOMPExecutableDirective(OpenMPDirectiveKind Kind, + DeclarationNameInfo DirName, ArrayRef Clauses, - Stmt *AStmt, - SourceLocation StartLoc, + Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { - return getSema().ActOnOpenMPExecutableDirective(Kind, Clauses, AStmt, - StartLoc, EndLoc); + return getSema().ActOnOpenMPExecutableDirective(Kind, DirName, Clauses, + AStmt, StartLoc, EndLoc); } /// \brief Build a new OpenMP 'if' clause. @@ -6445,9 +6445,16 @@ StmtResult TreeTransform::TransformOMPExecutableDirective( return StmtError(); } + // Transform directive name for 'omp critical' directive. + DeclarationNameInfo DirName; + if (D->getDirectiveKind() == OMPD_critical) { + DirName = cast(D)->getDirectiveName(); + DirName = getDerived().TransformDeclarationNameInfo(DirName); + } + return getDerived().RebuildOMPExecutableDirective( - D->getDirectiveKind(), TClauses, AssociatedStmt.get(), D->getLocStart(), - D->getLocEnd()); + D->getDirectiveKind(), DirName, TClauses, AssociatedStmt.get(), + D->getLocStart(), D->getLocEnd()); } template @@ -6528,6 +6535,16 @@ TreeTransform::TransformOMPMasterDirective(OMPMasterDirective *D) { } template +StmtResult +TreeTransform::TransformOMPCriticalDirective(OMPCriticalDirective *D) { + getDerived().getSema().StartOpenMPDSABlock( + OMPD_critical, D->getDirectiveName(), 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 99c9827..e8a8428 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1968,6 +1968,12 @@ void ASTStmtReader::VisitOMPMasterDirective(OMPMasterDirective *D) { VisitOMPExecutableDirective(D); } +void ASTStmtReader::VisitOMPCriticalDirective(OMPCriticalDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); + ReadDeclarationNameInfo(D->DirName, Record, Idx); +} + void ASTStmtReader::VisitOMPParallelForDirective(OMPParallelForDirective *D) { VisitStmt(D); // Two fields (NumClauses and CollapsedNum) were read in ReadStmtFromStream. @@ -2521,6 +2527,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = OMPMasterDirective::CreateEmpty(Context, Empty); break; + case STMT_OMP_CRITICAL_DIRECTIVE: + S = OMPCriticalDirective::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 db6adbc..dd78c24 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1868,6 +1868,13 @@ void ASTStmtWriter::VisitOMPMasterDirective(OMPMasterDirective *D) { Code = serialization::STMT_OMP_MASTER_DIRECTIVE; } +void ASTStmtWriter::VisitOMPCriticalDirective(OMPCriticalDirective *D) { + VisitStmt(D); + VisitOMPExecutableDirective(D); + Writer.AddDeclarationNameInfo(D->getDirectiveName(), Record); + Code = serialization::STMT_OMP_CRITICAL_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 8da1d8e..af2ef5e 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -738,6 +738,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::OMPSectionDirectiveClass: case Stmt::OMPSingleDirectiveClass: case Stmt::OMPMasterDirectiveClass: + case Stmt::OMPCriticalDirectiveClass: case Stmt::OMPParallelForDirectiveClass: case Stmt::OMPParallelSectionsDirectiveClass: case Stmt::OMPTaskDirectiveClass: diff --git a/clang/test/OpenMP/critical_ast_print.cpp b/clang/test/OpenMP/critical_ast_print.cpp new file mode 100644 index 0000000..98ece88 --- /dev/null +++ b/clang/test/OpenMP/critical_ast_print.cpp @@ -0,0 +1,29 @@ +// 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 critical + a=2; +// CHECK-NEXT: #pragma omp critical +// CHECK-NEXT: a = 2; +// CHECK-NEXT: ++a; + ++a; +#pragma omp critical (the_name) + foo(); +// CHECK-NEXT: #pragma omp critical (the_name) +// CHECK-NEXT: foo(); +// CHECK-NEXT: return 0; + return 0; +} + +#endif diff --git a/clang/test/OpenMP/critical_messages.cpp b/clang/test/OpenMP/critical_messages.cpp new file mode 100644 index 0000000..08df9e0 --- /dev/null +++ b/clang/test/OpenMP/critical_messages.cpp @@ -0,0 +1,72 @@ +// RUN: %clang_cc1 -verify -fopenmp=libiomp5 %s + +int foo(); + +int main() { + #pragma omp critical + ; + #pragma omp critical untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp critical'}} + #pragma omp critical unknown // expected-warning {{extra tokens at the end of '#pragma omp critical' are ignored}} + #pragma omp critical ( // expected-error {{expected identifier}} expected-error {{expected ')'}} expected-note {{to match this '('}} + #pragma omp critical ( + // expected-error {{expected identifier}} expected-error {{expected ')'}} expected-note {{to match this '('}} + #pragma omp critical (name // expected-error {{expected ')'}} expected-note {{to match this '('}} + #pragma omp critical (name1) + foo(); + { + #pragma omp critical + } // expected-error {{expected statement}} + #pragma omp critical (name) // expected-note {{previous 'critical' region starts here}} + #pragma omp critical + for (int i = 0; i < 10; ++i) { + foo(); + #pragma omp parallel + #pragma omp for + for (int j = 0; j < 10; j++) { + foo(); + #pragma omp critical(name) // expected-error {{cannot nest 'critical' regions having the same name 'name'}} + foo(); + } + } + #pragma omp critical (name) + #pragma omp critical + for (int i = 0; i < 10; ++i) { + foo(); + #pragma omp parallel + #pragma omp for + for (int j = 0; j < 10; j++) { + #pragma omp critical + foo(); + } + } + #pragma omp critical (name) + #pragma omp critical + for (int i = 0; i < 10; ++i) { + foo(); + #pragma omp parallel + #pragma omp for + for (int j = 0; j < 10; j++) { + #pragma omp critical (nam) + foo(); + } + } + + return 0; +} + +int foo() { + L1: + foo(); + #pragma omp critical + { + foo(); + goto L1; // expected-error {{use of undeclared label 'L1'}} + } + goto L2; // expected-error {{use of undeclared label 'L2'}} + #pragma omp critical + { + L2: + foo(); + } + + return 0; +} diff --git a/clang/test/OpenMP/nesting_of_regions.cpp b/clang/test/OpenMP/nesting_of_regions.cpp index 534c8a5..7224ceb 100644 --- a/clang/test/OpenMP/nesting_of_regions.cpp +++ b/clang/test/OpenMP/nesting_of_regions.cpp @@ -33,6 +33,11 @@ void foo() { bar(); } #pragma omp parallel +#pragma omp critical + { + bar(); + } +#pragma omp parallel #pragma omp parallel for for (int i = 0; i < 10; ++i) ; @@ -111,6 +116,13 @@ void foo() { } #pragma omp simd for (int i = 0; i < 10; ++i) { +#pragma omp critical // 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) ; @@ -193,7 +205,13 @@ void foo() { bar(); } } - +#pragma omp for + for (int i = 0; i < 10; ++i) { +#pragma omp critical + { + bar(); + } + } #pragma omp for for (int i = 0; i < 10; ++i) { #pragma omp parallel @@ -318,6 +336,25 @@ void foo() { } #pragma omp sections { +#pragma omp parallel + { +#pragma omp critical(A) // OK + { + bar(); + } +#pragma omp for // OK + for (int i = 0; i < 10; ++i) + ; +#pragma omp critical // OK + { + bar(); + } + } +#pragma omp critical(A) // expected-error {{statement in 'omp sections' directive must be enclosed into a section region}} + bar(); + } +#pragma omp sections + { #pragma omp parallel for for (int i = 0; i < 10; ++i) ; @@ -409,6 +446,8 @@ void foo() { bar(); #pragma omp master // expected-error {{region cannot be closely nested inside 'section' region}} bar(); +#pragma omp critical + bar(); } } #pragma omp sections @@ -520,6 +559,13 @@ void foo() { } #pragma omp single { +#pragma omp critical + { + 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(); @@ -613,6 +659,13 @@ void foo() { } #pragma omp master { +#pragma omp critical + { + 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(); @@ -671,6 +724,125 @@ void foo() { bar(); } +// CRITICAL DIRECTIVE +#pragma omp critical + { +#pragma omp for // expected-error {{region cannot be closely nested inside 'critical' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp critical + { +#pragma omp simd + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp critical + { +#pragma omp parallel + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp critical + { +#pragma omp single // expected-error {{region cannot be closely nested inside 'critical' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}} + { + bar(); + } + } +#pragma omp critical + { +#pragma omp master // OK, though second 'master' is redundant + { + bar(); + } + } +#pragma omp critical + { +#pragma omp critical + { + bar(); + } + } +#pragma omp critical + { +#pragma omp sections // expected-error {{region cannot be closely nested inside 'critical' region; perhaps you forget to enclose 'omp sections' directive into a parallel region?}} + { + bar(); + } + } +#pragma omp critical + { +#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 critical + { +#pragma omp parallel for + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp critical + { +#pragma omp parallel sections + { + bar(); + } + } +#pragma omp critical + { +#pragma omp task + { + bar(); + } + } +#pragma omp critical + { +#pragma omp taskyield + bar(); + } +#pragma omp critical + { +#pragma omp barrier // expected-error {{region cannot be closely nested inside 'critical' region}} + bar(); + } +#pragma omp critical + { +#pragma omp taskwait + bar(); + } +#pragma omp critical(Tuzik) + { +#pragma omp critical(grelka) + bar(); + } +#pragma omp critical(Belka)// expected-note {{previous 'critical' region starts here}} + { +#pragma omp critical(Belka) // expected-error {{cannot nest 'critical' regions having the same name 'Belka'}} + { +#pragma omp critical(Tuzik) + { +#pragma omp parallel +#pragma omp critical(grelka) + { + bar(); + } + } + } + } + // PARALLEL FOR DIRECTIVE #pragma omp parallel for for (int i = 0; i < 10; ++i) { @@ -722,6 +894,14 @@ void foo() { #pragma omp parallel for for (int i = 0; i < 10; ++i) { +#pragma omp critical + { + bar(); + } + } + +#pragma omp parallel for + for (int i = 0; i < 10; ++i) { #pragma omp parallel { #pragma omp single // OK @@ -824,6 +1004,14 @@ void foo() { } #pragma omp parallel sections { +#pragma omp section + { +#pragma omp critical + bar(); + } + } +#pragma omp parallel sections + { #pragma omp parallel { #pragma omp single // OK @@ -898,6 +1086,10 @@ void foo() { #pragma omp master // expected-error {{region cannot be closely nested inside 'task' region}} bar(); #pragma omp task +#pragma omp critical + bar(); + +#pragma omp task #pragma omp parallel for for (int i = 0; i < 10; ++i) ; @@ -960,6 +1152,9 @@ void foo() { #pragma omp master bar(); #pragma omp parallel +#pragma omp critical + bar(); +#pragma omp parallel #pragma omp parallel for for (int i = 0; i < 10; ++i) ; @@ -1031,6 +1226,13 @@ void foo() { } #pragma omp simd 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 critical // 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) ; @@ -1104,6 +1306,8 @@ void foo() { bar(); #pragma omp master // expected-error {{region cannot be closely nested inside 'for' region}} bar(); +#pragma omp critical + bar(); } #pragma omp for for (int i = 0; i < 10; ++i) { @@ -1193,6 +1397,8 @@ void foo() { } #pragma omp sections { +#pragma omp critical + bar(); #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}} @@ -1309,6 +1515,8 @@ void foo() { bar(); #pragma omp master // expected-error {{region cannot be closely nested inside 'section' region}} bar(); +#pragma omp critical + bar(); } } #pragma omp sections @@ -1412,6 +1620,8 @@ void foo() { } #pragma omp master // expected-error {{region cannot be closely nested inside 'single' region}} bar(); +#pragma omp critical + bar(); } #pragma omp single { @@ -1508,6 +1718,13 @@ void foo() { } #pragma omp master { +#pragma omp critical + { + 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(); @@ -1566,6 +1783,125 @@ void foo() { bar(); } +// CRITICAL DIRECTIVE +#pragma omp critical + { +#pragma omp for // expected-error {{region cannot be closely nested inside 'critical' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}} + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp critical + { +#pragma omp simd + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp critical + { +#pragma omp parallel + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp critical + { +#pragma omp single // expected-error {{region cannot be closely nested inside 'critical' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}} + { + bar(); + } + } +#pragma omp critical + { +#pragma omp master // OK, though second 'master' is redundant + { + bar(); + } + } +#pragma omp critical + { +#pragma omp critical + { + bar(); + } + } +#pragma omp critical + { +#pragma omp sections // expected-error {{region cannot be closely nested inside 'critical' region; perhaps you forget to enclose 'omp sections' directive into a parallel region?}} + { + bar(); + } + } +#pragma omp critical + { +#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 critical + { +#pragma omp parallel for + for (int i = 0; i < 10; ++i) + ; + } +#pragma omp critical + { +#pragma omp parallel sections + { + bar(); + } + } +#pragma omp critical + { +#pragma omp task + { + bar(); + } + } +#pragma omp critical + { +#pragma omp taskyield + bar(); + } +#pragma omp critical + { +#pragma omp barrier // expected-error {{region cannot be closely nested inside 'critical' region}} + bar(); + } +#pragma omp critical + { +#pragma omp taskwait + bar(); + } +#pragma omp critical(Belka) + { +#pragma omp critical(Strelka) + bar(); + } +#pragma omp critical(Tuzik)// expected-note {{previous 'critical' region starts here}} + { +#pragma omp critical(grelka) // expected-note {{previous 'critical' region starts here}} + { +#pragma omp critical(Tuzik) // expected-error {{cannot nest 'critical' regions having the same name 'Tuzik'}} + { +#pragma omp parallel +#pragma omp critical(grelka) // expected-error {{cannot nest 'critical' regions having the same name 'grelka'}} + { + bar(); + } + } + } + } + // PARALLEL FOR DIRECTIVE #pragma omp parallel for for (int i = 0; i < 10; ++i) { @@ -1609,6 +1945,10 @@ void foo() { { bar(); } +#pragma omp critical + { + bar(); + } } #pragma omp parallel for for (int i = 0; i < 10; ++i) { @@ -1622,6 +1962,10 @@ void foo() { { bar(); } +#pragma omp critical // OK + { + bar(); + } #pragma omp for // OK for (int i = 0; i < 10; ++i) ; @@ -1708,6 +2052,8 @@ void foo() { bar(); #pragma omp master // expected-error {{region cannot be closely nested inside 'section' region}} bar(); +#pragma omp critical + bar(); } } #pragma omp parallel sections @@ -1722,6 +2068,10 @@ void foo() { { bar(); } +#pragma omp critical // OK + { + bar(); + } #pragma omp for // OK for (int i = 0; i < 10; ++i) ; @@ -1790,6 +2140,9 @@ void foo() { #pragma omp master // expected-error {{region cannot be closely nested inside 'task' region}} bar(); #pragma omp task +#pragma omp critical + 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 ce74f9f..eb1765e 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -1784,6 +1784,8 @@ public: return cast(S)->getMemberNameInfo(); case Stmt::DependentScopeDeclRefExprClass: return cast(S)->getNameInfo(); + case Stmt::OMPCriticalDirectiveClass: + return cast(S)->getDirectiveName(); } } }; @@ -1861,6 +1863,7 @@ public: void VisitOMPSectionDirective(const OMPSectionDirective *D); void VisitOMPSingleDirective(const OMPSingleDirective *D); void VisitOMPMasterDirective(const OMPMasterDirective *D); + void VisitOMPCriticalDirective(const OMPCriticalDirective *D); void VisitOMPParallelForDirective(const OMPParallelForDirective *D); void VisitOMPParallelSectionsDirective(const OMPParallelSectionsDirective *D); void VisitOMPTaskDirective(const OMPTaskDirective *D); @@ -2330,6 +2333,11 @@ void EnqueueVisitor::VisitOMPMasterDirective(const OMPMasterDirective *D) { VisitOMPExecutableDirective(D); } +void EnqueueVisitor::VisitOMPCriticalDirective(const OMPCriticalDirective *D) { + VisitOMPExecutableDirective(D); + AddDeclarationNameInfo(D); +} + void EnqueueVisitor::VisitOMPParallelForDirective(const OMPParallelForDirective *D) { VisitOMPExecutableDirective(D); @@ -4043,6 +4051,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return cxstring::createRef("OMPSingleDirective"); case CXCursor_OMPMasterDirective: return cxstring::createRef("OMPMasterDirective"); + case CXCursor_OMPCriticalDirective: + return cxstring::createRef("OMPCriticalDirective"); 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 b8b949a..94d209e 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -538,6 +538,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent, case Stmt::OMPMasterDirectiveClass: K = CXCursor_OMPMasterDirective; break; + case Stmt::OMPCriticalDirectiveClass: + K = CXCursor_OMPCriticalDirective; + break; case Stmt::OMPParallelForDirectiveClass: K = CXCursor_OMPParallelForDirective; break; -- 2.7.4