From 549210e783c7d4557c2f7ddce35f202e469b518d Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Tue, 24 Jun 2014 04:39:47 +0000 Subject: [PATCH] [OPENMP] Added initial checking of nesting of OpenMP regions. llvm-svn: 211566 --- .../clang/Basic/DiagnosticSemaKinds.td | 5 ++ clang/lib/Sema/SemaOpenMP.cpp | 52 +++++++++++- clang/test/OpenMP/nesting_of_regions.cpp | 82 +++++++++++++++++++ 3 files changed, 136 insertions(+), 3 deletions(-) create mode 100644 clang/test/OpenMP/nesting_of_regions.cpp diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 035a7377e18b..98745ca9b8be 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/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/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index de3f860bdce4..561251c25655 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/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/clang/test/OpenMP/nesting_of_regions.cpp b/clang/test/OpenMP/nesting_of_regions.cpp new file mode 100644 index 000000000000..a1f416f3781f --- /dev/null +++ b/clang/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(); +} +