From: Alexey Bataev Date: Tue, 24 Jun 2014 04:39:47 +0000 (+0000) Subject: [OPENMP] Added initial checking of nesting of OpenMP regions. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b5db1b77d8fa80c507665d4c5c3217b0e972d3ed;p=clang [OPENMP] Added initial checking of nesting of OpenMP regions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@211566 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 035a7377e1..98745ca9b8 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -7096,6 +7096,11 @@ def err_omp_reduction_in_task : Error< "reduction variables may not be accessed in an explicit task">; def err_omp_reduction_id_not_compatible : Error< "variable of type %0 is not valid for specified reduction operation">; +def err_omp_prohibited_region : Error< + "region cannot be%select{| closely}0 nested inside '%1' region" + "%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">; } // end of OpenMP category let CategoryName = "Related Result Type Issue" in { diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index de3f860bdc..561251c256 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -152,6 +152,12 @@ public: OpenMPDirectiveKind getCurrentDirective() const { return Stack.back().Directive; } + /// \brief Returns parent directive. + OpenMPDirectiveKind getParentDirective() const { + if (Stack.size() > 2) + return Stack[Stack.size() - 2].Directive; + return OMPD_unknown; + } /// \brief Set default data sharing attribute to none. void setDefaultDSANone() { Stack.back().DefaultAttr = DSA_none; } @@ -912,6 +918,41 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, SourceLocation Loc, } } +bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, + OpenMPDirectiveKind CurrentRegion, + SourceLocation StartLoc) { + if (Stack->getCurScope()) { + auto ParentRegion = Stack->getParentDirective(); + bool NestingProhibited = false; + bool CloseNesting = true; + bool ShouldBeInParallelRegion = false; + if (isOpenMPSimdDirective(ParentRegion)) { + // OpenMP [2.16, Nesting of Regions] + // OpenMP constructs may not be nested inside a simd region. + SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_simd); + return true; + } + 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); + ShouldBeInParallelRegion = true; + } + if (NestingProhibited) { + SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region) + << CloseNesting << getOpenMPDirectiveName(ParentRegion) << true + << getOpenMPDirectiveName(CurrentRegion) << ShouldBeInParallelRegion; + return true; + } + } + return false; +} + StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, ArrayRef Clauses, Stmt *AStmt, @@ -920,6 +961,8 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, assert(AStmt && isa(AStmt) && "Captured statement expected"); StmtResult Res = StmtError(); + if (CheckNestingOfRegions(*this, DSAStack, Kind, StartLoc)) + return StmtError(); // Check default data sharing attributes for referenced variables. DSAAttrChecker DSAChecker(DSAStack, *this, cast(AStmt)); @@ -2246,7 +2289,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef VarList, // in a firstprivate clause on a worksharing construct if any of the // worksharing regions arising from the worksharing construct ever bind // to any of the parallel regions arising from the parallel construct. - if (isOpenMPWorksharingDirective(CurrDir)) { + if (isOpenMPWorksharingDirective(CurrDir) && + !isOpenMPParallelDirective(CurrDir)) { DVar = DSAStack->getImplicitDSA(VD); if (DVar.CKind != OMPC_shared) { Diag(ELoc, diag::err_omp_required_access) @@ -2357,7 +2401,8 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef VarList, // lastprivate clause on a worksharing construct if any of the corresponding // worksharing regions ever binds to any of the corresponding parallel // regions. - if (isOpenMPWorksharingDirective(CurrDir)) { + if (isOpenMPWorksharingDirective(CurrDir) && + !isOpenMPParallelDirective(CurrDir)) { DVar = DSAStack->getImplicitDSA(VD); if (DVar.CKind != OMPC_shared) { Diag(ELoc, diag::err_omp_required_access) @@ -2748,7 +2793,8 @@ OMPClause *Sema::ActOnOpenMPReductionClause( // construct must be shared in the parallel regions to which any of the // worksharing regions arising from the worksharing construct bind. OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective(); - if (isOpenMPWorksharingDirective(CurrDir)) { + if (isOpenMPWorksharingDirective(CurrDir) && + !isOpenMPParallelDirective(CurrDir)) { DVar = DSAStack->getImplicitDSA(VD); if (DVar.CKind != OMPC_shared) { Diag(ELoc, diag::err_omp_required_access) diff --git a/test/OpenMP/nesting_of_regions.cpp b/test/OpenMP/nesting_of_regions.cpp new file mode 100644 index 0000000000..a1f416f378 --- /dev/null +++ b/test/OpenMP/nesting_of_regions.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -fsyntax-only -fopenmp=libiomp5 -verify %s + +template +void foo() { +#pragma omp parallel +#pragma omp for + for (int i = 0; i < 10; ++i); +#pragma omp parallel +#pragma omp simd + for (int i = 0; i < 10; ++i); +#pragma omp simd + for (int i = 0; i < 10; ++i) { +#pragma omp for // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i); + } +#pragma omp simd + for (int i = 0; i < 10; ++i) { +#pragma omp simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i); + } +#pragma omp simd + for (int i = 0; i < 10; ++i) { +#pragma omp parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i); + } +#pragma omp for + for (int i = 0; i < 10; ++i) { +#pragma omp for // expected-error {{region cannot be closely nested inside 'for' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}} + for (int i = 0; i < 10; ++i); + } +#pragma omp for + for (int i = 0; i < 10; ++i) { +#pragma omp simd + for (int i = 0; i < 10; ++i); + } +#pragma omp for + for (int i = 0; i < 10; ++i) { +#pragma omp parallel + for (int i = 0; i < 10; ++i); + } +} + +void foo() { +#pragma omp parallel +#pragma omp for + for (int i = 0; i < 10; ++i); +#pragma omp parallel +#pragma omp simd + for (int i = 0; i < 10; ++i); +#pragma omp simd + for (int i = 0; i < 10; ++i) { +#pragma omp for // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i); + } +#pragma omp simd + for (int i = 0; i < 10; ++i) { +#pragma omp simd // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i); + } +#pragma omp simd + for (int i = 0; i < 10; ++i) { +#pragma omp parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}} + for (int i = 0; i < 10; ++i); + } +#pragma omp for + for (int i = 0; i < 10; ++i) { +#pragma omp for // expected-error {{region cannot be closely nested inside 'for' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}} + for (int i = 0; i < 10; ++i); + } +#pragma omp for + for (int i = 0; i < 10; ++i) { +#pragma omp simd + for (int i = 0; i < 10; ++i); + } +#pragma omp for + for (int i = 0; i < 10; ++i) { +#pragma omp parallel + for (int i = 0; i < 10; ++i); + } + return foo(); +} +