Author: Alexey Bataev Date: 2020-03-23T13:12:52-04:00 New Revision: 63828a35da6f790f448b87b3eec61d294df31ccc
URL: https://github.com/llvm/llvm-project/commit/63828a35da6f790f448b87b3eec61d294df31ccc DIFF: https://github.com/llvm/llvm-project/commit/63828a35da6f790f448b87b3eec61d294df31ccc.diff LOG: [OPENMP50]Bassic support for exclusive clause. Added basic support (parsing/sema/serialization) for exclusive clause in scan directives. Added: Modified: clang/include/clang/AST/OpenMPClause.h clang/include/clang/AST/RecursiveASTVisitor.h clang/include/clang/Basic/OpenMPKinds.def clang/include/clang/Sema/Sema.h clang/lib/AST/OpenMPClause.cpp clang/lib/AST/StmtProfile.cpp clang/lib/Basic/OpenMPKinds.cpp clang/lib/CodeGen/CGStmtOpenMP.cpp clang/lib/Parse/ParseOpenMP.cpp clang/lib/Sema/SemaOpenMP.cpp clang/lib/Sema/TreeTransform.h clang/lib/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp clang/test/OpenMP/scan_ast_print.cpp clang/test/OpenMP/scan_messages.cpp clang/tools/libclang/CIndex.cpp Removed: ################################################################################ diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h index a781797c2d56..acf450f07e66 100644 --- a/clang/include/clang/AST/OpenMPClause.h +++ b/clang/include/clang/AST/OpenMPClause.h @@ -6985,6 +6985,80 @@ class OMPInclusiveClause final } }; +/// This represents clause 'exclusive' in the '#pragma omp scan' directive. +/// +/// \code +/// #pragma omp scan exclusive(a,b) +/// \endcode +/// In this example directive '#pragma omp scan' has clause 'exclusive' +/// with the variables 'a' and 'b'. +class OMPExclusiveClause final + : public OMPVarListClause<OMPExclusiveClause>, + private llvm::TrailingObjects<OMPExclusiveClause, Expr *> { + friend class OMPClauseReader; + friend OMPVarListClause; + friend TrailingObjects; + + /// Build clause with number of variables \a N. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param N Number of the variables in the clause. + OMPExclusiveClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, unsigned N) + : OMPVarListClause<OMPExclusiveClause>(OMPC_exclusive, StartLoc, + LParenLoc, EndLoc, N) {} + + /// Build an empty clause. + /// + /// \param N Number of variables. + explicit OMPExclusiveClause(unsigned N) + : OMPVarListClause<OMPExclusiveClause>(OMPC_exclusive, SourceLocation(), + SourceLocation(), SourceLocation(), + N) {} + +public: + /// Creates clause with a list of variables \a VL. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param VL List of references to the original variables. + static OMPExclusiveClause *Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef<Expr *> VL); + + /// Creates an empty clause with the place for \a N variables. + /// + /// \param C AST context. + /// \param N The number of variables. + static OMPExclusiveClause *CreateEmpty(const ASTContext &C, unsigned N); + + child_range children() { + return child_range(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); + } + + const_child_range children() const { + auto Children = const_cast<OMPExclusiveClause *>(this)->children(); + return const_child_range(Children.begin(), Children.end()); + } + + 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() == OMPC_exclusive; + } +}; + /// This class implements a simple visitor for OMPClause /// subclasses. template<class ImplClass, template <typename> class Ptr, typename RetTy> diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 94f68f555fdf..4bd489f4ba6d 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -3190,6 +3190,13 @@ bool RecursiveASTVisitor<Derived>::VisitOMPInclusiveClause( return true; } +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPExclusiveClause( + OMPExclusiveClause *C) { + TRY_TO(VisitOMPClauseList(C)); + return true; +} + template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPPrivateClause(OMPPrivateClause *C) { TRY_TO(VisitOMPClauseList(C)); diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def index 1e4b2b116a98..ffffed50ef86 100644 --- a/clang/include/clang/Basic/OpenMPKinds.def +++ b/clang/include/clang/Basic/OpenMPKinds.def @@ -285,9 +285,11 @@ OPENMP_CLAUSE(depobj, OMPDepobjClause) OPENMP_CLAUSE(destroy, OMPDestroyClause) OPENMP_CLAUSE(detach, OMPDetachClause) OPENMP_CLAUSE(inclusive, OMPInclusiveClause) +OPENMP_CLAUSE(exclusive, OMPExclusiveClause) // Clauses allowed for OpenMP directive 'scan'. OPENMP_SCAN_CLAUSE(inclusive) +OPENMP_SCAN_CLAUSE(exclusive) // Clauses allowed for OpenMP directive 'parallel'. OPENMP_PARALLEL_CLAUSE(if) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 03f3a1b4bdc9..90ba85638f0b 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -10506,6 +10506,11 @@ class Sema final { SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); + /// Called on well-formed 'exclusive' clause. + OMPClause *ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); /// Called on well-formed 'allocate' clause. OMPClause * ActOnOpenMPAllocateClause(Expr *Allocator, ArrayRef<Expr *> VarList, diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp index de8fd67a0250..5f9da85a9f07 100644 --- a/clang/lib/AST/OpenMPClause.cpp +++ b/clang/lib/AST/OpenMPClause.cpp @@ -147,6 +147,7 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) { case OMPC_destroy: case OMPC_detach: case OMPC_inclusive: + case OMPC_exclusive: break; } @@ -235,6 +236,7 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C) case OMPC_destroy: case OMPC_detach: case OMPC_inclusive: + case OMPC_exclusive: break; } @@ -1268,6 +1270,24 @@ OMPInclusiveClause *OMPInclusiveClause::CreateEmpty(const ASTContext &C, return new (Mem) OMPInclusiveClause(N); } +OMPExclusiveClause *OMPExclusiveClause::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, + ArrayRef<Expr *> VL) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size())); + auto *Clause = + new (Mem) OMPExclusiveClause(StartLoc, LParenLoc, EndLoc, VL.size()); + Clause->setVarRefs(VL); + return Clause; +} + +OMPExclusiveClause *OMPExclusiveClause::CreateEmpty(const ASTContext &C, + unsigned N) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N)); + return new (Mem) OMPExclusiveClause(N); +} + //===----------------------------------------------------------------------===// // OpenMP clauses printing methods //===----------------------------------------------------------------------===// @@ -1833,6 +1853,14 @@ void OMPClausePrinter::VisitOMPInclusiveClause(OMPInclusiveClause *Node) { } } +void OMPClausePrinter::VisitOMPExclusiveClause(OMPExclusiveClause *Node) { + if (!Node->varlist_empty()) { + OS << "exclusive"; + VisitOMPClauseList(Node, '('); + OS << ")"; + } +} + void OMPTraitInfo::getAsVariantMatchInfo( ASTContext &ASTCtx, llvm::omp::VariantMatchInfo &VMI) const { for (const OMPTraitSet &Set : Sets) { diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index a31a65fad35f..cd39024cd838 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -798,6 +798,9 @@ void OMPClauseProfiler::VisitOMPNontemporalClause( void OMPClauseProfiler::VisitOMPInclusiveClause(const OMPInclusiveClause *C) { VisitOMPClauseList(C); } +void OMPClauseProfiler::VisitOMPExclusiveClause(const OMPExclusiveClause *C) { + VisitOMPClauseList(C); +} void OMPClauseProfiler::VisitOMPOrderClause(const OMPOrderClause *C) {} } // namespace diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index a905dff440d7..36e7f4583468 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -213,6 +213,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, case OMPC_destroy: case OMPC_detach: case OMPC_inclusive: + case OMPC_exclusive: break; } llvm_unreachable("Invalid OpenMP simple clause kind"); @@ -449,6 +450,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, case OMPC_destroy: case OMPC_detach: case OMPC_inclusive: + case OMPC_exclusive: break; } llvm_unreachable("Invalid OpenMP simple clause kind"); diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index e05829f0a890..bef36bf4693b 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -4617,6 +4617,7 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind, case OMPC_destroy: case OMPC_detach: case OMPC_inclusive: + case OMPC_exclusive: llvm_unreachable("Clause is not allowed in 'omp atomic'."); } } diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index bb239c833b82..acc1e55eb721 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -2344,7 +2344,8 @@ bool Parser::ParseOpenMPSimpleVarList( /// from-clause | is_device_ptr-clause | task_reduction-clause | /// in_reduction-clause | allocator-clause | allocate-clause | /// acq_rel-clause | acquire-clause | release-clause | relaxed-clause | -/// depobj-clause | destroy-clause | detach-clause | inclusive-clause +/// depobj-clause | destroy-clause | detach-clause | inclusive-clause | +/// exclusive-clause /// OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, bool FirstClause) { @@ -2514,6 +2515,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_allocate: case OMPC_nontemporal: case OMPC_inclusive: + case OMPC_exclusive: Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective); break; case OMPC_device_type: @@ -3239,7 +3241,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, /// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate', /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction', -/// 'in_reduction', 'nontemporal' or 'inclusive'. +/// 'in_reduction', 'nontemporal', 'exclusive' or 'inclusive'. /// /// private-clause: /// 'private' '(' list ')' @@ -3283,6 +3285,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, /// 'nontemporal' '(' list ')' /// inclusive-clause: /// 'inclusive' '(' list ')' +/// exclusive-clause: +/// 'exclusive' '(' list ')' /// /// For 'linear' clause linear-list may have the following forms: /// list diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 8c488da6cf0f..d9a4a17f1866 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -5100,6 +5100,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( case OMPC_order: case OMPC_destroy: case OMPC_inclusive: + case OMPC_exclusive: continue; case OMPC_allocator: case OMPC_flush: @@ -11084,6 +11085,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, case OMPC_order: case OMPC_destroy: case OMPC_inclusive: + case OMPC_exclusive: llvm_unreachable("Clause is not allowed."); } return Res; @@ -11820,6 +11822,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPC_destroy: case OMPC_detach: case OMPC_inclusive: + case OMPC_exclusive: llvm_unreachable("Unexpected OpenMP clause."); } return CaptureRegion; @@ -12258,6 +12261,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause( case OMPC_destroy: case OMPC_detach: case OMPC_inclusive: + case OMPC_exclusive: llvm_unreachable("Clause is not allowed."); } return Res; @@ -12482,6 +12486,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause( case OMPC_destroy: case OMPC_detach: case OMPC_inclusive: + case OMPC_exclusive: llvm_unreachable("Clause is not allowed."); } return Res; @@ -12713,6 +12718,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind, case OMPC_order: case OMPC_detach: case OMPC_inclusive: + case OMPC_exclusive: llvm_unreachable("Clause is not allowed."); } return Res; @@ -12923,6 +12929,9 @@ OMPClause *Sema::ActOnOpenMPVarListClause( case OMPC_inclusive: Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc); break; + case OMPC_exclusive: + Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc); + break; case OMPC_if: case OMPC_depobj: case OMPC_final: @@ -18008,3 +18017,31 @@ OMPClause *Sema::ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList, return OMPInclusiveClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars); } + +OMPClause *Sema::ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + SmallVector<Expr *, 8> Vars; + for (Expr *RefExpr : VarList) { + assert(RefExpr && "NULL expr in OpenMP nontemporal clause."); + SourceLocation ELoc; + SourceRange ERange; + Expr *SimpleRefExpr = RefExpr; + auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange, + /*AllowArraySection=*/true); + if (Res.second) + // It will be analyzed later. + Vars.push_back(RefExpr); + ValueDecl *D = Res.first; + if (!D) + continue; + + Vars.push_back(RefExpr); + } + + if (Vars.empty()) + return nullptr; + + return OMPExclusiveClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars); +} diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 8a22eb89d806..3e6d67d67845 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -2065,6 +2065,18 @@ class TreeTransform { EndLoc); } + /// Build a new OpenMP 'exclusive' clause. + /// + /// By default, performs semantic analysis to build the new OpenMP clause. + /// Subclasses may override this routine to provide diff erent behavior. + OMPClause *RebuildOMPExclusiveClause(ArrayRef<Expr *> VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, + EndLoc); + } + /// Build a new OpenMP 'order' clause. /// /// By default, performs semantic analysis to build the new OpenMP clause. @@ -9548,6 +9560,21 @@ TreeTransform<Derived>::TransformOMPInclusiveClause(OMPInclusiveClause *C) { Vars, C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); } +template <typename Derived> +OMPClause * +TreeTransform<Derived>::TransformOMPExclusiveClause(OMPExclusiveClause *C) { + llvm::SmallVector<Expr *, 16> Vars; + Vars.reserve(C->varlist_size()); + for (auto *VE : C->varlists()) { + ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE)); + if (EVar.isInvalid()) + return nullptr; + Vars.push_back(EVar.get()); + } + return getDerived().RebuildOMPExclusiveClause( + Vars, C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); +} + template <typename Derived> OMPClause * TreeTransform<Derived>::TransformOMPOrderClause(OMPOrderClause *C) { diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index ac111776fe76..77f15bcd910a 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -11845,6 +11845,9 @@ OMPClause *OMPClauseReader::readClause() { case OMPC_inclusive: C = OMPInclusiveClause::CreateEmpty(Context, Record.readInt()); break; + case OMPC_exclusive: + C = OMPExclusiveClause::CreateEmpty(Context, Record.readInt()); + break; case OMPC_order: C = new (Context) OMPOrderClause(); break; @@ -12665,6 +12668,16 @@ void OMPClauseReader::VisitOMPInclusiveClause(OMPInclusiveClause *C) { C->setVarRefs(Vars); } +void OMPClauseReader::VisitOMPExclusiveClause(OMPExclusiveClause *C) { + 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::VisitOMPOrderClause(OMPOrderClause *C) { C->setKind(Record.readEnum<OpenMPOrderClauseKind>()); C->setLParenLoc(Record.readSourceLocation()); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index a5d5b0f47144..9ccebae9567d 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -6611,6 +6611,13 @@ void OMPClauseWriter::VisitOMPInclusiveClause(OMPInclusiveClause *C) { Record.AddStmt(VE); } +void OMPClauseWriter::VisitOMPExclusiveClause(OMPExclusiveClause *C) { + Record.push_back(C->varlist_size()); + Record.AddSourceLocation(C->getLParenLoc()); + for (auto *VE : C->varlists()) + Record.AddStmt(VE); +} + void OMPClauseWriter::VisitOMPOrderClause(OMPOrderClause *C) { Record.writeEnum(C->getKind()); Record.AddSourceLocation(C->getLParenLoc()); diff --git a/clang/test/OpenMP/scan_ast_print.cpp b/clang/test/OpenMP/scan_ast_print.cpp index efcaa2da138a..4b9eca6f7ec9 100644 --- a/clang/test/OpenMP/scan_ast_print.cpp +++ b/clang/test/OpenMP/scan_ast_print.cpp @@ -39,11 +39,11 @@ int main(int argc, char **argv) { // CHECK: static int a; #pragma omp for simd for (int i = 0; i < 10; ++i) { -#pragma omp scan inclusive(a) +#pragma omp scan exclusive(a, argc) } // CHECK-NEXT: #pragma omp for simd // CHECK-NEXT: for (int i = 0; i < 10; ++i) { -// CHECK-NEXT: #pragma omp scan inclusive(a){{$}} +// CHECK-NEXT: #pragma omp scan exclusive(a,argc){{$}} return tmain(argc) + tmain(argv[0][0]) + a; } diff --git a/clang/test/OpenMP/scan_messages.cpp b/clang/test/OpenMP/scan_messages.cpp index 3be998d0f96e..9f093858c249 100644 --- a/clang/test/OpenMP/scan_messages.cpp +++ b/clang/test/OpenMP/scan_messages.cpp @@ -54,25 +54,25 @@ T tmain(T argc) { #pragma omp simd for (int i = 0; i < 10; ++i) switch (argc) { -#pragma omp scan inclusive(argc) // expected-note 2 {{previous 'scan' directive used here}} +#pragma omp scan exclusive(argc) // expected-note 2 {{previous 'scan' directive used here}} case 1: -#pragma omp scan inclusive(argc) // expected-error {{exactly one 'scan' directive must appear in the loop body of an enclosing directive}} +#pragma omp scan exclusive(argc) // expected-error {{exactly one 'scan' directive must appear in the loop body of an enclosing directive}} break; default: { -#pragma omp scan inclusive(argc) // expected-error {{exactly one 'scan' directive must appear in the loop body of an enclosing directive}} +#pragma omp scan exclusive(argc) // expected-error {{exactly one 'scan' directive must appear in the loop body of an enclosing directive}} } break; } #pragma omp simd for (int i = 0; i < 10; ++i) for (;;) -#pragma omp scan inclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} +#pragma omp scan exclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} for (;;) { -#pragma omp scan inclusive(argc) +#pragma omp scan exclusive(argc) } #pragma omp simd for (int i = 0; i < 10; ++i) { label: -#pragma omp scan inclusive(argc) +#pragma omp scan exclusive(argc) } #pragma omp simd for (int i = 0; i < 10; ++i) { @@ -91,6 +91,16 @@ int main(int argc, char **argv) { } #pragma omp simd for (int i = 0; i < 10; ++i) { +#pragma omp scan exclusive(argc) inclusive(argc) // expected-error {{exactly one of 'inclusive' or 'exclusive' clauses is expected}} + ; + } +#pragma omp simd + for (int i = 0; i < 10; ++i) { +#pragma omp scan exclusive(argc) exclusive(argc) // expected-error {{exactly one of 'inclusive' or 'exclusive' clauses is expected}} + ; + } +#pragma omp simd + for (int i = 0; i < 10; ++i) { #pragma omp scan untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp scan'}} expected-error {{exactly one of 'inclusive' or 'exclusive' clauses is expected}} #pragma omp scan unknown // expected-warning {{extra tokens at the end of '#pragma omp scan' are ignored}} expected-error {{exactly one of 'inclusive' or 'exclusive' clauses is expected}} } @@ -117,18 +127,18 @@ int main(int argc, char **argv) { #pragma omp simd for (int i = 0; i < 10; ++i) do { -#pragma omp scan inclusive(argc) +#pragma omp scan exclusive(argc) } while (argc); #pragma omp simd for (int i = 0; i < 10; ++i) switch (argc) -#pragma omp scan inclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} +#pragma omp scan exclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} switch (argc) case 1: -#pragma omp scan inclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} +#pragma omp scan exclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} switch (argc) case 1: { -#pragma omp scan inclusive(argc) +#pragma omp scan exclusive(argc) } #pragma omp simd for (int i = 0; i < 10; ++i) diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 31a0f364a348..ae7fd4271799 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -2312,6 +2312,9 @@ void OMPClauseEnqueue::VisitOMPClauseList(T *Node) { void OMPClauseEnqueue::VisitOMPInclusiveClause(const OMPInclusiveClause *C) { VisitOMPClauseList(C); } +void OMPClauseEnqueue::VisitOMPExclusiveClause(const OMPExclusiveClause *C) { + VisitOMPClauseList(C); +} void OMPClauseEnqueue::VisitOMPAllocateClause(const OMPAllocateClause *C) { VisitOMPClauseList(C); Visitor->AddStmt(C->getAllocator()); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits