64 changes: 57 additions & 7 deletions clang/lib/Sema/SemaOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1000,6 +1000,14 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
Params);
break;
}
case OMPD_master: {
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);
Expand Down Expand Up @@ -1044,16 +1052,18 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// +------------------+-----------------+------------------------------------+
// | parallel | parallel | * |
// | parallel | for | * |
// | parallel | master | * |
// | parallel | simd | * |
// | parallel | sections | * |
// | parallel | section | + |
// | parallel | section | + |
// | parallel | single | * |
// | parallel | parallel for | * |
// | parallel |parallel sections| * |
// | parallel | task | * |
// +------------------+-----------------+------------------------------------+
// | for | parallel | * |
// | for | for | + |
// | for | master | + |
// | for | simd | * |
// | for | sections | + |
// | for | section | + |
Expand All @@ -1062,8 +1072,20 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | for |parallel sections| * |
// | for | task | * |
// +------------------+-----------------+------------------------------------+
// | master | parallel | * |
// | master | for | + |
// | master | master | * |
// | master | simd | * |
// | master | sections | + |
// | master | section | + |
// | master | single | + |
// | master | parallel for | * |
// | master |parallel sections| * |
// | master | task | * |
// +------------------+-----------------+------------------------------------+
// | simd | parallel | |
// | simd | for | |
// | simd | master | |
// | simd | simd | |
// | simd | sections | |
// | simd | section | |
Expand All @@ -1074,6 +1096,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// +------------------+-----------------+------------------------------------+
// | sections | parallel | * |
// | sections | for | + |
// | sections | master | + |
// | sections | simd | * |
// | sections | sections | + |
// | sections | section | * |
Expand All @@ -1084,6 +1107,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// +------------------+-----------------+------------------------------------+
// | section | parallel | * |
// | section | for | + |
// | section | master | + |
// | section | simd | * |
// | section | sections | + |
// | section | section | + |
Expand All @@ -1094,6 +1118,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// +------------------+-----------------+------------------------------------+
// | single | parallel | * |
// | single | for | + |
// | single | master | + |
// | single | simd | * |
// | single | sections | + |
// | single | section | + |
Expand All @@ -1104,6 +1129,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// +------------------+-----------------+------------------------------------+
// | parallel for | parallel | * |
// | parallel for | for | + |
// | parallel for | master | + |
// | parallel for | simd | * |
// | parallel for | sections | + |
// | parallel for | section | + |
Expand All @@ -1114,6 +1140,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// +------------------+-----------------+------------------------------------+
// | parallel sections| parallel | * |
// | parallel sections| for | + |
// | parallel sections| master | + |
// | parallel sections| simd | * |
// | parallel sections| sections | + |
// | parallel sections| section | * |
Expand All @@ -1124,9 +1151,10 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// +------------------+-----------------+------------------------------------+
// | task | parallel | * |
// | task | for | + |
// | task | master | + |
// | task | simd | * |
// | task | sections | + |
// | task | section | + |
// | task | section | + |
// | task | single | + |
// | task | parallel for | * |
// | task |parallel sections| * |
Expand Down Expand Up @@ -1157,16 +1185,23 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
}
return false;
}
if (isOpenMPWorksharingDirective(CurrentRegion) &&
!isOpenMPParallelDirective(CurrentRegion) &&
!isOpenMPSimdDirective(CurrentRegion)) {
if (CurrentRegion == OMPD_master) {
// OpenMP [2.16, Nesting of Regions]
// A master region may not be closely nested inside a worksharing,
// atomic (TODO), or explicit task region.
NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
ParentRegion == OMPD_task;
} else if (isOpenMPWorksharingDirective(CurrentRegion) &&
!isOpenMPParallelDirective(CurrentRegion) &&
!isOpenMPSimdDirective(CurrentRegion)) {
// OpenMP [2.16, Nesting of Regions]
// A worksharing region may not be closely nested inside a worksharing,
// explicit task, critical, ordered, atomic, or master region.
// TODO
NestingProhibited = (isOpenMPWorksharingDirective(ParentRegion) &&
!isOpenMPSimdDirective(ParentRegion)) ||
ParentRegion == OMPD_task;
ParentRegion == OMPD_task ||
ParentRegion == OMPD_master;
ShouldBeInParallelRegion = true;
}
if (NestingProhibited) {
Expand Down Expand Up @@ -1231,13 +1266,18 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
break;
case OMPD_section:
assert(ClausesWithImplicit.empty() &&
"No clauses is allowed for 'omp section' directive");
"No clauses are allowed for 'omp section' directive");
Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
break;
case OMPD_single:
Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc,
EndLoc);
break;
case OMPD_master:
assert(ClausesWithImplicit.empty() &&
"No clauses are allowed for 'omp master' directive");
Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
break;
case OMPD_parallel_for:
Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
EndLoc, VarsWithInheritedDSA);
Expand Down Expand Up @@ -1906,6 +1946,16 @@ StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
return OMPSingleDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
}

StmtResult Sema::ActOnOpenMPMasterDirective(Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");

getCurFunction()->setHasBranchProtectedScope();

return OMPMasterDirective::Create(Context, StartLoc, EndLoc, AStmt);
}

StmtResult Sema::ActOnOpenMPParallelForDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc,
Expand Down
11 changes: 11 additions & 0 deletions clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -6508,6 +6508,17 @@ TreeTransform<Derived>::TransformOMPSingleDirective(OMPSingleDirective *D) {
return Res;
}

template <typename Derived>
StmtResult
TreeTransform<Derived>::TransformOMPMasterDirective(OMPMasterDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_master, DirName, nullptr,
D->getLocStart());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
}

template <typename Derived>
StmtResult TreeTransform<Derived>::TransformOMPParallelForDirective(
OMPParallelForDirective *D) {
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/Serialization/ASTReaderStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1952,6 +1952,11 @@ void ASTStmtReader::VisitOMPSingleDirective(OMPSingleDirective *D) {
VisitOMPExecutableDirective(D);
}

void ASTStmtReader::VisitOMPMasterDirective(OMPMasterDirective *D) {
VisitStmt(D);
VisitOMPExecutableDirective(D);
}

void ASTStmtReader::VisitOMPParallelForDirective(OMPParallelForDirective *D) {
VisitStmt(D);
// Two fields (NumClauses and CollapsedNum) were read in ReadStmtFromStream.
Expand Down Expand Up @@ -2486,6 +2491,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
Context, Record[ASTStmtReader::NumStmtFields], Empty);
break;

case STMT_OMP_MASTER_DIRECTIVE:
S = OMPMasterDirective::CreateEmpty(Context, Empty);
break;

case STMT_OMP_PARALLEL_FOR_DIRECTIVE: {
unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Serialization/ASTWriterStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1857,6 +1857,12 @@ void ASTStmtWriter::VisitOMPSingleDirective(OMPSingleDirective *D) {
Code = serialization::STMT_OMP_SINGLE_DIRECTIVE;
}

void ASTStmtWriter::VisitOMPMasterDirective(OMPMasterDirective *D) {
VisitStmt(D);
VisitOMPExecutableDirective(D);
Code = serialization::STMT_OMP_MASTER_DIRECTIVE;
}

void ASTStmtWriter::VisitOMPParallelForDirective(OMPParallelForDirective *D) {
VisitStmt(D);
Record.push_back(D->getNumClauses());
Expand Down
1 change: 1 addition & 0 deletions clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::OMPSectionsDirectiveClass:
case Stmt::OMPSectionDirectiveClass:
case Stmt::OMPSingleDirectiveClass:
case Stmt::OMPMasterDirectiveClass:
case Stmt::OMPParallelForDirectiveClass:
case Stmt::OMPParallelSectionsDirectiveClass:
case Stmt::OMPTaskDirectiveClass:
Expand Down
32 changes: 32 additions & 0 deletions clang/test/OpenMP/master_ast_print.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp=libiomp5 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics

#ifndef HEADER
#define HEADER

void foo() {}

int main (int argc, char **argv) {
int b = argc, c, d, e, f, g;
static int a;
// CHECK: static int a;
#pragma omp parallel
{
#pragma omp master
{
a=2;
}
}
// CHECK-NEXT: #pragma omp parallel
// CHECK-NEXT: {
// CHECK-NEXT: #pragma omp master
// CHECK-NEXT: {
// CHECK-NEXT: a = 2;
// CHECK-NEXT: }
// CHECK-NEXT: }
return (0);
}

#endif
64 changes: 64 additions & 0 deletions clang/test/OpenMP/master_messages.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// RUN: %clang_cc1 -verify -fopenmp=libiomp5 %s

int foo();

int main() {
#pragma omp master
;
#pragma omp master nowait // expected-error {{unexpected OpenMP clause 'nowait' in directive '#pragma omp master'}}
#pragma omp master unknown // expected-warning {{extra tokens at the end of '#pragma omp master' are ignored}}
foo();
{
#pragma omp master
} // expected-error {{expected statement}}
#pragma omp for
for (int i = 0; i < 10; ++i) {
foo();
#pragma omp master // expected-error {{region cannot be closely nested inside 'for' region}}
foo();
}
#pragma omp sections
{
foo();
#pragma omp master // expected-error {{region cannot be closely nested inside 'sections' region}}
foo();
}
#pragma omp single
for (int i = 0; i < 10; ++i) {
foo();
#pragma omp master // expected-error {{region cannot be closely nested inside 'single' region}}
foo();
}
#pragma omp master
for (int i = 0; i < 10; ++i) {
foo();
#pragma omp master
foo();
}
#pragma omp for ordered
for (int i = 0; i < 10; ++i)
#pragma omp master // expected-error {{region cannot be closely nested inside 'for' region}}
{
foo();
}

return 0;
}

int foo() {
L1:
foo();
#pragma omp master
{
foo();
goto L1; // expected-error {{use of undeclared label 'L1'}}
}
goto L2; // expected-error {{use of undeclared label 'L2'}}
#pragma omp master
{
L2:
foo();
}

return 0;
}
257 changes: 257 additions & 0 deletions clang/test/OpenMP/nesting_of_regions.cpp

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions clang/tools/libclang/CIndex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1860,6 +1860,7 @@ class EnqueueVisitor : public ConstStmtVisitor<EnqueueVisitor, void> {
void VisitOMPSectionsDirective(const OMPSectionsDirective *D);
void VisitOMPSectionDirective(const OMPSectionDirective *D);
void VisitOMPSingleDirective(const OMPSingleDirective *D);
void VisitOMPMasterDirective(const OMPMasterDirective *D);
void VisitOMPParallelForDirective(const OMPParallelForDirective *D);
void VisitOMPParallelSectionsDirective(const OMPParallelSectionsDirective *D);
void VisitOMPTaskDirective(const OMPTaskDirective *D);
Expand Down Expand Up @@ -2318,6 +2319,10 @@ void EnqueueVisitor::VisitOMPSingleDirective(const OMPSingleDirective *D) {
VisitOMPExecutableDirective(D);
}

void EnqueueVisitor::VisitOMPMasterDirective(const OMPMasterDirective *D) {
VisitOMPExecutableDirective(D);
}

void
EnqueueVisitor::VisitOMPParallelForDirective(const OMPParallelForDirective *D) {
VisitOMPExecutableDirective(D);
Expand Down Expand Up @@ -4016,6 +4021,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return cxstring::createRef("OMPSectionDirective");
case CXCursor_OMPSingleDirective:
return cxstring::createRef("OMPSingleDirective");
case CXCursor_OMPMasterDirective:
return cxstring::createRef("OMPMasterDirective");
case CXCursor_OMPParallelForDirective:
return cxstring::createRef("OMPParallelForDirective");
case CXCursor_OMPParallelSectionsDirective:
Expand Down
3 changes: 3 additions & 0 deletions clang/tools/libclang/CXCursor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
case Stmt::OMPSingleDirectiveClass:
K = CXCursor_OMPSingleDirective;
break;
case Stmt::OMPMasterDirectiveClass:
K = CXCursor_OMPMasterDirective;
break;
case Stmt::OMPParallelForDirectiveClass:
K = CXCursor_OMPParallelForDirective;
break;
Expand Down