summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Musman <alexander.musman@gmail.com>2014-07-21 09:42:05 +0000
committerAlexander Musman <alexander.musman@gmail.com>2014-07-21 09:42:05 +0000
commit76fc5c55ecf19799784bf1f798293da347a7e56f (patch)
tree311f55cc3ed96eb5a5343d925be0cabe14fb4e4a
parent88b9e43471b45aaa91b6904865374a35db7c1c0b (diff)
[OPENMP] Parsing/Sema of the OpenMP directive 'critical'.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@213510 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang-c/Index.h12
-rw-r--r--include/clang/AST/DataRecursiveASTVisitor.h5
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h5
-rw-r--r--include/clang/AST/StmtOpenMP.h63
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td2
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td4
-rw-r--r--include/clang/Basic/OpenMPKinds.def1
-rw-r--r--include/clang/Basic/StmtNodes.td1
-rw-r--r--include/clang/Sema/Sema.h10
-rw-r--r--include/clang/Serialization/ASTBitCodes.h1
-rw-r--r--lib/AST/Stmt.cpp20
-rw-r--r--lib/AST/StmtPrinter.cpp10
-rw-r--r--lib/AST/StmtProfile.cpp5
-rw-r--r--lib/Basic/OpenMPKinds.cpp1
-rw-r--r--lib/CodeGen/CGStmt.cpp3
-rw-r--r--lib/CodeGen/CGStmtOpenMP.cpp4
-rw-r--r--lib/CodeGen/CodeGenFunction.h1
-rw-r--r--lib/Parse/ParseOpenMP.cpp25
-rw-r--r--lib/Sema/SemaOpenMP.cpp114
-rw-r--r--lib/Sema/TreeTransform.h29
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp10
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp7
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp1
-rw-r--r--test/OpenMP/critical_ast_print.cpp29
-rw-r--r--test/OpenMP/critical_messages.cpp72
-rw-r--r--test/OpenMP/nesting_of_regions.cpp355
-rw-r--r--tools/libclang/CIndex.cpp10
-rw-r--r--tools/libclang/CXCursor.cpp3
28 files changed, 779 insertions, 24 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index 7b808419a6..e4d3ebd533 100644
--- a/include/clang-c/Index.h
+++ b/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/include/clang/AST/DataRecursiveASTVisitor.h b/include/clang/AST/DataRecursiveASTVisitor.h
index ea3bb17114..072bd7b0d9 100644
--- a/include/clang/AST/DataRecursiveASTVisitor.h
+++ b/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/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index e176a5fe0a..2953e7ad76 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/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/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h
index 62af6a2444..2c38c167f6 100644
--- a/include/clang/AST/StmtOpenMP.h
+++ b/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/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 1956afc858..34ac6a4525 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/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/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 98f08b246a..885cf36163 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/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/include/clang/Basic/OpenMPKinds.def b/include/clang/Basic/OpenMPKinds.def
index f43a8b5cf7..a871ff24a1 100644
--- a/include/clang/Basic/OpenMPKinds.def
+++ b/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/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td
index fd4546ac9e..28e0f4cf7b 100644
--- a/include/clang/Basic/StmtNodes.td
+++ b/include/clang/Basic/StmtNodes.td
@@ -185,6 +185,7 @@ def OMPSectionsDirective : DStmt<OMPExecutableDirective>;
def OMPSectionDirective : DStmt<OMPExecutableDirective>;
def OMPSingleDirective : DStmt<OMPExecutableDirective>;
def OMPMasterDirective : DStmt<OMPExecutableDirective>;
+def OMPCriticalDirective : DStmt<OMPExecutableDirective>;
def OMPParallelForDirective : DStmt<OMPExecutableDirective>;
def OMPParallelSectionsDirective : DStmt<OMPExecutableDirective>;
def OMPTaskDirective : DStmt<OMPExecutableDirective>;
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index bd4493bca6..6d8b62dbf0 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -7303,14 +7303,15 @@ public:
DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(
SourceLocation Loc,
ArrayRef<Expr *> VarList);
- // \brief Builds a new OpenMPThreadPrivateDecl and checks its correctness.
+ /// \brief Builds a new OpenMPThreadPrivateDecl and checks its correctness.
OMPThreadPrivateDecl *CheckOMPThreadPrivateDecl(
SourceLocation Loc,
ArrayRef<Expr *> 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<OMPClause *> 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/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index ae7f44b7a7..8c1b91af16 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/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/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index a5ca49df20..b011f9f24c 100644
--- a/lib/AST/Stmt.cpp
+++ b/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<Stmt *>());
+ 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<Stmt *>());
+ 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/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 0267bcca2a..9c00eeaa0f 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/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/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index 0cd0f62dc5..56827ed383 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/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/lib/Basic/OpenMPKinds.cpp b/lib/Basic/OpenMPKinds.cpp
index f304513fcc..869b00c02a 100644
--- a/lib/Basic/OpenMPKinds.cpp
+++ b/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/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index cd970c747c..82566382db 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -197,6 +197,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
case Stmt::OMPMasterDirectiveClass:
EmitOMPMasterDirective(cast<OMPMasterDirective>(*S));
break;
+ case Stmt::OMPCriticalDirectiveClass:
+ EmitOMPCriticalDirective(cast<OMPCriticalDirective>(*S));
+ break;
case Stmt::OMPParallelForDirectiveClass:
EmitOMPParallelForDirective(cast<OMPParallelForDirective>(*S));
break;
diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp
index 7731c76f51..e4ef5a6911 100644
--- a/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/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/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 3692b0203f..66bf78f002 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/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/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp
index cf99178430..79cf6af6fd 100644
--- a/lib/Parse/ParseOpenMP.cpp
+++ b/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' [ '(' <name> ')' ] |
+/// '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/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp
index f2421da582..c0a6d60a16 100644
--- a/lib/Sema/SemaOpenMP.cpp
+++ b/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 <class NamedDirectivesPredicate>
+ 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 <class NamedDirectivesPredicate>
+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<OMPClause *> 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<OMPClause *, 8> 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<CapturedStmt>(AStmt) && "Captured statement expected");
+
+ getCurFunction()->setHasBranchProtectedScope();
+
+ return OMPCriticalDirective::Create(Context, DirName, StartLoc, EndLoc,
+ AStmt);
+}
+
StmtResult Sema::ActOnOpenMPParallelForDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc,
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 1f648d4aca..ba67df7417 100644
--- a/lib/Sema/TreeTransform.h
+++ b/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<OMPClause *> 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<Derived>::TransformOMPExecutableDirective(
return StmtError();
}
+ // Transform directive name for 'omp critical' directive.
+ DeclarationNameInfo DirName;
+ if (D->getDirectiveKind() == OMPD_critical) {
+ DirName = cast<OMPCriticalDirective>(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 <typename Derived>
@@ -6528,6 +6535,16 @@ TreeTransform<Derived>::TransformOMPMasterDirective(OMPMasterDirective *D) {
}
template <typename Derived>
+StmtResult
+TreeTransform<Derived>::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 <typename Derived>
StmtResult TreeTransform<Derived>::TransformOMPParallelForDirective(
OMPParallelForDirective *D) {
DeclarationNameInfo DirName;
diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp
index 99c9827ae2..e8a84282e7 100644
--- a/lib/Serialization/ASTReaderStmt.cpp
+++ b/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/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp
index db6adbcbaa..dd78c2446b 100644
--- a/lib/Serialization/ASTWriterStmt.cpp
+++ b/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/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 8da1d8e942..af2ef5e07a 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/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/test/OpenMP/critical_ast_print.cpp b/test/OpenMP/critical_ast_print.cpp
new file mode 100644
index 0000000000..98ece88e0f
--- /dev/null
+++ b/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/test/OpenMP/critical_messages.cpp b/test/OpenMP/critical_messages.cpp
new file mode 100644
index 0000000000..08df9e0666
--- /dev/null
+++ b/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/test/OpenMP/nesting_of_regions.cpp b/test/OpenMP/nesting_of_regions.cpp
index 534c8a502c..7224ceb00c 100644
--- a/test/OpenMP/nesting_of_regions.cpp
+++ b/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/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index ce74f9f9c4..eb1765efbc 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -1784,6 +1784,8 @@ public:
return cast<CXXDependentScopeMemberExpr>(S)->getMemberNameInfo();
case Stmt::DependentScopeDeclRefExprClass:
return cast<DependentScopeDeclRefExpr>(S)->getNameInfo();
+ case Stmt::OMPCriticalDirectiveClass:
+ return cast<OMPCriticalDirective>(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/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp
index b8b949a16c..94d209e7a7 100644
--- a/tools/libclang/CXCursor.cpp
+++ b/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;