https://github.com/kevinsala updated https://github.com/llvm/llvm-project/pull/208353
>From 62e4015a676c1948402df1f484b3c36c11e8ffad Mon Sep 17 00:00:00 2001 From: Kevin Sala <[email protected]> Date: Wed, 8 Jul 2026 13:14:49 -0700 Subject: [PATCH] [Clang][OpenMP] Add parsing/sema for dims modifier in num_threads --- clang/docs/OpenMPSupport.rst | 3 +- clang/docs/ReleaseNotes.md | 4 +- clang/include/clang/AST/OpenMPClause.h | 185 ++++++++++++++---- clang/include/clang/AST/RecursiveASTVisitor.h | 4 +- clang/include/clang/Basic/OpenMPKinds.def | 3 +- clang/include/clang/Sema/SemaOpenMP.h | 9 +- clang/lib/AST/OpenMPClause.cpp | 59 +++++- clang/lib/AST/StmtProfile.cpp | 7 +- clang/lib/CodeGen/CGExprScalar.cpp | 1 + clang/lib/CodeGen/CGOpenMPRuntime.cpp | 6 +- clang/lib/CodeGen/CGStmtOpenMP.cpp | 6 +- clang/lib/Parse/ParseOpenMP.cpp | 113 +++++++---- clang/lib/Sema/SemaOpenMP.cpp | 91 +++++---- clang/lib/Sema/TreeTransform.h | 41 ++-- clang/lib/Serialization/ASTReader.cpp | 17 +- clang/lib/Serialization/ASTWriter.cpp | 11 +- clang/test/OpenMP/dims_modifier_ast_print.cpp | 62 ++++++ clang/test/OpenMP/dims_modifier_messages.cpp | 54 ++++- ...bute_parallel_for_num_threads_messages.cpp | 4 +- ...parallel_for_simd_num_threads_messages.cpp | 4 +- .../parallel_for_num_threads_messages.cpp | 4 +- ...parallel_for_simd_num_threads_messages.cpp | 4 +- .../parallel_masked_num_threads_messages.cpp | 4 +- .../parallel_master_num_threads_messages.cpp | 4 +- .../OpenMP/parallel_num_threads_messages.cpp | 28 +-- ...parallel_sections_num_threads_messages.cpp | 4 +- ...rget_parallel_for_num_threads_messages.cpp | 4 +- ...parallel_for_simd_num_threads_messages.cpp | 4 +- .../target_parallel_num_threads_messages.cpp | 28 +-- ...bute_parallel_for_num_threads_messages.cpp | 4 +- ...parallel_for_simd_num_threads_messages.cpp | 4 +- ...parallel_for_simd_num_threads_messages.cpp | 4 +- clang/tools/libclang/CIndex.cpp | 4 +- 33 files changed, 583 insertions(+), 201 deletions(-) diff --git a/clang/docs/OpenMPSupport.rst b/clang/docs/OpenMPSupport.rst index d0f667f4df50c..3b14447ba7a57 100644 --- a/clang/docs/OpenMPSupport.rst +++ b/clang/docs/OpenMPSupport.rst @@ -682,7 +682,8 @@ implementation. | | | | RT: @abhinavgaba (https://github.com/llvm/llvm-project/pull/169603) | +-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ | dims modifier for num_teams, thread_limit and num_threads | :part:`partial` | :part:`In Progress` | C/C++: kevinsala | -| (multidimensional teams and leagues) | | | Clang Parsing/Sema: https://github.com/llvm/llvm-project/pull/206412 | +| (multidimensional teams and leagues) | | | Clang Parsing/Sema: https://github.com/llvm/llvm-project/pull/206412, | +| | | | https://github.com/llvm/llvm-project/pull/208353 | | | | | Fortran: skc7, kparzysz, mjklemm | +-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 39392e9d10b74..401cfc39f0d7b 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -1150,8 +1150,8 @@ latest release, please see the [Clang Web Site](https://clang.llvm.org) or the (e.g. `std::complex`). The private copy is now initialized to the multiplicative identity instead of being value-initialized, which previously produced a wrong result (the product collapsed to the additive identity). -- Added parsing and semantic support for `dims` modifier in `num_teams` and - `thread_limit` clauses when OpenMP >= 61. +- Added parsing and semantic support for `dims` modifier in `num_teams`, + `thread_limit`, and `num_threads` clauses when OpenMP >= 61. ### SYCL Support diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h index 641c03bf8ff5c..1a9f285e67475 100644 --- a/clang/include/clang/AST/OpenMPClause.h +++ b/clang/include/clang/AST/OpenMPClause.h @@ -804,67 +804,176 @@ class OMPFinalClause final return const_cast<OMPFinalClause *>(this)->used_children(); } }; + /// This represents 'num_threads' clause in the '#pragma omp ...' /// directive. /// /// \code -/// #pragma omp parallel num_threads(6) +/// #pragma omp parallel num_threads(n) +/// \endcode +/// In this example directive '#pragma omp parallel' has 'num_threads' clause +/// requesting 'n' threads. +/// +/// \code +/// #pragma omp parallel num_threads(strict: n) /// \endcode -/// In this example directive '#pragma omp parallel' has simple 'num_threads' -/// clause with number of threads '6'. +/// In this example directive '#pragma omp parallel' has 'num_threads' clause +/// requesting 'n' threads strictly with the 'strict' modifier. +/// +/// \code +/// #pragma omp parallel num_threads(dims(2): x, y) +/// \endcode +/// In this example directive '#pragma omp parallel' has clause 'num_threads' +/// with the 'dims' modifier specifying two dimensions. The list specifies the +/// number of threads in each dimension. class OMPNumThreadsClause final - : public OMPOneStmtClause<llvm::omp::OMPC_num_threads, OMPClause>, - public OMPClauseWithPreInit { + : public OMPVarListClause<OMPNumThreadsClause>, + public OMPClauseWithPreInit, + private llvm::TrailingObjects<OMPNumThreadsClause, Expr *> { + friend class OMPVarListClause<OMPNumThreadsClause>; + friend TrailingObjects; friend class OMPClauseReader; - /// Modifiers for 'num_threads' clause. - OpenMPNumThreadsClauseModifier Modifier = OMPC_NUMTHREADS_unknown; +private: + /// Categories of modifiers for the 'num_threads' clause. + enum { PRESCRIPTIVENESS, DIMS, NUM_MODIFIERS }; - /// Location of the modifier. - SourceLocation ModifierLoc; + /// Modifiers for the clause, indexed by category. + OpenMPNumThreadsClauseModifier Modifiers[NUM_MODIFIERS] = { + OMPC_NUMTHREADS_unknown, OMPC_NUMTHREADS_unknown}; - /// Sets modifier. - void setModifier(OpenMPNumThreadsClauseModifier M) { Modifier = M; } + /// Locations of the modifiers, indexed by category. + SourceLocation ModifiersLoc[NUM_MODIFIERS]; - /// Sets modifier location. - void setModifierLoc(SourceLocation Loc) { ModifierLoc = Loc; } + /// Build clause with number of expressions \a N. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param N Number of expressions. + OMPNumThreadsClause(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc, + unsigned N) + : OMPVarListClause<OMPNumThreadsClause>(llvm::omp::OMPC_num_threads, + StartLoc, LParenLoc, EndLoc, N), + OMPClauseWithPreInit(this) {} - /// Set condition. - void setNumThreads(Expr *NThreads) { setStmt(NThreads); } + /// Build an empty clause. + /// + /// \param N Number of expressions. + explicit OMPNumThreadsClause(unsigned N) + : OMPVarListClause<OMPNumThreadsClause>( + llvm::omp::OMPC_num_threads, SourceLocation(), SourceLocation(), + SourceLocation(), N), + OMPClauseWithPreInit(this) {} + + /// Sets the dims modifier. + void setDimsModifier(OpenMPNumThreadsClauseModifier M) { + Modifiers[DIMS] = M; + } + + /// Sets the prescriptiveness modifier. + void setPrescriptivenessModifier(OpenMPNumThreadsClauseModifier M) { + Modifiers[PRESCRIPTIVENESS] = M; + } + + /// Sets the location of the prescriptiveness modifier. + void setPrescriptivenessModifierLoc(SourceLocation Loc) { + ModifiersLoc[PRESCRIPTIVENESS] = Loc; + } + + /// Sets the location of the dims modifier. + void setDimsModifierLoc(SourceLocation Loc) { ModifiersLoc[DIMS] = Loc; } + + /// Sets the dims modifier expression. + void setDimsModifierExpr(Expr *E) { *varlist_end() = E; } public: - /// Build 'num_threads' clause with condition \a NumThreads. + /// Creates clause with a list of variables/expressions. /// - /// \param Modifier Clause modifier. - /// \param NumThreads Number of threads for the construct. - /// \param HelperNumThreads Helper Number of threads for the construct. - /// \param CaptureRegion Innermost OpenMP region where expressions in this - /// clause must be captured. + /// \param C AST context. + /// \param CaptureRegion The captured region for the pre-init statements. /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. - /// \param ModifierLoc Modifier location. /// \param EndLoc Ending location of the clause. - OMPNumThreadsClause(OpenMPNumThreadsClauseModifier Modifier, Expr *NumThreads, - Stmt *HelperNumThreads, OpenMPDirectiveKind CaptureRegion, - SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation ModifierLoc, SourceLocation EndLoc) - : OMPOneStmtClause(NumThreads, StartLoc, LParenLoc, EndLoc), - OMPClauseWithPreInit(this), Modifier(Modifier), - ModifierLoc(ModifierLoc) { - setPreInitStmt(HelperNumThreads, CaptureRegion); + /// \param VL List of references to the expressions. + /// \param PrescriptivenessModifier The prescriptiveness modifier. + /// \param DimsModifier The dims modifier. + /// \param PrescriptivenessModifierLoc Location of the prescriptiveness + /// modifier. + /// \param DimsModifierLoc Location of the dims modifier. + /// \param DimsModifierExpr The expression of the number of dimensions. + /// \param PreInit + static OMPNumThreadsClause * + Create(const ASTContext &C, OpenMPDirectiveKind CaptureRegion, + SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef<Expr *> VL, + OpenMPNumThreadsClauseModifier PrescriptivenessModifier, + OpenMPNumThreadsClauseModifier DimsModifier, + SourceLocation PrescriptivenessModifierLoc, + SourceLocation DimsModifierLoc, Expr *DimsModifierExpr, Stmt *PreInit); + + /// Creates an empty clause with the place for \a N expressions. + /// + /// \param C AST context. + /// \param N The number of expressions. + static OMPNumThreadsClause *CreateEmpty(const ASTContext &C, unsigned N); + + /// Return NumThreads expressions. + ArrayRef<Expr *> getNumThreads() { return getVarRefs(); } + ArrayRef<Expr *> getNumThreads() const { + return const_cast<OMPNumThreadsClause *>(this)->getNumThreads(); } - /// Build an empty clause. - OMPNumThreadsClause() : OMPOneStmtClause(), OMPClauseWithPreInit(this) {} + /// Returns the prescriptiveness modifier. + OpenMPNumThreadsClauseModifier getPrescriptivenessModifier() const { + return Modifiers[PRESCRIPTIVENESS]; + } + /// Returns the location of the prescriptiveness modifier. + SourceLocation getPrescriptivenessModifierLoc() const { + return ModifiersLoc[PRESCRIPTIVENESS]; + } - /// Gets modifier. - OpenMPNumThreadsClauseModifier getModifier() const { return Modifier; } + /// Returns the dims modifier. + OpenMPNumThreadsClauseModifier getDimsModifier() const { + return Modifiers[DIMS]; + } + /// Returns the location of the dims modifier. + SourceLocation getDimsModifierLoc() const { return ModifiersLoc[DIMS]; } - /// Gets modifier location. - SourceLocation getModifierLoc() const { return ModifierLoc; } + /// Checks if the clause has the dims modifier. + bool hasDimsModifier() const { + return Modifiers[DIMS] == OMPC_NUMTHREADS_dims; + } - /// Returns number of threads. - Expr *getNumThreads() const { return getStmtAs<Expr>(); } + /// Returns the dims modifier expression if present. + Expr *getDimsModifierExpr() { + return hasDimsModifier() ? *varlist_end() : nullptr; + } + /// Returns the dims modifier expression if present. + const Expr *getDimsModifierExpr() const { + return const_cast<OMPNumThreadsClause *>(this)->getDimsModifierExpr(); + } + + child_range children() { + return child_range(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end()) + 1); + } + const_child_range children() const { + return const_cast<OMPNumThreadsClause *>(this)->children(); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == llvm::omp::OMPC_num_threads; + } }; /// This represents 'safelen' clause in the '#pragma omp ...' diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 84aaac71746ed..1c0c182241064 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -3501,8 +3501,10 @@ bool RecursiveASTVisitor<Derived>::VisitOMPFinalClause(OMPFinalClause *C) { template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) { + if (auto *E = C->getDimsModifierExpr()) + TRY_TO(VisitStmt(E)); + TRY_TO(VisitOMPClauseList(C)); TRY_TO(VisitOMPClauseWithPreInit(C)); - TRY_TO(TraverseStmt(C->getNumThreads())); return true; } diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def index 5c396a5d2d4b3..5b5222a2ab446 100644 --- a/clang/include/clang/Basic/OpenMPKinds.def +++ b/clang/include/clang/Basic/OpenMPKinds.def @@ -278,8 +278,9 @@ OPENMP_NUMTASKS_MODIFIER(strict) OPENMP_NUMTEAMS_MODIFIER(lower_bound) OPENMP_NUMTEAMS_MODIFIER(dims) -// Modifiers for the 'num_tasks' clause. +// Modifiers for the 'num_threads' clause. OPENMP_NUMTHREADS_MODIFIER(strict) +OPENMP_NUMTHREADS_MODIFIER(dims) // Modifiers for the 'thread_limit' clause. OPENMP_THREADLIMIT_MODIFIER(dims) diff --git a/clang/include/clang/Sema/SemaOpenMP.h b/clang/include/clang/Sema/SemaOpenMP.h index 9ef388a744db8..93f8bd7f85958 100644 --- a/clang/include/clang/Sema/SemaOpenMP.h +++ b/clang/include/clang/Sema/SemaOpenMP.h @@ -898,9 +898,12 @@ class SemaOpenMP : public SemaBase { SourceLocation EndLoc); /// Called on well-formed 'num_threads' clause. OMPClause *ActOnOpenMPNumThreadsClause( - OpenMPNumThreadsClauseModifier Modifier, Expr *NumThreads, - SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation ModifierLoc, SourceLocation EndLoc); + ArrayRef<Expr *> VarList, + OpenMPNumThreadsClauseModifier PrescriptivenessModifier, + SourceLocation PrescriptivenessModifierLoc, + OpenMPNumThreadsClauseModifier DimsModifier, Expr *DimsModifierExpr, + SourceLocation DimsModifierLoc, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc); /// Called on well-formed 'align' clause. OMPClause *ActOnOpenMPAlignClause(Expr *Alignment, SourceLocation StartLoc, SourceLocation LParenLoc, diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp index d451255bf5845..2860a96d4e3e4 100644 --- a/clang/lib/AST/OpenMPClause.cpp +++ b/clang/lib/AST/OpenMPClause.cpp @@ -1999,6 +1999,35 @@ OMPThreadLimitClause *OMPThreadLimitClause::CreateEmpty(const ASTContext &C, return new (Mem) OMPThreadLimitClause(N); } +OMPNumThreadsClause *OMPNumThreadsClause::Create( + const ASTContext &C, OpenMPDirectiveKind CaptureRegion, + SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, + ArrayRef<Expr *> VL, + OpenMPNumThreadsClauseModifier PrescriptivenessModifier, + OpenMPNumThreadsClauseModifier DimsModifier, + SourceLocation PrescriptivenessModifierLoc, SourceLocation DimsModifierLoc, + Expr *DimsModifierExpr, Stmt *PreInit) { + // Reserve space for an extra modifier expression. + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size() + 1)); + OMPNumThreadsClause *Clause = + new (Mem) OMPNumThreadsClause(C, StartLoc, LParenLoc, EndLoc, VL.size()); + Clause->setVarRefs(VL); + Clause->setPrescriptivenessModifier(PrescriptivenessModifier); + Clause->setPrescriptivenessModifierLoc(PrescriptivenessModifierLoc); + Clause->setDimsModifier(DimsModifier); + Clause->setDimsModifierExpr(DimsModifierExpr); + Clause->setDimsModifierLoc(DimsModifierLoc); + Clause->setPreInitStmt(PreInit, CaptureRegion); + return Clause; +} + +OMPNumThreadsClause *OMPNumThreadsClause::CreateEmpty(const ASTContext &C, + unsigned N) { + // Reserve space for an extra modifier expression. + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N + 1)); + return new (Mem) OMPNumThreadsClause(N); +} + //===----------------------------------------------------------------------===// // OpenMP clauses printing methods //===----------------------------------------------------------------------===// @@ -2018,14 +2047,30 @@ void OMPClausePrinter::VisitOMPFinalClause(OMPFinalClause *Node) { } void OMPClausePrinter::VisitOMPNumThreadsClause(OMPNumThreadsClause *Node) { - OS << "num_threads("; - OpenMPNumThreadsClauseModifier Modifier = Node->getModifier(); - if (Modifier != OMPC_NUMTHREADS_unknown) { - OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), Modifier) - << ": "; + if (!Node->varlist_empty()) { + OS << "num_threads"; + bool HasPrescriptiveness = + Node->getPrescriptivenessModifier() != OMPC_NUMTHREADS_unknown; + bool HasDims = Node->getDimsModifier() != OMPC_NUMTHREADS_unknown; + if (HasPrescriptiveness || HasDims) { + OS << "("; + if (HasPrescriptiveness) + OS << getOpenMPSimpleClauseTypeName( + Node->getClauseKind(), Node->getPrescriptivenessModifier()); + if (HasPrescriptiveness && HasDims) + OS << ","; + if (HasDims) { + OS << "dims("; + Node->getDimsModifierExpr()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; + } + OS << ":"; + VisitOMPClauseList(Node, ' '); + } else { + VisitOMPClauseList(Node, '('); + } + OS << ")"; } - Node->getNumThreads()->printPretty(OS, nullptr, Policy, 0); - OS << ")"; } void OMPClausePrinter::VisitOMPAlignClause(OMPAlignClause *Node) { diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 291c72385518e..0751783483bf6 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -475,9 +475,12 @@ void OMPClauseProfiler::VisitOMPFinalClause(const OMPFinalClause *C) { } void OMPClauseProfiler::VisitOMPNumThreadsClause(const OMPNumThreadsClause *C) { + Profiler->VisitInteger(C->getPrescriptivenessModifier()); + Profiler->VisitInteger(C->getDimsModifier()); + if (const Expr *Modifier = C->getDimsModifierExpr()) + Profiler->VisitStmt(Modifier); + VisitOMPClauseList(C); VisitOMPClauseWithPreInit(C); - if (C->getNumThreads()) - Profiler->VisitStmt(C->getNumThreads()); } void OMPClauseProfiler::VisitOMPAlignClause(const OMPAlignClause *C) { diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 18ed6570730f4..f957eb4d859c9 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -6201,6 +6201,7 @@ Value *ScalarExprEmitter::VisitAtomicExpr(AtomicExpr *E) { /// Emit the computation of the specified expression of scalar type, ignoring /// the result. Value *CodeGenFunction::EmitScalarExpr(const Expr *E, bool IgnoreResultAssign) { + assert(E && "Invalid expression to emit"); assert(E && hasScalarEvaluationKind(E->getType()) && "Invalid scalar expression to emit"); diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index eb2f92cdbf972..67d575d9d5e0d 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -6701,7 +6701,7 @@ static void getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); const auto *NumThreadsClause = Dir->getSingleClause<OMPNumThreadsClause>(); - const Expr *NTExpr = NumThreadsClause->getNumThreads(); + const Expr *NTExpr = NumThreadsClause->getNumThreads().front(); if (NTExpr->isIntegerConstantExpr(CGF.getContext())) if (auto Constant = NTExpr->getIntegerConstantExpr(CGF.getContext())) UpperBound = @@ -6887,8 +6887,8 @@ const Expr *CGOpenMPRuntime::getNumThreadsExprForTargetDirective( if (D.hasClausesOfKind<OMPNumThreadsClause>()) { CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>(); - CheckForConstExpr(NumThreadsClause->getNumThreads(), nullptr); - return NumThreadsClause->getNumThreads(); + CheckForConstExpr(NumThreadsClause->getNumThreads().front(), nullptr); + return NumThreadsClause->getNumThreads().front(); } return NT; } diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 88f698f38cce0..9174f6c63a751 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -1913,9 +1913,9 @@ static void emitCommonOMPParallelDirective( if (const auto *NumThreadsClause = S.getSingleClause<OMPNumThreadsClause>()) { CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); - NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads(), + NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads().front(), /*IgnoreResultAssign=*/true); - Modifier = NumThreadsClause->getModifier(); + Modifier = NumThreadsClause->getPrescriptivenessModifier(); if (const auto *MessageClause = S.getSingleClause<OMPMessageClause>()) { Message = MessageClause->getMessageString(); MessageLoc = MessageClause->getBeginLoc(); @@ -2113,7 +2113,7 @@ void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) { llvm::Value *NumThreads = nullptr; if (const auto *NumThreadsClause = S.getSingleClause<OMPNumThreadsClause>()) - NumThreads = EmitScalarExpr(NumThreadsClause->getNumThreads(), + NumThreads = EmitScalarExpr(NumThreadsClause->getNumThreads().front(), /*IgnoreResultAssign=*/true); ProcBindKind ProcBind = OMP_PROC_BIND_default; diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 7ef1e4211a1ef..4e19082f8f814 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -3231,7 +3231,6 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, switch (CKind) { case OMPC_final: - case OMPC_num_threads: case OMPC_safelen: case OMPC_simdlen: case OMPC_collapse: @@ -3297,7 +3296,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, PP.LookAhead(/*N=*/0).isNot(tok::l_paren)) Clause = ParseOpenMPClause(CKind, WrongDirective); else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks || - CKind == OMPC_num_threads || CKind == OMPC_dyn_groupprivate) + CKind == OMPC_dyn_groupprivate) Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective); else Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective); @@ -3428,6 +3427,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, break; case OMPC_num_teams: case OMPC_thread_limit: + case OMPC_num_threads: if (!FirstClause) { Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind, OMPVersion) @@ -4331,33 +4331,6 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind, Arg.push_back(OMPC_NUMTASKS_unknown); KLoc.emplace_back(); } - } else if (Kind == OMPC_num_threads) { - // Parse optional <num_threads modifier> ':' - OpenMPNumThreadsClauseModifier Modifier = - static_cast<OpenMPNumThreadsClauseModifier>(getOpenMPSimpleClauseType( - Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), - getLangOpts())); - if (getLangOpts().OpenMP >= 60) { - if (NextToken().is(tok::colon)) { - Arg.push_back(Modifier); - KLoc.push_back(Tok.getLocation()); - // Parse modifier - ConsumeAnyToken(); - // Parse ':' - ConsumeAnyToken(); - } else { - if (Modifier == OMPC_NUMTHREADS_strict) { - Diag(Tok, diag::err_modifier_expected_colon) << "strict"; - // Parse modifier - ConsumeAnyToken(); - } - Arg.push_back(OMPC_NUMTHREADS_unknown); - KLoc.emplace_back(); - } - } else { - Arg.push_back(OMPC_NUMTHREADS_unknown); - KLoc.emplace_back(); - } } else { assert(Kind == OMPC_if); KLoc.push_back(Tok.getLocation()); @@ -4378,11 +4351,11 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind, } } - bool NeedAnExpression = - (Kind == OMPC_schedule && DelimLoc.isValid()) || - (Kind == OMPC_dist_schedule && DelimLoc.isValid()) || Kind == OMPC_if || - Kind == OMPC_device || Kind == OMPC_grainsize || Kind == OMPC_num_tasks || - Kind == OMPC_num_threads || Kind == OMPC_dyn_groupprivate; + bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) || + (Kind == OMPC_dist_schedule && DelimLoc.isValid()) || + Kind == OMPC_if || Kind == OMPC_device || + Kind == OMPC_grainsize || Kind == OMPC_num_tasks || + Kind == OMPC_dyn_groupprivate; if (NeedAnExpression) { SourceLocation ELoc = Tok.getLocation(); ExprResult LHS( @@ -5355,6 +5328,78 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, TPA.Revert(); } } + } else if (Kind == OMPC_num_threads) { + Data.ExtraModifierArray[0] = static_cast<int>(OMPC_NUMTHREADS_unknown); + Data.ExtraModifierArray[1] = static_cast<int>(OMPC_NUMTHREADS_unknown); + + bool HasModifier = false; + while (true) { + if (Tok.is(tok::identifier) && Tok.getIdentifierInfo()->isStr("dims") && + NextToken().is(tok::l_paren)) { + + SourceLocation TLoc = Tok.getLocation(); + ConsumeToken(); + SourceLocation RLoc; + + ExprResult ExprR = + ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc); + + if (Data.ExtraModifierArray[1] != OMPC_NUMTHREADS_unknown) { + Diag(TLoc, diag::err_omp_duplicate_modifier) + << getOpenMPSimpleClauseTypeName(Kind, OMPC_NUMTHREADS_dims) + << getOpenMPClauseName(Kind); + } else if (ExprR.isUsable()) { + Data.ExtraModifierArray[1] = static_cast<int>(OMPC_NUMTHREADS_dims); + Data.ExtraModifierExprArray[1] = ExprR.get(); + Data.ExtraModifierLocArray[1] = TLoc; + } + HasModifier = true; + } else { + StringRef ModName = Tok.isAnnotation() ? "" : PP.getSpelling(Tok); + OpenMPNumThreadsClauseModifier Modifier = + static_cast<OpenMPNumThreadsClauseModifier>( + getOpenMPSimpleClauseType(Kind, ModName, getLangOpts())); + + // The dims modifier is a complex modifier. It must be parsed above. + if (Modifier == OMPC_NUMTHREADS_dims) + Modifier = OMPC_NUMTHREADS_unknown; + + if (Modifier != OMPC_NUMTHREADS_unknown) { + if (Data.ExtraModifierArray[0] != OMPC_NUMTHREADS_unknown) { + Diag(Tok, diag::err_omp_duplicate_modifier) + << getOpenMPSimpleClauseTypeName(Kind, OMPC_NUMTHREADS_strict) + << getOpenMPClauseName(Kind); + } else { + Data.ExtraModifierArray[0] = Modifier; + Data.ExtraModifierLocArray[0] = Tok.getLocation(); + } + ConsumeAnyToken(); + HasModifier = true; + } else { + break; + } + } + + if (Tok.is(tok::comma)) { + ConsumeToken(); + } else { + break; + } + } + + if (HasModifier) { + if (Tok.is(tok::colon)) { + ConsumeToken(); + } else { + Diag(Tok, diag::err_modifier_expected_colon) + << getOpenMPClauseName(Kind); + SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); + Data.RLoc = Tok.getLocation(); + if (!T.consumeClose()) + Data.RLoc = T.getCloseLocation(); + return true; + } + } } bool IsComma = diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index f961c2887d9ed..1ba8644765ec8 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -17341,43 +17341,62 @@ static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First, } OMPClause *SemaOpenMP::ActOnOpenMPNumThreadsClause( - OpenMPNumThreadsClauseModifier Modifier, Expr *NumThreads, - SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation ModifierLoc, SourceLocation EndLoc) { - assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 60) && - "Unexpected num_threads modifier in OpenMP < 60."); - - if (ModifierLoc.isValid() && Modifier == OMPC_NUMTHREADS_unknown) { - std::string Values = getListOfPossibleValues(OMPC_num_threads, /*First=*/0, - OMPC_NUMTHREADS_unknown); - Diag(ModifierLoc, diag::err_omp_unexpected_clause_value) - << Values << getOpenMPClauseNameForDiag(OMPC_num_threads); - return nullptr; + ArrayRef<Expr *> VarList, + OpenMPNumThreadsClauseModifier PrescriptivenessModifier, + SourceLocation PrescriptivenessModifierLoc, + OpenMPNumThreadsClauseModifier DimsModifier, Expr *DimsModifierExpr, + SourceLocation DimsModifierLoc, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc) { + SmallVector<Expr *, 3> Vars(VarList.begin(), VarList.end()); + for (Expr *&ValExpr : Vars) { + // OpenMP [2.5, Restrictions] + // The num_threads expression must evaluate to a positive integer value. + if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_threads, + /*StrictlyPositive=*/true)) + return nullptr; } - Expr *ValExpr = NumThreads; - Stmt *HelperValStmt = nullptr; + if (DimsModifier == OMPC_NUMTHREADS_dims) { + ExprResult Res = ActOnOpenMPDimsModifier(OMPC_num_threads, DimsModifier, + DimsModifierExpr, DimsModifierLoc, + Vars, EndLoc); + if (Res.isInvalid()) + return nullptr; + DimsModifierExpr = Res.get(); - // OpenMP [2.5, Restrictions] - // The num_threads expression must evaluate to a positive integer value. - if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_threads, - /*StrictlyPositive=*/true)) + if (validateMultidimClauseExprs(*this, OMPC_num_threads, StartLoc, Vars, + DimsModifierExpr)) + return nullptr; + } + if (PrescriptivenessModifier == OMPC_NUMTHREADS_strict && + getLangOpts().OpenMP < 60) { + Diag(PrescriptivenessModifierLoc, diag::err_omp_modifier_requires_version) + << getOpenMPSimpleClauseTypeName(llvm::omp::OMPC_num_threads, + PrescriptivenessModifier) + << getOpenMPClauseName(llvm::omp::OMPC_num_threads) << "6.0"; return nullptr; + } OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause( DKind, OMPC_num_threads, getLangOpts().OpenMP); - if (CaptureRegion != OMPD_unknown && - !SemaRef.CurContext->isDependentContext()) { + if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext()) + return OMPNumThreadsClause::Create( + getASTContext(), CaptureRegion, StartLoc, LParenLoc, EndLoc, Vars, + PrescriptivenessModifier, DimsModifier, PrescriptivenessModifierLoc, + DimsModifierLoc, DimsModifierExpr, /*PreInit=*/nullptr); + + llvm::MapVector<const Expr *, DeclRefExpr *> Captures; + for (Expr *&ValExpr : Vars) { ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); - llvm::MapVector<const Expr *, DeclRefExpr *> Captures; ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get(); - HelperValStmt = buildPreInits(getASTContext(), Captures); } + Stmt *PreInit = buildPreInits(getASTContext(), Captures); - return new (getASTContext()) - OMPNumThreadsClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, - StartLoc, LParenLoc, ModifierLoc, EndLoc); + return OMPNumThreadsClause::Create( + getASTContext(), CaptureRegion, StartLoc, LParenLoc, EndLoc, Vars, + PrescriptivenessModifier, DimsModifier, PrescriptivenessModifierLoc, + DimsModifierLoc, DimsModifierExpr, PreInit); } ExprResult SemaOpenMP::VerifyPositiveIntegerConstantInClause( @@ -18398,13 +18417,6 @@ OMPClause *SemaOpenMP::ActOnOpenMPSingleExprWithArgClause( ArgumentLoc[Modifier2], EndLoc); break; } - case OMPC_num_threads: - assert(Argument.size() == 1 && ArgumentLoc.size() == 1 && - "Modifier for num_threads clause and its location are expected."); - Res = ActOnOpenMPNumThreadsClause( - static_cast<OpenMPNumThreadsClauseModifier>(Argument.back()), Expr, - StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc); - break; case OMPC_final: case OMPC_safelen: case OMPC_simdlen: @@ -19387,10 +19399,23 @@ OMPClause *SemaOpenMP::ActOnOpenMPVarListClause(OpenMPClauseKind Kind, VarList, static_cast<OpenMPThreadLimitClauseModifier>(ExtraModifier), ExtraModifierExpr, ExtraModifierLoc, StartLoc, LParenLoc, EndLoc); break; + case OMPC_num_threads: + assert(0 <= Data.ExtraModifierArray[0] && + Data.ExtraModifierArray[0] <= OMPC_NUMTHREADS_unknown && + 0 <= Data.ExtraModifierArray[1] && + Data.ExtraModifierArray[1] <= OMPC_NUMTHREADS_unknown && + "Unexpected num_threads modifier."); + Res = ActOnOpenMPNumThreadsClause( + VarList, + static_cast<OpenMPNumThreadsClauseModifier>(Data.ExtraModifierArray[0]), + Data.ExtraModifierLocArray[0], + static_cast<OpenMPNumThreadsClauseModifier>(Data.ExtraModifierArray[1]), + Data.ExtraModifierExprArray[1], Data.ExtraModifierLocArray[1], StartLoc, + LParenLoc, EndLoc); + break; case OMPC_if: case OMPC_depobj: case OMPC_final: - case OMPC_num_threads: case OMPC_safelen: case OMPC_simdlen: case OMPC_sizes: diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 92df2e622a37c..775d591787e5b 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -1730,14 +1730,17 @@ class TreeTransform { /// /// By default, performs semantic analysis to build the new OpenMP clause. /// Subclasses may override this routine to provide different behavior. - OMPClause *RebuildOMPNumThreadsClause(OpenMPNumThreadsClauseModifier Modifier, - Expr *NumThreads, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation ModifierLoc, - SourceLocation EndLoc) { + OMPClause *RebuildOMPNumThreadsClause( + ArrayRef<Expr *> VarList, + OpenMPNumThreadsClauseModifier PrescriptivenessModifier, + SourceLocation PrescriptivenessModifierLoc, + OpenMPNumThreadsClauseModifier DimsModifier, Expr *DimsModifierExpr, + SourceLocation DimsModifierLoc, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc) { return getSema().OpenMP().ActOnOpenMPNumThreadsClause( - Modifier, NumThreads, StartLoc, LParenLoc, ModifierLoc, EndLoc); + VarList, PrescriptivenessModifier, PrescriptivenessModifierLoc, + DimsModifier, DimsModifierExpr, DimsModifierLoc, StartLoc, LParenLoc, + EndLoc); } /// Build a new OpenMP 'safelen' clause. @@ -10586,12 +10589,26 @@ OMPClause *TreeTransform<Derived>::TransformOMPFinalClause(OMPFinalClause *C) { template <typename Derived> OMPClause * TreeTransform<Derived>::TransformOMPNumThreadsClause(OMPNumThreadsClause *C) { - ExprResult NumThreads = getDerived().TransformExpr(C->getNumThreads()); - if (NumThreads.isInvalid()) - return nullptr; + llvm::SmallVector<Expr *, 3> Vars; + Vars.reserve(C->varlist_size()); + for (auto *VE : C->varlist()) { + ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE)); + if (EVar.isInvalid()) + return nullptr; + Vars.push_back(EVar.get()); + } + Expr *DimsModifierExpr = C->getDimsModifierExpr(); + if (DimsModifierExpr) { + ExprResult EVar = getDerived().TransformExpr(cast<Expr>(DimsModifierExpr)); + if (EVar.isInvalid()) + return nullptr; + DimsModifierExpr = EVar.get(); + } return getDerived().RebuildOMPNumThreadsClause( - C->getModifier(), NumThreads.get(), C->getBeginLoc(), C->getLParenLoc(), - C->getModifierLoc(), C->getEndLoc()); + Vars, C->getPrescriptivenessModifier(), + C->getPrescriptivenessModifierLoc(), C->getDimsModifier(), + DimsModifierExpr, C->getDimsModifierLoc(), C->getBeginLoc(), + C->getLParenLoc(), C->getEndLoc()); } template <typename Derived> diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 3189bf3431c1e..6a2118511abf6 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -11466,7 +11466,7 @@ OMPClause *OMPClauseReader::readClause() { C = new (Context) OMPFinalClause(); break; case llvm::omp::OMPC_num_threads: - C = new (Context) OMPNumThreadsClause(); + C = OMPNumThreadsClause::CreateEmpty(Context, Record.readInt()); break; case llvm::omp::OMPC_safelen: C = new (Context) OMPSafelenClause(); @@ -11878,11 +11878,20 @@ void OMPClauseReader::VisitOMPFinalClause(OMPFinalClause *C) { } void OMPClauseReader::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) { + C->setPrescriptivenessModifier( + Record.readEnum<OpenMPNumThreadsClauseModifier>()); + C->setPrescriptivenessModifierLoc(Record.readSourceLocation()); + C->setDimsModifier(Record.readEnum<OpenMPNumThreadsClauseModifier>()); + C->setDimsModifierLoc(Record.readSourceLocation()); + C->setDimsModifierExpr(Record.readSubExpr()); VisitOMPClauseWithPreInit(C); - C->setModifier(Record.readEnum<OpenMPNumThreadsClauseModifier>()); - C->setNumThreads(Record.readSubExpr()); - C->setModifierLoc(Record.readSourceLocation()); C->setLParenLoc(Record.readSourceLocation()); + unsigned NumVars = C->varlist_size(); + SmallVector<Expr *, 16> Vars; + Vars.reserve(NumVars); + for (unsigned I = 0; I != NumVars; ++I) + Vars.push_back(Record.readSubExpr()); + C->setVarRefs(Vars); } void OMPClauseReader::VisitOMPSafelenClause(OMPSafelenClause *C) { diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index a305e92b6a602..9fcf4d269e9ea 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -8057,11 +8057,16 @@ void OMPClauseWriter::VisitOMPFinalClause(OMPFinalClause *C) { } void OMPClauseWriter::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) { + Record.push_back(C->varlist_size()); + Record.writeEnum(C->getPrescriptivenessModifier()); + Record.AddSourceLocation(C->getPrescriptivenessModifierLoc()); + Record.writeEnum(C->getDimsModifier()); + Record.AddSourceLocation(C->getDimsModifierLoc()); + Record.AddStmt(C->getDimsModifierExpr()); VisitOMPClauseWithPreInit(C); - Record.writeEnum(C->getModifier()); - Record.AddStmt(C->getNumThreads()); - Record.AddSourceLocation(C->getModifierLoc()); Record.AddSourceLocation(C->getLParenLoc()); + for (auto *VE : C->varlist()) + Record.AddStmt(VE); } void OMPClauseWriter::VisitOMPSafelenClause(OMPSafelenClause *C) { diff --git a/clang/test/OpenMP/dims_modifier_ast_print.cpp b/clang/test/OpenMP/dims_modifier_ast_print.cpp index d47e8353abcad..57801f305218f 100644 --- a/clang/test/OpenMP/dims_modifier_ast_print.cpp +++ b/clang/test/OpenMP/dims_modifier_ast_print.cpp @@ -21,6 +21,46 @@ void test_ast_print() { // CHECK: #pragma omp target teams num_teams(dims(1):N) thread_limit(dims(1):M) #pragma omp target teams num_teams(dims(1): N) thread_limit(dims(1): M) {} + + // CHECK: #pragma omp parallel num_threads(dims(3): 1,2,3) + #pragma omp parallel num_threads(dims(3): 1, 2, 3) + {} + + // CHECK: #pragma omp parallel num_threads(strict: 10) + #pragma omp parallel num_threads(strict: 10) + {} + + // CHECK: #pragma omp parallel num_threads(strict,dims(2): N + 1,N) + #pragma omp parallel num_threads(strict, dims(2): N + 1, N) + {} + + // CHECK: #pragma omp parallel num_threads(strict,dims(2): 10,20) + #pragma omp parallel num_threads(dims(2), strict: 10, 20) + {} + + // CHECK: #pragma omp parallel num_threads(strict,dims(2): N,N + 1) + #pragma omp parallel num_threads(strict, dims(2): N, N + 1) + {} + + // CHECK: #pragma omp target parallel thread_limit(dims(2):10,20) num_threads(dims(2): N,N + 1) + #pragma omp target parallel thread_limit(dims(2): 10, 20) num_threads(dims(2): N, N + 1) + {} + + // CHECK: #pragma omp target teams num_teams(dims(3):1,2,3) thread_limit(dims(2):10,20) + // CHECK-NEXT: #pragma omp parallel num_threads(dims(2): N,N + 1) + #pragma omp target teams num_teams(dims(3): 1, 2, 3) thread_limit(dims(2): 10, 20) + #pragma omp parallel num_threads(dims(2): N, N + 1) + {} + + // CHECK: #pragma omp target parallel thread_limit(dims(1):M) num_threads(strict,dims(2): 10,20) + #pragma omp target parallel thread_limit(dims(1): M) num_threads(dims(2), strict: 10, 20) + {} + + // CHECK: #pragma omp target teams num_teams(dims(1):N) thread_limit(dims(1):M) + // CHECK-NEXT: #pragma omp parallel num_threads(strict,dims(2): 10,20) + #pragma omp target teams num_teams(dims(1): N) thread_limit(dims(1): M) + #pragma omp parallel num_threads(dims(2), strict: 10, 20) + {} } template <int D> @@ -33,6 +73,28 @@ void template_test() { // CHECK: #pragma omp target teams num_teams(dims(3):arr[0],arr[1],arr[2]) thread_limit(dims(2):3,arr[0]) #pragma omp target teams num_teams(dims(D): arr[0], arr[1], arr[2]) thread_limit(dims(2): D, arr[0]) {} + + // CHECK: #pragma omp parallel num_threads(dims(3): arr[0],arr[1],arr[2]) + #pragma omp parallel num_threads(dims(3): arr[0], arr[1], arr[2]) + {} + + // CHECK: #pragma omp parallel num_threads(strict,dims(2): 3,arr[0]) + #pragma omp parallel num_threads(strict, dims(2): D, arr[0]) + {} + + // CHECK: #pragma omp parallel num_threads(strict,dims(2): 3,arr[0]) + #pragma omp parallel num_threads(dims(2), strict: D, arr[0]) + {} + + // CHECK: #pragma omp target parallel thread_limit(dims(1):3) num_threads(strict,dims(2): 3,arr[0]) + #pragma omp target parallel thread_limit(dims(1): D) num_threads(dims(2), strict: D, arr[0]) + {} + + // CHECK: #pragma omp target teams num_teams(dims(3):arr[0],arr[1],arr[2]) thread_limit(dims(1):3) + // CHECK-NEXT: #pragma omp parallel num_threads(strict,dims(2): 3,arr[0]) + #pragma omp target teams num_teams(dims(3): arr[0], arr[1], arr[2]) thread_limit(dims(1): D) + #pragma omp parallel num_threads(dims(2), strict: D, arr[0]) + {} } void call_templates() { diff --git a/clang/test/OpenMP/dims_modifier_messages.cpp b/clang/test/OpenMP/dims_modifier_messages.cpp index ce0dd7eb79c52..e7e74e900cf1d 100644 --- a/clang/test/OpenMP/dims_modifier_messages.cpp +++ b/clang/test/OpenMP/dims_modifier_messages.cpp @@ -8,17 +8,25 @@ void foo() { } #ifndef VERSION52 -void bar(int N) { // expected-note {{declared here}} +void bar(int N) { // expected-note 2 {{declared here}} // 1. Invalid syntax of the dims modifier. #pragma omp target teams num_teams(dims 2: 4) // expected-error {{use of undeclared identifier 'dims'}} foo(); +#pragma omp parallel num_threads(dims 2: 4) // expected-error {{use of undeclared identifier 'dims'}} + foo(); + #pragma omp target thread_limit(dim(2) 4, 5) // expected-error@-1 {{use of undeclared identifier 'dim'}} // expected-error@-2 {{expected ',' or ')' in 'thread_limit' clause}} foo(); +#pragma omp parallel num_threads(dim(2) 4, 5) + // expected-error@-1 {{use of undeclared identifier 'dim'}} + // expected-error@-2 {{expected ',' or ')' in 'num_threads' clause}} + foo(); + #pragma omp target thread_limit(dims((2): 4, 5) // expected-error@-1 {{expected ')'}} // expected-error@-2 {{expected ')'}} @@ -27,17 +35,36 @@ void bar(int N) { // expected-note {{declared here}} // expected-error@-5 {{missing ':' after thread_limit modifier}} foo(); +#pragma omp parallel num_threads(dims((2): 4, 5) + // expected-error@-1 {{expected ')'}} + // expected-error@-2 {{expected ')'}} + // expected-note@-3 {{to match this '('}} + // expected-note@-4 {{to match this '('}} + // expected-error@-5 {{missing ':' after num_threads modifier}} + foo(); + #pragma omp target thread_limit(dims(2)): 4, 5) // expected-error@-1 {{missing ':' after thread_limit modifier}} // expected-warning@-2 {{extra tokens at the end of '#pragma omp target' are ignored}} foo(); +#pragma omp parallel num_threads(dims(2)): 4, 5) + // expected-error@-1 {{missing ':' after num_threads modifier}} + // expected-warning@-2 {{extra tokens at the end of '#pragma omp parallel' are ignored}} + foo(); + #pragma omp target thread_limit(dims(2) 4, 5) // expected-error {{missing ':' after thread_limit modifier}} foo(); +#pragma omp parallel num_threads(dims(2) 4, 5) // expected-error {{missing ':' after num_threads modifier}} + foo(); + #pragma omp target teams distribute num_teams(dims(): 4) // expected-error {{expected expression}} for (int i = 0; i < 10; ++i) {} +#pragma omp parallel num_threads(dims(): 4) // expected-error {{expected expression}} + foo(); + // 3. Incompatible modifiers. #pragma omp target teams num_teams(dims(1),10:20) // expected-error {{'lower_bound' modifier cannot be specified with 'dims' modifier in 'num_teams' clause}} @@ -51,6 +78,9 @@ void bar(int N) { // expected-note {{declared here}} #pragma omp target thread_limit(dims(1): 4, 5) // expected-error {{unexpected number of expressions in 'thread_limit' clause}} foo(); +#pragma omp parallel num_threads(dims(2): 4) // expected-error {{unexpected number of expressions in 'num_threads' clause}} + foo(); + #pragma omp target teams distribute num_teams(dims(3): 4, 5) // expected-error {{unexpected number of expressions in 'num_teams' clause}} for (int i = 0; i < 10; ++i) {} @@ -62,6 +92,9 @@ void bar(int N) { // expected-note {{declared here}} #pragma omp target thread_limit(dims(2): 1, 2, 3, 4) // expected-error {{unexpected number of expressions in 'thread_limit' clause}} foo(); +#pragma omp parallel num_threads(dims(4): 1, 2, 3, 4) // expected-error {{maximum three expressions are supported in 'num_threads' clause}} + foo(); + #pragma omp target teams distribute thread_limit(dims(4): 1, 2, 3, 4) // expected-error {{maximum three expressions are supported in 'thread_limit' clause}} for (int i = 0; i < 10; ++i) {} @@ -80,14 +113,25 @@ void bar(int N) { // expected-note {{declared here}} // expected-note@-2 {{function parameter 'N' with unknown value cannot be used in a constant expression}} foo(); +#pragma omp parallel num_threads(dims(N): 1, 2) + // expected-error@-1 {{expression is not an integral constant expression}} + // expected-note@-2 {{function parameter 'N' with unknown value cannot be used in a constant expression}} + foo(); + #pragma omp target thread_limit(dims(2.5): 1, 2) // expected-error {{integral constant expression must have integral or unscoped enumeration type, not 'double'}} foo(); +#pragma omp parallel num_threads(dims(2.5): 1, 2) // expected-error {{integral constant expression must have integral or unscoped enumeration type, not 'double'}} + foo(); + #pragma omp target teams distribute num_teams(dims(0): 4) // expected-error {{argument to 'num_teams' clause must be a strictly positive integer value}} for (int i = 0; i < 10; ++i) {} #pragma omp target teams thread_limit(dims(-1): 4) // expected-error {{argument to 'thread_limit' clause must be a strictly positive integer value}} foo(); + +#pragma omp parallel num_threads(dims(0): 4) // expected-error {{argument to 'num_threads' clause must be a strictly positive integer value}} + foo(); } template <int D> @@ -104,6 +148,11 @@ void template_test() { // expected-error@-2 {{argument to 'thread_limit' clause must be a strictly positive integer value}} foo(); +#pragma omp parallel num_threads(dims(D): 4) + // expected-error@-1 {{unexpected number of expressions in 'num_threads' clause}} + // expected-error@-2 {{argument to 'num_threads' clause must be a strictly positive integer value}} + foo(); + #pragma omp target teams distribute num_teams(dims(D): 4, 5) // expected-error@-1 {{unexpected number of expressions in 'num_teams' clause}} // expected-error@-2 {{argument to 'num_teams' clause must be a strictly positive integer value}} @@ -125,5 +174,8 @@ void version() { #pragma omp target thread_limit(dims(1): 4) // expected-error {{'dims' modifier in 'thread_limit' clause requires OpenMP 6.1 or later}} foo(); + +#pragma omp target parallel num_threads(dims(1): 4) // expected-error {{'dims' modifier in 'num_threads' clause requires OpenMP 6.1 or later}} + foo(); } #endif diff --git a/clang/test/OpenMP/distribute_parallel_for_num_threads_messages.cpp b/clang/test/OpenMP/distribute_parallel_for_num_threads_messages.cpp index ab301cc517207..296d0865d14e3 100644 --- a/clang/test/OpenMP/distribute_parallel_for_num_threads_messages.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_num_threads_messages.cpp @@ -48,7 +48,7 @@ T tmain(T argc, S **argv) { for (i = 0; i < argc; ++i) foo(); #pragma omp target #pragma omp teams -#pragma omp distribute parallel for num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2 {{expression must have integral or unscoped enumeration type, not 'char *'}} +#pragma omp distribute parallel for num_threads (argv[1]=2) // expected-error 2 {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} for (i = 0; i < argc; ++i) foo(); #pragma omp target #pragma omp teams @@ -98,7 +98,7 @@ int main(int argc, char **argv) { for (i = 0; i < argc; ++i) foo(); #pragma omp target #pragma omp teams -#pragma omp distribute parallel for num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} +#pragma omp distribute parallel for num_threads (argv[1]=2) // expected-error {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} for (i = 0; i < argc; ++i) foo(); #pragma omp target #pragma omp teams diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_num_threads_messages.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_num_threads_messages.cpp index 9f9de197aca0d..d405246cd5a56 100644 --- a/clang/test/OpenMP/distribute_parallel_for_simd_num_threads_messages.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_simd_num_threads_messages.cpp @@ -48,7 +48,7 @@ T tmain(T argc, S **argv) { for (i = 0; i < argc; ++i) foo(); #pragma omp target #pragma omp teams -#pragma omp distribute parallel for simd num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2 {{expression must have integral or unscoped enumeration type, not 'char *'}} +#pragma omp distribute parallel for simd num_threads (argv[1]=2) // expected-error 2 {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} for (i = 0; i < argc; ++i) foo(); #pragma omp target #pragma omp teams @@ -98,7 +98,7 @@ int main(int argc, char **argv) { for (i = 0; i < argc; ++i) foo(); #pragma omp target #pragma omp teams -#pragma omp distribute parallel for simd num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} +#pragma omp distribute parallel for simd num_threads (argv[1]=2) // expected-error {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} for (i = 0; i < argc; ++i) foo(); #pragma omp target #pragma omp teams diff --git a/clang/test/OpenMP/parallel_for_num_threads_messages.cpp b/clang/test/OpenMP/parallel_for_num_threads_messages.cpp index e689df8fc7d85..4979e7df7e1a0 100644 --- a/clang/test/OpenMP/parallel_for_num_threads_messages.cpp +++ b/clang/test/OpenMP/parallel_for_num_threads_messages.cpp @@ -30,7 +30,7 @@ T tmain(T argc, S **argv) { for (i = 0; i < argc; ++i) foo(); #pragma omp parallel for num_threads (S) // expected-error {{'S' does not refer to a value}} for (i = 0; i < argc; ++i) foo(); - #pragma omp parallel for num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2 {{expression must have integral or unscoped enumeration type, not 'char *'}} + #pragma omp parallel for num_threads (argv[1]=2) // expected-error 2 {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} for (i = 0; i < argc; ++i) foo(); #pragma omp parallel for num_threads (argc+z) for (i = 0; i < argc; ++i) foo(); @@ -58,7 +58,7 @@ int main(int argc, char **argv) { for (i = 0; i < argc; ++i) foo(); #pragma omp parallel for num_threads (S1) // expected-error {{'S1' does not refer to a value}} for (i = 0; i < argc; ++i) foo(); - #pragma omp parallel for num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} + #pragma omp parallel for num_threads (argv[1]=2) // expected-error {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} for (i = 0; i < argc; ++i) foo(); #pragma omp parallel for num_threads (num_threads(tmain<int, char, -1>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}} expected-note {{in instantiation of function template specialization 'tmain<int, char, -1>' requested here}} for (i = 0; i < argc; ++i) foo(); diff --git a/clang/test/OpenMP/parallel_for_simd_num_threads_messages.cpp b/clang/test/OpenMP/parallel_for_simd_num_threads_messages.cpp index f79ec4f68f4bb..f7457697bc227 100644 --- a/clang/test/OpenMP/parallel_for_simd_num_threads_messages.cpp +++ b/clang/test/OpenMP/parallel_for_simd_num_threads_messages.cpp @@ -30,7 +30,7 @@ T tmain(T argc, S **argv) { for (i = 0; i < argc; ++i) foo(); #pragma omp parallel for simd num_threads (S) // expected-error {{'S' does not refer to a value}} for (i = 0; i < argc; ++i) foo(); - #pragma omp parallel for simd num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2 {{expression must have integral or unscoped enumeration type, not 'char *'}} + #pragma omp parallel for simd num_threads (argv[1]=2) // expected-error 2 {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} for (i = 0; i < argc; ++i) foo(); #pragma omp parallel for simd num_threads (argc + z) for (i = 0; i < argc; ++i) foo(); @@ -58,7 +58,7 @@ int main(int argc, char **argv) { for (i = 0; i < argc; ++i) foo(); #pragma omp parallel for simd num_threads (S1) // expected-error {{'S1' does not refer to a value}} for (i = 0; i < argc; ++i) foo(); - #pragma omp parallel for simd num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} + #pragma omp parallel for simd num_threads (argv[1]=2) // expected-error {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} for (i = 0; i < argc; ++i) foo(); #pragma omp parallel for simd num_threads (num_threads(tmain<int, char, -1>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}} expected-note {{in instantiation of function template specialization 'tmain<int, char, -1>' requested here}} for (i = 0; i < argc; ++i) foo(); diff --git a/clang/test/OpenMP/parallel_masked_num_threads_messages.cpp b/clang/test/OpenMP/parallel_masked_num_threads_messages.cpp index 928c07c5610e1..46dc4035cc9d6 100644 --- a/clang/test/OpenMP/parallel_masked_num_threads_messages.cpp +++ b/clang/test/OpenMP/parallel_masked_num_threads_messages.cpp @@ -30,7 +30,7 @@ T tmain(T argc, S **argv) { {foo();} #pragma omp parallel masked num_threads (S) // expected-error {{'S' does not refer to a value}} {foo();} - #pragma omp parallel masked num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2 {{expression must have integral or unscoped enumeration type, not 'char *'}} + #pragma omp parallel masked num_threads (argv[1]=2) // expected-error 2 {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} {foo();} #pragma omp parallel masked num_threads (argc + z) {foo();} @@ -58,7 +58,7 @@ int main(int argc, char **argv) { {foo();} #pragma omp parallel masked num_threads (S1) // expected-error {{'S1' does not refer to a value}} {foo();} - #pragma omp parallel masked num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} + #pragma omp parallel masked num_threads (argv[1]=2) // expected-error {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} {foo();} #pragma omp parallel masked num_threads (num_threads(tmain<int, char, -1>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}} expected-note {{in instantiation of function template specialization 'tmain<int, char, -1>' requested here}} {foo();} diff --git a/clang/test/OpenMP/parallel_master_num_threads_messages.cpp b/clang/test/OpenMP/parallel_master_num_threads_messages.cpp index 601164f1e5328..d951abccb12c0 100644 --- a/clang/test/OpenMP/parallel_master_num_threads_messages.cpp +++ b/clang/test/OpenMP/parallel_master_num_threads_messages.cpp @@ -30,7 +30,7 @@ T tmain(T argc, S **argv) { {foo();} #pragma omp parallel master num_threads (S) // expected-error {{'S' does not refer to a value}} {foo();} - #pragma omp parallel master num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2 {{expression must have integral or unscoped enumeration type, not 'char *'}} + #pragma omp parallel master num_threads (argv[1]=2) // expected-error 2 {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} {foo();} #pragma omp parallel master num_threads (argc + z) {foo();} @@ -58,7 +58,7 @@ int main(int argc, char **argv) { {foo();} #pragma omp parallel master num_threads (S1) // expected-error {{'S1' does not refer to a value}} {foo();} - #pragma omp parallel master num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} + #pragma omp parallel master num_threads (argv[1]=2) // expected-error {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} {foo();} #pragma omp parallel master num_threads (num_threads(tmain<int, char, -1>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}} expected-note {{in instantiation of function template specialization 'tmain<int, char, -1>' requested here}} {foo();} diff --git a/clang/test/OpenMP/parallel_num_threads_messages.cpp b/clang/test/OpenMP/parallel_num_threads_messages.cpp index 02c1cb6e69d99..fbffa06c29d6d 100644 --- a/clang/test/OpenMP/parallel_num_threads_messages.cpp +++ b/clang/test/OpenMP/parallel_num_threads_messages.cpp @@ -26,7 +26,7 @@ T tmain(T argc, S **argv) { #pragma omp parallel num_threads ((argc > 0) ? argv[1] : argv[2]) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'char *'}} #pragma omp parallel num_threads (foobool(argc)), num_threads (true), num_threads (-5) // expected-error 2 {{directive '#pragma omp parallel' cannot contain more than one 'num_threads' clause}} expected-error {{argument to 'num_threads' clause must be a strictly positive integer value}} #pragma omp parallel num_threads (S) // expected-error {{'S' does not refer to a value}} - #pragma omp parallel num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2 {{expression must have integral or unscoped enumeration type, not 'char *'}} + #pragma omp parallel num_threads (argv[1]=2) // expected-error 2 {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} #pragma omp parallel num_threads (argc+z) #pragma omp parallel num_threads (N) // expected-error {{argument to 'num_threads' clause must be a strictly positive integer value}} #pragma omp parallel redef_num_threads (argc, argc) @@ -42,23 +42,23 @@ T tmain(T argc, S **argv) { #pragma omp parallel num_threads(strict: // omp60-error {{expected expression}} omp60-error {{expected ')'}} omp60-note {{to match this '('}} // Invalid: unknown/missing modifier - #pragma omp parallel num_threads(foo: 4) // omp60-error {{expected 'strict' in OpenMP clause 'num_threads'}} - #pragma omp parallel num_threads(: 4) // omp60-error {{expected expression}} omp60-error {{expected ')'}} omp60-note {{to match this '('}} - #pragma omp parallel num_threads(:)// omp60-error {{expected expression}} omp60-error {{expected ')'}} omp60-note {{to match this '('}} + #pragma omp parallel num_threads(foo: 4) // omp60-error {{expected ',' or ')' in 'num_threads' clause}} omp60-error {{expected ')'}} omp60-note {{to match this '('}} omp60-error 3 {{expression must have integral or unscoped enumeration type, not 'void ()'}} + #pragma omp parallel num_threads(: 4) // omp60-error {{expected expression}} + #pragma omp parallel num_threads(:)// omp60-error {{expected expression}} // Invalid: missing colon after modifier - #pragma omp parallel num_threads(strict 4) // omp60-error {{missing ':' after strict modifier}} + #pragma omp parallel num_threads(strict 4) // omp60-error {{missing ':' after num_threads modifier}} // Invalid: negative, zero, or non-integral #pragma omp parallel num_threads(strict: -1) // omp60-error {{argument to 'num_threads' clause must be a strictly positive integer value}} #pragma omp parallel num_threads(strict: 0) // omp60-error {{argument to 'num_threads' clause must be a strictly positive integer value}} #pragma omp parallel num_threads(strict: (argc > 0) ? argv[1] : argv[2]) // omp60-error 2 {{expression must have integral or unscoped enumeration type, not 'char *'}} #pragma omp parallel num_threads(strict: S) // omp60-error {{'S' does not refer to a value}} - #pragma omp parallel num_threads(strict: argv[1]=2) // omp60-error {{expected ')'}} omp60-note {{to match this '('}} omp60-error 2 {{expression must have integral or unscoped enumeration type, not 'char *'}} + #pragma omp parallel num_threads(strict: argv[1]=2) // omp60-error 2 {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} #pragma omp parallel num_threads(strict: N) // omp60-error {{argument to 'num_threads' clause must be a strictly positive integer value}} // Invalid: multiple strict modifiers or mixed with non-strict - #pragma omp parallel num_threads(strict: 4, strict: 5) // omp60-error {{expected ')'}} expected-note {{to match this '('}} + #pragma omp parallel num_threads(strict: 4, strict: 5) // omp60-error {{use of undeclared identifier 'strict'}} #pragma omp parallel num_threads(strict: 4), num_threads(5) // omp60-error {{directive '#pragma omp parallel' cannot contain more than one 'num_threads' clause}} #pragma omp parallel num_threads(4), num_threads(strict: 5) // omp60-error {{directive '#pragma omp parallel' cannot contain more than one 'num_threads' clause}} #endif // OMP60 @@ -78,7 +78,7 @@ int z; #pragma omp parallel num_threads (argc > 0 ? argv[1] : argv[2]) // expected-error {{integral }} #pragma omp parallel num_threads (foobool(argc)), num_threads (true), num_threads (-5) // expected-error 2 {{directive '#pragma omp parallel' cannot contain more than one 'num_threads' clause}} expected-error {{argument to 'num_threads' clause must be a strictly positive integer value}} #pragma omp parallel num_threads (S1) // expected-error {{'S1' does not refer to a value}} - #pragma omp parallel num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} + #pragma omp parallel num_threads (argv[1]=2) // expected-error {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} #pragma omp parallel num_threads (num_threads(tmain<int, char, -1>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}} expected-note {{in instantiation of function template specialization 'tmain<int, char, -1>' requested here}} #pragma omp parallel redef_num_threads (argc, argc) @@ -93,22 +93,22 @@ int z; #pragma omp parallel num_threads(strict: // omp60-error {{expected expression}} omp60-error {{expected ')'}} omp60-note {{to match this '('}} // Invalid: unknown/missing modifier - #pragma omp parallel num_threads(foo: 4) // omp60-error {{expected 'strict' in OpenMP clause 'num_threads'}} - #pragma omp parallel num_threads(: 4) // omp60-error {{expected expression}} omp60-error {{expected ')'}} omp60-note {{to match this '('}} - #pragma omp parallel num_threads(:) // omp60-error {{expected expression}} omp60-error {{expected ')'}} omp60-note {{to match this '('}} + #pragma omp parallel num_threads(foo: 4) // omp60-error {{expected ',' or ')' in 'num_threads' clause}} omp60-error {{expected ')'}} omp60-note {{to match this '('}} omp60-error {{expression must have integral or unscoped enumeration type, not 'void ()'}} + #pragma omp parallel num_threads(: 4) // omp60-error {{expected expression}} + #pragma omp parallel num_threads(:) // omp60-error {{expected expression}} // Invalid: missing colon after modifier - #pragma omp parallel num_threads(strict 4) // omp60-error {{missing ':' after strict modifier}} + #pragma omp parallel num_threads(strict 4) // omp60-error {{missing ':' after num_threads modifier}} // Invalid: negative, zero, or non-integral #pragma omp parallel num_threads(strict: -1) // omp60-error {{argument to 'num_threads' clause must be a strictly positive integer value}} #pragma omp parallel num_threads(strict: 0) // omp60-error {{argument to 'num_threads' clause must be a strictly positive integer value}} #pragma omp parallel num_threads(strict: (argc > 0) ? argv[1] : argv[2]) // omp60-error {{expression must have integral or unscoped enumeration type, not 'char *'}} #pragma omp parallel num_threads(strict: S1) // omp60-error {{'S1' does not refer to a value}} - #pragma omp parallel num_threads(strict: argv[1]=2) // omp60-error {{expected ')'}} omp60-note {{to match this '('}} omp60-error {{expression must have integral or unscoped enumeration type, not 'char *'}} + #pragma omp parallel num_threads(strict: argv[1]=2) // omp60-error {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} // Invalid: multiple strict modifiers or mixed with non-strict - #pragma omp parallel num_threads(strict: 4, strict: 5) // omp60-error {{expected ')'}} expected-note {{to match this '('}} + #pragma omp parallel num_threads(strict: 4, strict: 5) // omp60-error {{use of undeclared identifier 'strict'}} #pragma omp parallel num_threads(strict: 4), num_threads(5) // omp60-error {{directive '#pragma omp parallel' cannot contain more than one 'num_threads' clause}} #pragma omp parallel num_threads(4), num_threads(strict: 5) // omp60-error {{directive '#pragma omp parallel' cannot contain more than one 'num_threads' clause}} #endif // OMP60 diff --git a/clang/test/OpenMP/parallel_sections_num_threads_messages.cpp b/clang/test/OpenMP/parallel_sections_num_threads_messages.cpp index 31434e4757ab2..f396eb41e983e 100644 --- a/clang/test/OpenMP/parallel_sections_num_threads_messages.cpp +++ b/clang/test/OpenMP/parallel_sections_num_threads_messages.cpp @@ -30,7 +30,7 @@ T tmain(T argc, S **argv) { {foo();} #pragma omp parallel sections num_threads (S) // expected-error {{'S' does not refer to a value}} {foo();} - #pragma omp parallel sections num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2 {{expression must have integral or unscoped enumeration type, not 'char *'}} + #pragma omp parallel sections num_threads (argv[1]=2) // expected-error 2 {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} {foo();} #pragma omp parallel sections num_threads (argc + z) {foo();} @@ -58,7 +58,7 @@ int main(int argc, char **argv) { {foo();} #pragma omp parallel sections num_threads (S1) // expected-error {{'S1' does not refer to a value}} {foo();} - #pragma omp parallel sections num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} + #pragma omp parallel sections num_threads (argv[1]=2) // expected-error {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} {foo();} #pragma omp parallel sections num_threads (num_threads(tmain<int, char, -1>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}} expected-note {{in instantiation of function template specialization 'tmain<int, char, -1>' requested here}} {foo();} diff --git a/clang/test/OpenMP/target_parallel_for_num_threads_messages.cpp b/clang/test/OpenMP/target_parallel_for_num_threads_messages.cpp index 11f0c90780471..fddf0f8b05ef2 100644 --- a/clang/test/OpenMP/target_parallel_for_num_threads_messages.cpp +++ b/clang/test/OpenMP/target_parallel_for_num_threads_messages.cpp @@ -30,7 +30,7 @@ T tmain(T argc, S **argv) { for (i = 0; i < argc; ++i) foo(); #pragma omp target parallel for num_threads (S) // expected-error {{'S' does not refer to a value}} for (i = 0; i < argc; ++i) foo(); - #pragma omp target parallel for num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2 {{expression must have integral or unscoped enumeration type, not 'char *'}} + #pragma omp target parallel for num_threads (argv[1]=2) // expected-error 2 {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} for (i = 0; i < argc; ++i) foo(); #pragma omp target parallel for num_threads (argc) for (i = 0; i < argc; ++i) foo(); @@ -58,7 +58,7 @@ int main(int argc, char **argv) { for (i = 0; i < argc; ++i) foo(); #pragma omp target parallel for num_threads (S1) // expected-error {{'S1' does not refer to a value}} for (i = 0; i < argc; ++i) foo(); - #pragma omp target parallel for num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} + #pragma omp target parallel for num_threads (argv[1]=2) // expected-error {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} for (i = 0; i < argc; ++i) foo(); #pragma omp target parallel for num_threads (num_threads(tmain<int, char, -1>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}} expected-note {{in instantiation of function template specialization 'tmain<int, char, -1>' requested here}} for (i = 0; i < argc; ++i) foo(); diff --git a/clang/test/OpenMP/target_parallel_for_simd_num_threads_messages.cpp b/clang/test/OpenMP/target_parallel_for_simd_num_threads_messages.cpp index f7979057ae2b4..39b75ce91de8f 100644 --- a/clang/test/OpenMP/target_parallel_for_simd_num_threads_messages.cpp +++ b/clang/test/OpenMP/target_parallel_for_simd_num_threads_messages.cpp @@ -30,7 +30,7 @@ T tmain(T argc, S **argv) { for (i = 0; i < argc; ++i) foo(); #pragma omp target parallel for simd num_threads (S) // expected-error {{'S' does not refer to a value}} for (i = 0; i < argc; ++i) foo(); - #pragma omp target parallel for simd num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2 {{expression must have integral or unscoped enumeration type, not 'char *'}} + #pragma omp target parallel for simd num_threads (argv[1]=2) // expected-error 2 {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} for (i = 0; i < argc; ++i) foo(); #pragma omp target parallel for simd num_threads (argc) for (i = 0; i < argc; ++i) foo(); @@ -58,7 +58,7 @@ int main(int argc, char **argv) { for (i = 0; i < argc; ++i) foo(); #pragma omp target parallel for simd num_threads (S1) // expected-error {{'S1' does not refer to a value}} for (i = 0; i < argc; ++i) foo(); - #pragma omp target parallel for simd num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} + #pragma omp target parallel for simd num_threads (argv[1]=2) // expected-error {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} for (i = 0; i < argc; ++i) foo(); #pragma omp target parallel for simd num_threads (num_threads(tmain<int, char, -1>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}} expected-note {{in instantiation of function template specialization 'tmain<int, char, -1>' requested here}} for (i = 0; i < argc; ++i) foo(); diff --git a/clang/test/OpenMP/target_parallel_num_threads_messages.cpp b/clang/test/OpenMP/target_parallel_num_threads_messages.cpp index 64e9929d68101..19d40a3448cef 100644 --- a/clang/test/OpenMP/target_parallel_num_threads_messages.cpp +++ b/clang/test/OpenMP/target_parallel_num_threads_messages.cpp @@ -34,7 +34,7 @@ T tmain(T argc, S **argv) { foo(); #pragma omp target parallel num_threads (S) // expected-error {{'S' does not refer to a value}} foo(); - #pragma omp target parallel num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2 {{expression must have integral or unscoped enumeration type, not 'char *'}} + #pragma omp target parallel num_threads (argv[1]=2) // expected-error 2 {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} foo(); #pragma omp target parallel num_threads (argc + z) foo(); @@ -59,15 +59,15 @@ T tmain(T argc, S **argv) { foo(); // Invalid: unknown/missing modifier - #pragma omp target parallel num_threads(foo: 4) // omp60-error {{expected 'strict' in OpenMP clause 'num_threads'}} + #pragma omp target parallel num_threads(foo: 4) // omp60-error {{expected ',' or ')' in 'num_threads' clause}} omp60-error {{expected ')'}} omp60-note {{to match this '('}} omp60-error 3 {{expression must have integral or unscoped enumeration type, not 'void ()'}} foo(); - #pragma omp target parallel num_threads(: 4) // omp60-error {{expected expression}} omp60-error {{expected ')'}} omp60-note {{to match this '('}} + #pragma omp target parallel num_threads(: 4) // omp60-error {{expected expression}} foo(); - #pragma omp target parallel num_threads(:)// omp60-error {{expected expression}} omp60-error {{expected ')'}} omp60-note {{to match this '('}} + #pragma omp target parallel num_threads(:)// omp60-error {{expected expression}} foo(); // Invalid: missing colon after modifier - #pragma omp target parallel num_threads(strict 4) // omp60-error {{missing ':' after strict modifier}} + #pragma omp target parallel num_threads(strict 4) // omp60-error {{missing ':' after num_threads modifier}} foo(); // Invalid: negative, zero, or non-integral @@ -79,13 +79,13 @@ T tmain(T argc, S **argv) { foo(); #pragma omp target parallel num_threads(strict: S) // omp60-error {{'S' does not refer to a value}} foo(); - #pragma omp target parallel num_threads(strict: argv[1]=2) // omp60-error {{expected ')'}} omp60-note {{to match this '('}} omp60-error 2 {{expression must have integral or unscoped enumeration type, not 'char *'}} + #pragma omp target parallel num_threads(strict: argv[1]=2) // omp60-error 2 {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} foo(); #pragma omp target parallel num_threads(strict: N) // omp60-error {{argument to 'num_threads' clause must be a strictly positive integer value}} foo(); // Invalid: multiple strict modifiers or mixed with non-strict - #pragma omp target parallel num_threads(strict: 4, strict: 5) // omp60-error {{expected ')'}} expected-note {{to match this '('}} + #pragma omp target parallel num_threads(strict: 4, strict: 5) // omp60-error {{use of undeclared identifier 'strict'}} foo(); #pragma omp target parallel num_threads(strict: 4), num_threads(5) // omp60-error {{directive '#pragma omp target parallel' cannot contain more than one 'num_threads' clause}} foo(); @@ -114,7 +114,7 @@ int main(int argc, char **argv) { foo(); #pragma omp target parallel num_threads (S1) // expected-error {{'S1' does not refer to a value}} foo(); - #pragma omp target parallel num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} + #pragma omp target parallel num_threads (argv[1]=2) // expected-error {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} foo(); #pragma omp target parallel num_threads (num_threads(tmain<int, char, -1>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}} expected-note {{in instantiation of function template specialization 'tmain<int, char, -1>' requested here}} foo(); @@ -137,15 +137,15 @@ int main(int argc, char **argv) { foo(); // Invalid: unknown/missing modifier - #pragma omp target parallel num_threads(foo: 4) // omp60-error {{expected 'strict' in OpenMP clause 'num_threads'}} + #pragma omp target parallel num_threads(foo: 4) // omp60-error {{expected ',' or ')' in 'num_threads' clause}} omp60-error {{expected ')'}} omp60-note {{to match this '('}} omp60-error {{expression must have integral or unscoped enumeration type, not 'void ()'}} foo(); - #pragma omp target parallel num_threads(: 4) // omp60-error {{expected expression}} omp60-error {{expected ')'}} omp60-note {{to match this '('}} + #pragma omp target parallel num_threads(: 4) // omp60-error {{expected expression}} foo(); - #pragma omp target parallel num_threads(:) // omp60-error {{expected expression}} omp60-error {{expected ')'}} omp60-note {{to match this '('}} + #pragma omp target parallel num_threads(:) // omp60-error {{expected expression}} foo(); // Invalid: missing colon after modifier - #pragma omp target parallel num_threads(strict 4) // omp60-error {{missing ':' after strict modifier}} + #pragma omp target parallel num_threads(strict 4) // omp60-error {{missing ':' after num_threads modifier}} foo(); // Invalid: negative, zero, or non-integral @@ -157,11 +157,11 @@ int main(int argc, char **argv) { foo(); #pragma omp target parallel num_threads(strict: S1) // omp60-error {{'S1' does not refer to a value}} foo(); - #pragma omp target parallel num_threads(strict: argv[1]=2) // omp60-error {{expected ')'}} omp60-note {{to match this '('}} omp60-error {{expression must have integral or unscoped enumeration type, not 'char *'}} + #pragma omp target parallel num_threads(strict: argv[1]=2) // omp60-error {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} foo(); // Invalid: multiple strict modifiers or mixed with non-strict - #pragma omp target parallel num_threads(strict: 4, strict: 5) // omp60-error {{expected ')'}} expected-note {{to match this '('}} + #pragma omp target parallel num_threads(strict: 4, strict: 5) // omp60-error {{use of undeclared identifier 'strict'}} foo(); #pragma omp target parallel num_threads(strict: 4), num_threads(5) // omp60-error {{directive '#pragma omp target parallel' cannot contain more than one 'num_threads' clause}} foo(); diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_num_threads_messages.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_num_threads_messages.cpp index d4b0c02c4393e..61690f0f052d6 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_num_threads_messages.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_num_threads_messages.cpp @@ -30,7 +30,7 @@ T tmain(T argc, S **argv) { for (i = 0; i < argc; ++i) foo(); #pragma omp target teams distribute parallel for num_threads (S) // expected-error {{'S' does not refer to a value}} for (i = 0; i < argc; ++i) foo(); -#pragma omp target teams distribute parallel for num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2 {{expression must have integral or unscoped enumeration type, not 'char *'}} +#pragma omp target teams distribute parallel for num_threads (argv[1]=2) // expected-error 2 {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} for (i = 0; i < argc; ++i) foo(); #pragma omp target teams distribute parallel for num_threads (argc) for (i = 0; i < argc; ++i) foo(); @@ -58,7 +58,7 @@ int main(int argc, char **argv) { for (i = 0; i < argc; ++i) foo(); #pragma omp target teams distribute parallel for num_threads (S1) // expected-error {{'S1' does not refer to a value}} for (i = 0; i < argc; ++i) foo(); -#pragma omp target teams distribute parallel for num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} +#pragma omp target teams distribute parallel for num_threads (argv[1]=2) // expected-error {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} for (i = 0; i < argc; ++i) foo(); #pragma omp target teams distribute parallel for num_threads (num_threads(tmain<int, char, -1>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}} expected-note {{in instantiation of function template specialization 'tmain<int, char, -1>' requested here}} for (i = 0; i < argc; ++i) foo(); diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_num_threads_messages.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_num_threads_messages.cpp index 397c83d199e9e..017cdff2f28d9 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_num_threads_messages.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_num_threads_messages.cpp @@ -30,7 +30,7 @@ T tmain(T argc, S **argv) { for (i = 0; i < argc; ++i) foo(); #pragma omp target teams distribute parallel for simd num_threads (S) // expected-error {{'S' does not refer to a value}} for (i = 0; i < argc; ++i) foo(); -#pragma omp target teams distribute parallel for simd num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2 {{expression must have integral or unscoped enumeration type, not 'char *'}} +#pragma omp target teams distribute parallel for simd num_threads (argv[1]=2) // expected-error 2 {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} for (i = 0; i < argc; ++i) foo(); #pragma omp target teams distribute parallel for simd num_threads (argc + k) for (i = 0; i < argc; ++i) foo(); @@ -58,7 +58,7 @@ int main(int argc, char **argv) { for (i = 0; i < argc; ++i) foo(); #pragma omp target teams distribute parallel for simd num_threads (S1) // expected-error {{'S1' does not refer to a value}} for (i = 0; i < argc; ++i) foo(); -#pragma omp target teams distribute parallel for simd num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} +#pragma omp target teams distribute parallel for simd num_threads (argv[1]=2) // expected-error {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} for (i = 0; i < argc; ++i) foo(); #pragma omp target teams distribute parallel for simd num_threads (num_threads(tmain<int, char, -1>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}} expected-note {{in instantiation of function template specialization 'tmain<int, char, -1>' requested here}} for (i = 0; i < argc; ++i) foo(); diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_messages.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_messages.cpp index 6ff5db319a985..4f24e7bd09356 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_messages.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_messages.cpp @@ -39,7 +39,7 @@ T tmain(T argc, S **argv) { #pragma omp teams distribute parallel for simd num_threads (S) // expected-error {{'S' does not refer to a value}} for (i = 0; i < argc; ++i) foo(); #pragma omp target -#pragma omp teams distribute parallel for simd num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2 {{expression must have integral or unscoped enumeration type, not 'char *'}} +#pragma omp teams distribute parallel for simd num_threads (argv[1]=2) // expected-error 2 {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} for (i = 0; i < argc; ++i) foo(); #pragma omp target #pragma omp teams distribute parallel for simd num_threads (argc) @@ -78,7 +78,7 @@ int main(int argc, char **argv) { #pragma omp teams distribute parallel for simd num_threads (S1) // expected-error {{'S1' does not refer to a value}} for (i = 0; i < argc; ++i) foo(); #pragma omp target -#pragma omp teams distribute parallel for simd num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} +#pragma omp teams distribute parallel for simd num_threads (argv[1]=2) // expected-error {{incompatible integer to pointer conversion assigning to 'char *' from 'int'}} for (i = 0; i < argc; ++i) foo(); #pragma omp target #pragma omp teams distribute parallel for simd num_threads (num_threads(tmain<int, char, -1>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}} expected-note {{in instantiation of function template specialization 'tmain<int, char, -1>' requested here}} diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index af9dc02656597..7a8f49e620ea9 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -2339,8 +2339,10 @@ void OMPClauseEnqueue::VisitOMPFinalClause(const OMPFinalClause *C) { } void OMPClauseEnqueue::VisitOMPNumThreadsClause(const OMPNumThreadsClause *C) { + if (const Expr *Modifier = C->getDimsModifierExpr()) + Visitor->AddStmt(Modifier); + VisitOMPClauseList(C); VisitOMPClauseWithPreInit(C); - Visitor->AddStmt(C->getNumThreads()); } void OMPClauseEnqueue::VisitOMPSafelenClause(const OMPSafelenClause *C) { _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
