*/
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,
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)); })
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)); })
}
};
+/// \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
"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<
"%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<
OPENMP_DIRECTIVE(section)
OPENMP_DIRECTIVE(single)
OPENMP_DIRECTIVE(master)
+OPENMP_DIRECTIVE(critical)
OPENMP_DIRECTIVE(taskyield)
OPENMP_DIRECTIVE(barrier)
OPENMP_DIRECTIVE(taskwait)
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>;
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,
/// 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(
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,
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,
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);
VisitOMPExecutableDirective(S);
}
+void StmtProfiler::VisitOMPCriticalDirective(const OMPCriticalDirective *S) {
+ VisitOMPExecutableDirective(S);
+ VisitName(S->getDirectiveName().getName());
+}
+
void
StmtProfiler::VisitOMPParallelForDirective(const OMPParallelForDirective *S) {
VisitOMPExecutableDirective(S);
case OMPD_threadprivate:
case OMPD_section:
case OMPD_master:
+ case OMPD_critical:
case OMPD_taskyield:
case OMPD_barrier:
case OMPD_taskwait:
case Stmt::OMPMasterDirectiveClass:
EmitOMPMasterDirective(cast<OMPMasterDirective>(*S));
break;
+ case Stmt::OMPCriticalDirectiveClass:
+ EmitOMPCriticalDirective(cast<OMPCriticalDirective>(*S));
+ break;
case Stmt::OMPParallelForDirectiveClass:
EmitOMPParallelForDirective(cast<OMPParallelForDirective>(*S));
break;
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.");
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);
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)
///
/// 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) {
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;
}
if (CreateDirective)
Directive = Actions.ActOnOpenMPExecutableDirective(
- DKind, Clauses, AssociatedStmt.get(), Loc, EndLoc);
+ DKind, DirName, Clauses, AssociatedStmt.get(), Loc, EndLoc);
// Exit scope.
Actions.EndOpenMPDSABlock(Directive.get());
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 {
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);
}
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);
}
}
-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(*)|
// | parallel | parallel | * |
// | parallel | for | * |
// | parallel | master | * |
+ // | parallel | critical | * |
// | parallel | simd | * |
// | parallel | sections | * |
// | parallel | section | + |
// | for | parallel | * |
// | for | for | + |
// | for | master | + |
+ // | for | critical | * |
// | for | simd | * |
// | for | sections | + |
// | for | section | + |
// | master | parallel | * |
// | master | for | + |
// | master | master | * |
+ // | master | critical | * |
// | master | simd | * |
// | master | sections | + |
// | master | section | + |
// | 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 | |
// | sections | parallel | * |
// | sections | for | + |
// | sections | master | + |
+ // | sections | critical | * |
// | sections | simd | * |
// | sections | sections | + |
// | sections | section | * |
// | section | parallel | * |
// | section | for | + |
// | section | master | + |
+ // | section | critical | * |
// | section | simd | * |
// | section | sections | + |
// | section | section | + |
// | single | parallel | * |
// | single | for | + |
// | single | master | + |
+ // | single | critical | * |
// | single | simd | * |
// | single | sections | + |
// | single | section | + |
// | parallel for | parallel | * |
// | parallel for | for | + |
// | parallel for | master | + |
+ // | parallel for | critical | * |
// | parallel for | simd | * |
// | parallel for | sections | + |
// | parallel for | section | + |
// | parallel sections| parallel | * |
// | parallel sections| for | + |
// | parallel sections| master | + |
+ // | parallel sections| critical | + |
// | parallel sections| simd | * |
// | parallel sections| sections | + |
// | parallel sections| section | * |
// | task | parallel | * |
// | task | for | + |
// | task | master | + |
+ // | task | critical | * |
// | task | simd | * |
// | task | sections | + |
// | task | section | + |
// 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)) {
NestingProhibited = (isOpenMPWorksharingDirective(ParentRegion) &&
!isOpenMPSimdDirective(ParentRegion)) ||
ParentRegion == OMPD_task ||
- ParentRegion == OMPD_master;
+ ParentRegion == OMPD_master ||
+ ParentRegion == OMPD_critical;
ShouldBeInParallelRegion = true;
}
if (NestingProhibited) {
}
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;
"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);
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,
/// 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.
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>
return Res;
}
+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) {
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.
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];
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());
case Stmt::OMPSectionDirectiveClass:
case Stmt::OMPSingleDirectiveClass:
case Stmt::OMPMasterDirectiveClass:
+ case Stmt::OMPCriticalDirectiveClass:
case Stmt::OMPParallelForDirectiveClass:
case Stmt::OMPParallelSectionsDirectiveClass:
case Stmt::OMPTaskDirectiveClass:
--- /dev/null
+// 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
--- /dev/null
+// 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;
+}
bar();
}
#pragma omp parallel
+#pragma omp critical
+ {
+ bar();
+ }
+#pragma omp parallel
#pragma omp parallel for
for (int i = 0; i < 10; ++i)
;
}
#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)
;
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
}
#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)
;
bar();
#pragma omp master // expected-error {{region cannot be closely nested inside 'section' region}}
bar();
+#pragma omp critical
+ bar();
}
}
#pragma omp sections
}
#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();
}
#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();
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) {
}
}
+#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 parallel sections
{
+#pragma omp section
+ {
+#pragma omp critical
+ bar();
+ }
+ }
+#pragma omp parallel sections
+ {
#pragma omp parallel
{
#pragma omp single // OK
#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)
;
#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)
;
}
#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)
;
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) {
}
#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}}
bar();
#pragma omp master // expected-error {{region cannot be closely nested inside 'section' region}}
bar();
+#pragma omp critical
+ bar();
}
}
#pragma omp sections
}
#pragma omp master // expected-error {{region cannot be closely nested inside 'single' region}}
bar();
+#pragma omp critical
+ bar();
}
#pragma omp single
{
}
#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();
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) {
{
bar();
}
+#pragma omp critical
+ {
+ bar();
+ }
}
#pragma omp parallel for
for (int i = 0; i < 10; ++i) {
{
bar();
}
+#pragma omp critical // OK
+ {
+ bar();
+ }
#pragma omp for // OK
for (int i = 0; i < 10; ++i)
;
bar();
#pragma omp master // expected-error {{region cannot be closely nested inside 'section' region}}
bar();
+#pragma omp critical
+ bar();
}
}
#pragma omp parallel sections
{
bar();
}
+#pragma omp critical // OK
+ {
+ bar();
+ }
#pragma omp for // OK
for (int i = 0; i < 10; ++i)
;
#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)
;
return cast<CXXDependentScopeMemberExpr>(S)->getMemberNameInfo();
case Stmt::DependentScopeDeclRefExprClass:
return cast<DependentScopeDeclRefExpr>(S)->getNameInfo();
+ case Stmt::OMPCriticalDirectiveClass:
+ return cast<OMPCriticalDirective>(S)->getDirectiveName();
}
}
};
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);
VisitOMPExecutableDirective(D);
}
+void EnqueueVisitor::VisitOMPCriticalDirective(const OMPCriticalDirective *D) {
+ VisitOMPExecutableDirective(D);
+ AddDeclarationNameInfo(D);
+}
+
void
EnqueueVisitor::VisitOMPParallelForDirective(const OMPParallelForDirective *D) {
VisitOMPExecutableDirective(D);
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:
case Stmt::OMPMasterDirectiveClass:
K = CXCursor_OMPMasterDirective;
break;
+ case Stmt::OMPCriticalDirectiveClass:
+ K = CXCursor_OMPCriticalDirective;
+ break;
case Stmt::OMPParallelForDirectiveClass:
K = CXCursor_OMPParallelForDirective;
break;