[OPENMP] Parsing/Sema of the OpenMP directive 'critical'.

llvm-svn: 213510
This commit is contained in:
Alexander Musman 2014-07-21 09:42:05 +00:00
parent ddf36dea13
commit d9ed09f7a5
28 changed files with 779 additions and 24 deletions

View File

@ -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,

View File

@ -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)); })

View File

@ -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)); })

View File

@ -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

View File

@ -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<

View File

@ -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<

View File

@ -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)

View File

@ -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>;

View File

@ -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(

View File

@ -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,

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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:

View File

@ -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;

View File

@ -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.");

View File

@ -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);

View File

@ -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());

View File

@ -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,

View File

@ -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>
@ -6527,6 +6534,16 @@ TreeTransform<Derived>::TransformOMPMasterDirective(OMPMasterDirective *D) {
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) {

View File

@ -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];

View File

@ -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());

View File

@ -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:

View File

@ -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

View File

@ -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;
}

View File

@ -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) {
@ -720,6 +892,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
@ -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)
;

View File

@ -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:

View File

@ -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;