diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:02:28 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:02:28 +0000 |
commit | 7442d6faa2719e4e7d33a7021c406c5a4facd74d (patch) | |
tree | c72b9241553fc9966179aba84f90f17bfa9235c3 /lib/Sema/SemaOpenMP.cpp | |
parent | b52119637f743680a99710ce5fdb6646da2772af (diff) | |
download | src-7442d6faa2719e4e7d33a7021c406c5a4facd74d.tar.gz src-7442d6faa2719e4e7d33a7021c406c5a4facd74d.zip |
Vendor import of clang trunk r300422:vendor/clang/clang-trunk-r300422
Notes
Notes:
svn path=/vendor/clang/dist/; revision=317019
svn path=/vendor/clang/clang-trunk-r300422/; revision=317020; tag=vendor/clang/clang-trunk-r300422
Diffstat (limited to 'lib/Sema/SemaOpenMP.cpp')
-rw-r--r-- | lib/Sema/SemaOpenMP.cpp | 562 |
1 files changed, 521 insertions, 41 deletions
diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index dcd19c8d817d..616ab05eaec8 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -1050,7 +1050,8 @@ void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName, Scope *CurScope, SourceLocation Loc) { DSAStack->push(DKind, DirName, CurScope, Loc); - PushExpressionEvaluationContext(PotentiallyEvaluated); + PushExpressionEvaluationContext( + ExpressionEvaluationContext::PotentiallyEvaluated); } void Sema::StartOpenMPClause(OpenMPClauseKind K) { @@ -1594,8 +1595,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { case OMPD_parallel_for: case OMPD_parallel_for_simd: case OMPD_parallel_sections: - case OMPD_teams: - case OMPD_target_teams: { + case OMPD_teams: { QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1); QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty).withConst().withRestrict(); @@ -1608,6 +1608,28 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { Params); break; } + case OMPD_target_teams: + case OMPD_target_parallel: { + Sema::CapturedParamNameType ParamsTarget[] = { + std::make_pair(StringRef(), QualType()) // __context with shared vars + }; + // Start a captured region for 'target' with no implicit parameters. + ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, + ParamsTarget); + QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1); + QualType KmpInt32PtrTy = + Context.getPointerType(KmpInt32Ty).withConst().withRestrict(); + Sema::CapturedParamNameType ParamsTeamsOrParallel[] = { + std::make_pair(".global_tid.", KmpInt32PtrTy), + std::make_pair(".bound_tid.", KmpInt32PtrTy), + std::make_pair(StringRef(), QualType()) // __context with shared vars + }; + // Start a captured region for 'teams' or 'parallel'. Both regions have + // the same implicit parameters. + ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, + ParamsTeamsOrParallel); + break; + } case OMPD_simd: case OMPD_for: case OMPD_for_simd: @@ -1622,7 +1644,6 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { case OMPD_atomic: case OMPD_target_data: case OMPD_target: - case OMPD_target_parallel: case OMPD_target_parallel_for: case OMPD_target_parallel_for_simd: case OMPD_target_simd: { @@ -1737,6 +1758,12 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { } } +int Sema::getOpenMPCaptureLevels(OpenMPDirectiveKind DKind) { + SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; + getOpenMPCaptureRegions(CaptureRegions, DKind); + return CaptureRegions.size(); +} + static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id, Expr *CaptureExpr, bool WithInit, bool AsExpression) { @@ -1796,16 +1823,49 @@ static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref) { return CaptureExpr->isGLValue() ? Res : S.DefaultLvalueConversion(Res.get()); } +namespace { +// OpenMP directives parsed in this section are represented as a +// CapturedStatement with an associated statement. If a syntax error +// is detected during the parsing of the associated statement, the +// compiler must abort processing and close the CapturedStatement. +// +// Combined directives such as 'target parallel' have more than one +// nested CapturedStatements. This RAII ensures that we unwind out +// of all the nested CapturedStatements when an error is found. +class CaptureRegionUnwinderRAII { +private: + Sema &S; + bool &ErrorFound; + OpenMPDirectiveKind DKind; + +public: + CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound, + OpenMPDirectiveKind DKind) + : S(S), ErrorFound(ErrorFound), DKind(DKind) {} + ~CaptureRegionUnwinderRAII() { + if (ErrorFound) { + int ThisCaptureLevel = S.getOpenMPCaptureLevels(DKind); + while (--ThisCaptureLevel >= 0) + S.ActOnCapturedRegionError(); + } + } +}; +} // namespace + StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S, ArrayRef<OMPClause *> Clauses) { + bool ErrorFound = false; + CaptureRegionUnwinderRAII CaptureRegionUnwinder( + *this, ErrorFound, DSAStack->getCurrentDirective()); if (!S.isUsable()) { - ActOnCapturedRegionError(); + ErrorFound = true; return StmtError(); } OMPOrderedClause *OC = nullptr; OMPScheduleClause *SC = nullptr; SmallVector<OMPLinearClause *, 4> LCs; + SmallVector<OMPClauseWithPreInit *, 8> PICs; // This is required for proper codegen. for (auto *Clause : Clauses) { if (isOpenMPPrivate(Clause->getClauseKind()) || @@ -1822,15 +1882,8 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S, } DSAStack->setForceVarCapturing(/*V=*/false); } else if (isParallelOrTaskRegion(DSAStack->getCurrentDirective())) { - // Mark all variables in private list clauses as used in inner region. - // Required for proper codegen of combined directives. - // TODO: add processing for other clauses. - if (auto *C = OMPClauseWithPreInit::get(Clause)) { - if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) { - for (auto *D : DS->decls()) - MarkVariableReferenced(D->getLocation(), cast<VarDecl>(D)); - } - } + if (auto *C = OMPClauseWithPreInit::get(Clause)) + PICs.push_back(C); if (auto *C = OMPClauseWithPostUpdate::get(Clause)) { if (auto *E = C->getPostUpdateExpr()) MarkDeclarationsReferencedInExpr(E); @@ -1843,7 +1896,6 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S, else if (Clause->getClauseKind() == OMPC_linear) LCs.push_back(cast<OMPLinearClause>(Clause)); } - bool ErrorFound = false; // OpenMP, 2.7.1 Loop Construct, Restrictions // The nonmonotonic modifier cannot be specified if an ordered clause is // specified. @@ -1874,13 +1926,54 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S, ErrorFound = true; } if (ErrorFound) { - ActOnCapturedRegionError(); return StmtError(); } - return ActOnCapturedRegionEnd(S.get()); + StmtResult SR = S; + SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; + getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective()); + for (auto ThisCaptureRegion : llvm::reverse(CaptureRegions)) { + // Mark all variables in private list clauses as used in inner region. + // Required for proper codegen of combined directives. + // TODO: add processing for other clauses. + if (isParallelOrTaskRegion(DSAStack->getCurrentDirective())) { + for (auto *C : PICs) { + OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion(); + // Find the particular capture region for the clause if the + // directive is a combined one with multiple capture regions. + // If the directive is not a combined one, the capture region + // associated with the clause is OMPD_unknown and is generated + // only once. + if (CaptureRegion == ThisCaptureRegion || + CaptureRegion == OMPD_unknown) { + if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) { + for (auto *D : DS->decls()) + MarkVariableReferenced(D->getLocation(), cast<VarDecl>(D)); + } + } + } + } + SR = ActOnCapturedRegionEnd(SR.get()); + } + return SR; } -static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, +static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion, + OpenMPDirectiveKind CancelRegion, + SourceLocation StartLoc) { + // CancelRegion is only needed for cancel and cancellation_point. + if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point) + return false; + + if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for || + CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup) + return false; + + SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region) + << getOpenMPDirectiveName(CancelRegion); + return true; +} + +static bool checkNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, OpenMPDirectiveKind CurrentRegion, const DeclarationNameInfo &CurrentName, OpenMPDirectiveKind CancelRegion, @@ -2180,7 +2273,9 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { StmtResult Res = StmtError(); - if (CheckNestingOfRegions(*this, DSAStack, Kind, DirName, CancelRegion, + // First check CancelRegion which is then used in checkNestingOfRegions. + if (checkCancelRegion(*this, Kind, CancelRegion, StartLoc) || + checkNestingOfRegions(*this, DSAStack, Kind, DirName, CancelRegion, StartLoc)) return StmtError(); @@ -2193,7 +2288,11 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( // Check default data sharing attributes for referenced variables. DSAAttrChecker DSAChecker(DSAStack, *this, cast<CapturedStmt>(AStmt)); - DSAChecker.Visit(cast<CapturedStmt>(AStmt)->getCapturedStmt()); + int ThisCaptureLevel = getOpenMPCaptureLevels(Kind); + Stmt *S = AStmt; + while (--ThisCaptureLevel >= 0) + S = cast<CapturedStmt>(S)->getCapturedStmt(); + DSAChecker.Visit(S); if (DSAChecker.isErrorFound()) return StmtError(); // Generate list of implicitly defined firstprivate variables. @@ -4101,6 +4200,36 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, return 0; } + // Create: increment expression for distribute loop when combined in a same + // directive with for as IV = IV + ST; ensure upper bound expression based + // on PrevUB instead of NumIterations - used to implement 'for' when found + // in combination with 'distribute', like in 'distribute parallel for' + SourceLocation DistIncLoc; + ExprResult DistCond, DistInc, PrevEUB; + if (isOpenMPLoopBoundSharingDirective(DKind)) { + DistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), UB.get()); + assert(DistCond.isUsable() && "distribute cond expr was not built"); + + DistInc = + SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get()); + assert(DistInc.isUsable() && "distribute inc expr was not built"); + DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(), + DistInc.get()); + DistInc = SemaRef.ActOnFinishFullExpr(DistInc.get()); + assert(DistInc.isUsable() && "distribute inc expr was not built"); + + // Build expression: UB = min(UB, prevUB) for #for in composite or combined + // construct + SourceLocation DistEUBLoc; + ExprResult IsUBGreater = + SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT, UB.get(), PrevUB.get()); + ExprResult CondOp = SemaRef.ActOnConditionalOp( + DistEUBLoc, DistEUBLoc, IsUBGreater.get(), PrevUB.get(), UB.get()); + PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(), + CondOp.get()); + PrevEUB = SemaRef.ActOnFinishFullExpr(PrevEUB.get()); + } + // Build updates and final values of the loop counters. bool HasErrors = false; Built.Counters.resize(NestedLoopCount); @@ -4215,6 +4344,8 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Built.NUB = NextUB.get(); Built.PrevLB = PrevLB.get(); Built.PrevUB = PrevUB.get(); + Built.DistInc = DistInc.get(); + Built.PrevEUB = PrevEUB.get(); Expr *CounterVal = SemaRef.DefaultLvalueConversion(IV.get()).get(); // Fill data for doacross depend clauses. @@ -5748,12 +5879,6 @@ StmtResult Sema::ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) { - if (CancelRegion != OMPD_parallel && CancelRegion != OMPD_for && - CancelRegion != OMPD_sections && CancelRegion != OMPD_taskgroup) { - Diag(StartLoc, diag::err_omp_wrong_cancel_region) - << getOpenMPDirectiveName(CancelRegion); - return StmtError(); - } if (DSAStack->isParentNowaitRegion()) { Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0; return StmtError(); @@ -5770,12 +5895,6 @@ StmtResult Sema::ActOnOpenMPCancelDirective(ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) { - if (CancelRegion != OMPD_parallel && CancelRegion != OMPD_for && - CancelRegion != OMPD_sections && CancelRegion != OMPD_taskgroup) { - Diag(StartLoc, diag::err_omp_wrong_cancel_region) - << getOpenMPDirectiveName(CancelRegion); - return StmtError(); - } if (DSAStack->isParentNowaitRegion()) { Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1; return StmtError(); @@ -6551,6 +6670,322 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, return Res; } +// An OpenMP directive such as 'target parallel' has two captured regions: +// for the 'target' and 'parallel' respectively. This function returns +// the region in which to capture expressions associated with a clause. +// A return value of OMPD_unknown signifies that the expression should not +// be captured. +static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( + OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, + OpenMPDirectiveKind NameModifier = OMPD_unknown) { + OpenMPDirectiveKind CaptureRegion = OMPD_unknown; + + switch (CKind) { + case OMPC_if: + switch (DKind) { + case OMPD_target_parallel: + // If this clause applies to the nested 'parallel' region, capture within + // the 'target' region, otherwise do not capture. + if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel) + CaptureRegion = OMPD_target; + break; + case OMPD_cancel: + case OMPD_parallel: + case OMPD_parallel_sections: + case OMPD_parallel_for: + case OMPD_parallel_for_simd: + case OMPD_target: + case OMPD_target_simd: + case OMPD_target_parallel_for: + case OMPD_target_parallel_for_simd: + case OMPD_target_teams: + case OMPD_target_teams_distribute: + case OMPD_target_teams_distribute_simd: + case OMPD_target_teams_distribute_parallel_for: + case OMPD_target_teams_distribute_parallel_for_simd: + case OMPD_teams_distribute_parallel_for: + case OMPD_teams_distribute_parallel_for_simd: + case OMPD_distribute_parallel_for: + case OMPD_distribute_parallel_for_simd: + case OMPD_task: + case OMPD_taskloop: + case OMPD_taskloop_simd: + case OMPD_target_data: + case OMPD_target_enter_data: + case OMPD_target_exit_data: + case OMPD_target_update: + // Do not capture if-clause expressions. + break; + case OMPD_threadprivate: + case OMPD_taskyield: + case OMPD_barrier: + case OMPD_taskwait: + case OMPD_cancellation_point: + case OMPD_flush: + case OMPD_declare_reduction: + case OMPD_declare_simd: + case OMPD_declare_target: + case OMPD_end_declare_target: + case OMPD_teams: + case OMPD_simd: + case OMPD_for: + case OMPD_for_simd: + case OMPD_sections: + case OMPD_section: + case OMPD_single: + case OMPD_master: + case OMPD_critical: + case OMPD_taskgroup: + case OMPD_distribute: + case OMPD_ordered: + case OMPD_atomic: + case OMPD_distribute_simd: + case OMPD_teams_distribute: + case OMPD_teams_distribute_simd: + llvm_unreachable("Unexpected OpenMP directive with if-clause"); + case OMPD_unknown: + llvm_unreachable("Unknown OpenMP directive"); + } + break; + case OMPC_num_threads: + switch (DKind) { + case OMPD_target_parallel: + CaptureRegion = OMPD_target; + break; + case OMPD_cancel: + case OMPD_parallel: + case OMPD_parallel_sections: + case OMPD_parallel_for: + case OMPD_parallel_for_simd: + case OMPD_target: + case OMPD_target_simd: + case OMPD_target_parallel_for: + case OMPD_target_parallel_for_simd: + case OMPD_target_teams: + case OMPD_target_teams_distribute: + case OMPD_target_teams_distribute_simd: + case OMPD_target_teams_distribute_parallel_for: + case OMPD_target_teams_distribute_parallel_for_simd: + case OMPD_teams_distribute_parallel_for: + case OMPD_teams_distribute_parallel_for_simd: + case OMPD_distribute_parallel_for: + case OMPD_distribute_parallel_for_simd: + case OMPD_task: + case OMPD_taskloop: + case OMPD_taskloop_simd: + case OMPD_target_data: + case OMPD_target_enter_data: + case OMPD_target_exit_data: + case OMPD_target_update: + // Do not capture num_threads-clause expressions. + break; + case OMPD_threadprivate: + case OMPD_taskyield: + case OMPD_barrier: + case OMPD_taskwait: + case OMPD_cancellation_point: + case OMPD_flush: + case OMPD_declare_reduction: + case OMPD_declare_simd: + case OMPD_declare_target: + case OMPD_end_declare_target: + case OMPD_teams: + case OMPD_simd: + case OMPD_for: + case OMPD_for_simd: + case OMPD_sections: + case OMPD_section: + case OMPD_single: + case OMPD_master: + case OMPD_critical: + case OMPD_taskgroup: + case OMPD_distribute: + case OMPD_ordered: + case OMPD_atomic: + case OMPD_distribute_simd: + case OMPD_teams_distribute: + case OMPD_teams_distribute_simd: + llvm_unreachable("Unexpected OpenMP directive with num_threads-clause"); + case OMPD_unknown: + llvm_unreachable("Unknown OpenMP directive"); + } + break; + case OMPC_num_teams: + switch (DKind) { + case OMPD_target_teams: + CaptureRegion = OMPD_target; + break; + case OMPD_cancel: + case OMPD_parallel: + case OMPD_parallel_sections: + case OMPD_parallel_for: + case OMPD_parallel_for_simd: + case OMPD_target: + case OMPD_target_simd: + case OMPD_target_parallel: + case OMPD_target_parallel_for: + case OMPD_target_parallel_for_simd: + case OMPD_target_teams_distribute: + case OMPD_target_teams_distribute_simd: + case OMPD_target_teams_distribute_parallel_for: + case OMPD_target_teams_distribute_parallel_for_simd: + case OMPD_teams_distribute_parallel_for: + case OMPD_teams_distribute_parallel_for_simd: + case OMPD_distribute_parallel_for: + case OMPD_distribute_parallel_for_simd: + case OMPD_task: + case OMPD_taskloop: + case OMPD_taskloop_simd: + case OMPD_target_data: + case OMPD_target_enter_data: + case OMPD_target_exit_data: + case OMPD_target_update: + case OMPD_teams: + case OMPD_teams_distribute: + case OMPD_teams_distribute_simd: + // Do not capture num_teams-clause expressions. + break; + case OMPD_threadprivate: + case OMPD_taskyield: + case OMPD_barrier: + case OMPD_taskwait: + case OMPD_cancellation_point: + case OMPD_flush: + case OMPD_declare_reduction: + case OMPD_declare_simd: + case OMPD_declare_target: + case OMPD_end_declare_target: + case OMPD_simd: + case OMPD_for: + case OMPD_for_simd: + case OMPD_sections: + case OMPD_section: + case OMPD_single: + case OMPD_master: + case OMPD_critical: + case OMPD_taskgroup: + case OMPD_distribute: + case OMPD_ordered: + case OMPD_atomic: + case OMPD_distribute_simd: + llvm_unreachable("Unexpected OpenMP directive with num_teams-clause"); + case OMPD_unknown: + llvm_unreachable("Unknown OpenMP directive"); + } + break; + case OMPC_thread_limit: + switch (DKind) { + case OMPD_target_teams: + CaptureRegion = OMPD_target; + break; + case OMPD_cancel: + case OMPD_parallel: + case OMPD_parallel_sections: + case OMPD_parallel_for: + case OMPD_parallel_for_simd: + case OMPD_target: + case OMPD_target_simd: + case OMPD_target_parallel: + case OMPD_target_parallel_for: + case OMPD_target_parallel_for_simd: + case OMPD_target_teams_distribute: + case OMPD_target_teams_distribute_simd: + case OMPD_target_teams_distribute_parallel_for: + case OMPD_target_teams_distribute_parallel_for_simd: + case OMPD_teams_distribute_parallel_for: + case OMPD_teams_distribute_parallel_for_simd: + case OMPD_distribute_parallel_for: + case OMPD_distribute_parallel_for_simd: + case OMPD_task: + case OMPD_taskloop: + case OMPD_taskloop_simd: + case OMPD_target_data: + case OMPD_target_enter_data: + case OMPD_target_exit_data: + case OMPD_target_update: + case OMPD_teams: + case OMPD_teams_distribute: + case OMPD_teams_distribute_simd: + // Do not capture thread_limit-clause expressions. + break; + case OMPD_threadprivate: + case OMPD_taskyield: + case OMPD_barrier: + case OMPD_taskwait: + case OMPD_cancellation_point: + case OMPD_flush: + case OMPD_declare_reduction: + case OMPD_declare_simd: + case OMPD_declare_target: + case OMPD_end_declare_target: + case OMPD_simd: + case OMPD_for: + case OMPD_for_simd: + case OMPD_sections: + case OMPD_section: + case OMPD_single: + case OMPD_master: + case OMPD_critical: + case OMPD_taskgroup: + case OMPD_distribute: + case OMPD_ordered: + case OMPD_atomic: + case OMPD_distribute_simd: + llvm_unreachable("Unexpected OpenMP directive with thread_limit-clause"); + case OMPD_unknown: + llvm_unreachable("Unknown OpenMP directive"); + } + break; + case OMPC_schedule: + case OMPC_dist_schedule: + case OMPC_firstprivate: + case OMPC_lastprivate: + case OMPC_reduction: + case OMPC_linear: + case OMPC_default: + case OMPC_proc_bind: + case OMPC_final: + case OMPC_safelen: + case OMPC_simdlen: + case OMPC_collapse: + case OMPC_private: + case OMPC_shared: + case OMPC_aligned: + case OMPC_copyin: + case OMPC_copyprivate: + case OMPC_ordered: + case OMPC_nowait: + case OMPC_untied: + case OMPC_mergeable: + case OMPC_threadprivate: + case OMPC_flush: + case OMPC_read: + case OMPC_write: + case OMPC_update: + case OMPC_capture: + case OMPC_seq_cst: + case OMPC_depend: + case OMPC_device: + case OMPC_threads: + case OMPC_simd: + case OMPC_map: + case OMPC_priority: + case OMPC_grainsize: + case OMPC_nogroup: + case OMPC_num_tasks: + case OMPC_hint: + case OMPC_defaultmap: + case OMPC_unknown: + case OMPC_uniform: + case OMPC_to: + case OMPC_from: + case OMPC_use_device_ptr: + case OMPC_is_device_ptr: + llvm_unreachable("Unexpected OpenMP clause."); + } + return CaptureRegion; +} + OMPClause *Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, @@ -6558,6 +6993,8 @@ OMPClause *Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, SourceLocation ColonLoc, SourceLocation EndLoc) { Expr *ValExpr = Condition; + Stmt *HelperValStmt = nullptr; + OpenMPDirectiveKind CaptureRegion = OMPD_unknown; if (!Condition->isValueDependent() && !Condition->isTypeDependent() && !Condition->isInstantiationDependent() && !Condition->containsUnexpandedParameterPack()) { @@ -6566,10 +7003,20 @@ OMPClause *Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, return nullptr; ValExpr = MakeFullExpr(Val.get()).get(); + + OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); + CaptureRegion = + getOpenMPCaptureRegionForClause(DKind, OMPC_if, NameModifier); + if (CaptureRegion != OMPD_unknown) { + llvm::MapVector<Expr *, DeclRefExpr *> Captures; + ValExpr = tryBuildCapture(*this, ValExpr, Captures).get(); + HelperValStmt = buildPreInits(Context, Captures); + } } - return new (Context) OMPIfClause(NameModifier, ValExpr, StartLoc, LParenLoc, - NameModifierLoc, ColonLoc, EndLoc); + return new (Context) + OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc, + LParenLoc, NameModifierLoc, ColonLoc, EndLoc); } OMPClause *Sema::ActOnOpenMPFinalClause(Expr *Condition, @@ -6665,6 +7112,8 @@ OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads, SourceLocation LParenLoc, SourceLocation EndLoc) { Expr *ValExpr = NumThreads; + Stmt *HelperValStmt = nullptr; + OpenMPDirectiveKind CaptureRegion = OMPD_unknown; // OpenMP [2.5, Restrictions] // The num_threads expression must evaluate to a positive integer value. @@ -6672,8 +7121,16 @@ OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads, /*StrictlyPositive=*/true)) return nullptr; - return new (Context) - OMPNumThreadsClause(ValExpr, StartLoc, LParenLoc, EndLoc); + OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); + CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_num_threads); + if (CaptureRegion != OMPD_unknown) { + llvm::MapVector<Expr *, DeclRefExpr *> Captures; + ValExpr = tryBuildCapture(*this, ValExpr, Captures).get(); + HelperValStmt = buildPreInits(Context, Captures); + } + + return new (Context) OMPNumThreadsClause( + ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc); } ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E, @@ -10451,7 +10908,8 @@ void Sema::ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D) { else CurContext = DRD; - PushExpressionEvaluationContext(PotentiallyEvaluated); + PushExpressionEvaluationContext( + ExpressionEvaluationContext::PotentiallyEvaluated); QualType ReductionType = DRD->getType(); // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will @@ -10505,7 +10963,8 @@ void Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D) { else CurContext = DRD; - PushExpressionEvaluationContext(PotentiallyEvaluated); + PushExpressionEvaluationContext( + ExpressionEvaluationContext::PotentiallyEvaluated); QualType ReductionType = DRD->getType(); // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will @@ -10566,6 +11025,8 @@ OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams, SourceLocation LParenLoc, SourceLocation EndLoc) { Expr *ValExpr = NumTeams; + Stmt *HelperValStmt = nullptr; + OpenMPDirectiveKind CaptureRegion = OMPD_unknown; // OpenMP [teams Constrcut, Restrictions] // The num_teams expression must evaluate to a positive integer value. @@ -10573,7 +11034,16 @@ OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams, /*StrictlyPositive=*/true)) return nullptr; - return new (Context) OMPNumTeamsClause(ValExpr, StartLoc, LParenLoc, EndLoc); + OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); + CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_num_teams); + if (CaptureRegion != OMPD_unknown) { + llvm::MapVector<Expr *, DeclRefExpr *> Captures; + ValExpr = tryBuildCapture(*this, ValExpr, Captures).get(); + HelperValStmt = buildPreInits(Context, Captures); + } + + return new (Context) OMPNumTeamsClause(ValExpr, HelperValStmt, CaptureRegion, + StartLoc, LParenLoc, EndLoc); } OMPClause *Sema::ActOnOpenMPThreadLimitClause(Expr *ThreadLimit, @@ -10581,6 +11051,8 @@ OMPClause *Sema::ActOnOpenMPThreadLimitClause(Expr *ThreadLimit, SourceLocation LParenLoc, SourceLocation EndLoc) { Expr *ValExpr = ThreadLimit; + Stmt *HelperValStmt = nullptr; + OpenMPDirectiveKind CaptureRegion = OMPD_unknown; // OpenMP [teams Constrcut, Restrictions] // The thread_limit expression must evaluate to a positive integer value. @@ -10588,8 +11060,16 @@ OMPClause *Sema::ActOnOpenMPThreadLimitClause(Expr *ThreadLimit, /*StrictlyPositive=*/true)) return nullptr; - return new (Context) - OMPThreadLimitClause(ValExpr, StartLoc, LParenLoc, EndLoc); + OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); + CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_thread_limit); + if (CaptureRegion != OMPD_unknown) { + llvm::MapVector<Expr *, DeclRefExpr *> Captures; + ValExpr = tryBuildCapture(*this, ValExpr, Captures).get(); + HelperValStmt = buildPreInits(Context, Captures); + } + + return new (Context) OMPThreadLimitClause( + ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc); } OMPClause *Sema::ActOnOpenMPPriorityClause(Expr *Priority, |