From c112e941a0c5d3b3423272c3f0024cdf6b50e44e Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Fri, 28 Feb 2020 09:52:15 -0500 Subject: [PATCH] [OPENMP50]Add basic support for depobj construct. Added basic parsing/sema/serialization support for depobj directive. --- clang/include/clang-c/Index.h | 6 +- clang/include/clang/AST/OpenMPClause.h | 86 ++++++++++++ clang/include/clang/AST/RecursiveASTVisitor.h | 9 ++ clang/include/clang/AST/StmtOpenMP.h | 58 +++++++++ clang/include/clang/Basic/DiagnosticSemaKinds.td | 10 +- clang/include/clang/Basic/OpenMPKinds.def | 8 ++ clang/include/clang/Basic/StmtNodes.td | 1 + clang/include/clang/Sema/Sema.h | 8 ++ clang/include/clang/Serialization/ASTBitCodes.h | 1 + clang/lib/AST/OpenMPClause.cpp | 22 ++++ clang/lib/AST/StmtOpenMP.cpp | 26 +++- clang/lib/AST/StmtPrinter.cpp | 5 + clang/lib/AST/StmtProfile.cpp | 8 ++ clang/lib/Basic/OpenMPKinds.cpp | 26 +++- clang/lib/CodeGen/CGOpenMPRuntime.cpp | 5 + clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp | 4 + clang/lib/CodeGen/CGStmt.cpp | 3 + clang/lib/CodeGen/CGStmtOpenMP.cpp | 3 + clang/lib/CodeGen/CodeGenFunction.h | 1 + clang/lib/Parse/ParseOpenMP.cpp | 49 ++++--- clang/lib/Sema/SemaExceptionSpec.cpp | 1 + clang/lib/Sema/SemaOpenMP.cpp | 97 +++++++++++++- clang/lib/Sema/TreeTransform.h | 32 +++++ clang/lib/Serialization/ASTReader.cpp | 8 ++ clang/lib/Serialization/ASTReaderStmt.cpp | 12 ++ clang/lib/Serialization/ASTWriter.cpp | 5 + clang/lib/Serialization/ASTWriterStmt.cpp | 7 + clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 1 + clang/test/OpenMP/allocate_allocator_messages.cpp | 8 +- clang/test/OpenMP/depobj_ast_print.cpp | 39 ++++++ clang/test/OpenMP/depobj_messages.cpp | 151 ++++++++++++++++++++++ clang/test/OpenMP/flush_messages.cpp | 2 +- clang/tools/libclang/CIndex.cpp | 14 +- clang/tools/libclang/CXCursor.cpp | 3 + llvm/include/llvm/Frontend/OpenMP/OMPKinds.def | 3 +- 35 files changed, 691 insertions(+), 31 deletions(-) create mode 100644 clang/test/OpenMP/depobj_ast_print.cpp create mode 100644 clang/test/OpenMP/depobj_messages.cpp diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index efb96f3..9d4930a 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2574,7 +2574,11 @@ enum CXCursorKind { */ CXCursor_OMPParallelMasterDirective = 285, - CXCursor_LastStmt = CXCursor_OMPParallelMasterDirective, + /** OpenMP depobj directive. + */ + CXCursor_OMPDepobjDirective = 286, + + CXCursor_LastStmt = CXCursor_OMPDepobjDirective, /** * Cursor that represents the translation unit itself. diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h index 453c068..5d78e90 100644 --- a/clang/include/clang/AST/OpenMPClause.h +++ b/clang/include/clang/AST/OpenMPClause.h @@ -4108,6 +4108,92 @@ public: } }; +/// This represents implicit clause 'depobj' for the '#pragma omp depobj' +/// directive. +/// This clause does not exist by itself, it can be only as a part of 'omp +/// depobj' directive. This clause is introduced to keep the original structure +/// of \a OMPExecutableDirective class and its derivatives and to use the +/// existing infrastructure of clauses with the list of variables. +/// +/// \code +/// #pragma omp depobj(a) destroy +/// \endcode +/// In this example directive '#pragma omp depobj' has implicit clause 'depobj' +/// with the depobj 'a'. +class OMPDepobjClause final : public OMPClause { + friend class OMPClauseReader; + + /// Location of '('. + SourceLocation LParenLoc; + + /// Chunk size. + Expr *Depobj = nullptr; + + /// 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. + OMPDepobjClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : OMPClause(OMPC_depobj, StartLoc, EndLoc), LParenLoc(LParenLoc) {} + + /// Build an empty clause. + /// + explicit OMPDepobjClause() + : OMPClause(OMPC_depobj, SourceLocation(), SourceLocation()) {} + + void setDepobj(Expr *E) { Depobj = E; } + + /// Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + +public: + /// Creates clause. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param Depobj depobj expression associated with the 'depobj' directive. + static OMPDepobjClause *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, Expr *Depobj); + + /// Creates an empty clause. + /// + /// \param C AST context. + static OMPDepobjClause *CreateEmpty(const ASTContext &C); + + /// Returns depobj expression associated with the clause. + Expr *getDepobj() { return Depobj; } + const Expr *getDepobj() const { return Depobj; } + + /// Returns the location of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + child_range children() { + return child_range(reinterpret_cast(&Depobj), + reinterpret_cast(&Depobj) + 1); + } + + const_child_range children() const { + auto Children = const_cast(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_depobj; + } +}; + /// This represents implicit clause 'depend' for the '#pragma omp task' /// directive. /// diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 29b2c35..ceb49b4 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2842,6 +2842,9 @@ DEF_TRAVERSE_STMT(OMPCancelDirective, DEF_TRAVERSE_STMT(OMPFlushDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPDepobjDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPOrderedDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) @@ -3348,6 +3351,12 @@ bool RecursiveASTVisitor::VisitOMPFlushClause(OMPFlushClause *C) { } template +bool RecursiveASTVisitor::VisitOMPDepobjClause(OMPDepobjClause *C) { + TRY_TO(TraverseStmt(C->getDepobj())); + return true; +} + +template bool RecursiveASTVisitor::VisitOMPDependClause(OMPDependClause *C) { TRY_TO(VisitOMPClauseList(C)); return true; diff --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h index 5564907..5f7589a 100644 --- a/clang/include/clang/AST/StmtOpenMP.h +++ b/clang/include/clang/AST/StmtOpenMP.h @@ -2314,6 +2314,64 @@ public: } }; +/// This represents '#pragma omp depobj' directive. +/// +/// \code +/// #pragma omp depobj(a) depend(in:x,y) +/// \endcode +/// In this example directive '#pragma omp depobj' initializes a depobj object +/// 'a' with dependence type 'in' and a list with 'x' and 'y' locators. +class OMPDepobjDirective final : public OMPExecutableDirective { + friend class ASTStmtReader; + + /// Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param NumClauses Number of clauses. + /// + OMPDepobjDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPDepobjDirectiveClass, + llvm::omp::OMPD_depobj, StartLoc, EndLoc, + NumClauses, 0) {} + + /// Build an empty directive. + /// + /// \param NumClauses Number of clauses. + /// + explicit OMPDepobjDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPDepobjDirectiveClass, + llvm::omp::OMPD_depobj, SourceLocation(), + SourceLocation(), NumClauses, 0) {} + +public: + /// Creates directive with a list of \a Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param Clauses List of clauses. + /// + static OMPDepobjDirective *Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef Clauses); + + /// Creates an empty directive with the place for \a NumClauses + /// clauses. + /// + /// \param C AST context. + /// \param NumClauses Number of clauses. + /// + static OMPDepobjDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPDepobjDirectiveClass; + } +}; + /// This represents '#pragma omp ordered' directive. /// /// \code diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 2d6978f..e6155d5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10031,8 +10031,14 @@ def note_omp_invalid_subscript_on_this_ptr_map : Note < "expected 'this' subscript expression on map clause to be 'this[0]'">; def err_omp_invalid_map_this_expr : Error < "invalid 'this' expression on 'map' clause">; -def err_implied_omp_allocator_handle_t_not_found : Error< - "omp_allocator_handle_t type not found; include ">; +def err_omp_implied_type_not_found : Error< + "'%0' type not found; include ">; +def err_omp_expected_omp_depend_t_lvalue : Error< + "expected lvalue expression%select{ of 'omp_depend_t' type, not %1|}0">; +def err_omp_depobj_expected : Error< + "expected depobj expression">; +def err_omp_depobj_single_clause_expected : Error< + "exactly one of 'depend', 'destroy', or 'update' clauses is expected">; def err_omp_expected_predefined_allocator : Error< "expected one of the predefined allocators for the variables with the static " "storage: 'omp_default_mem_alloc', 'omp_large_cap_mem_alloc', " diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def index f2913fe..2954f7b 100644 --- a/clang/include/clang/Basic/OpenMPKinds.def +++ b/clang/include/clang/Basic/OpenMPKinds.def @@ -209,6 +209,9 @@ #ifndef OPENMP_FLUSH_CLAUSE #define OPENMP_FLUSH_CLAUSE(Name) #endif +#ifndef OPENMP_DEPOBJ_CLAUSE +#define OPENMP_DEPOBJ_CLAUSE(Name) +#endif // OpenMP clauses. OPENMP_CLAUSE(allocator, OMPAllocatorClause) @@ -272,6 +275,7 @@ OPENMP_CLAUSE(atomic_default_mem_order, OMPAtomicDefaultMemOrderClause) OPENMP_CLAUSE(allocate, OMPAllocateClause) OPENMP_CLAUSE(nontemporal, OMPNontemporalClause) OPENMP_CLAUSE(order, OMPOrderClause) +OPENMP_CLAUSE(depobj, OMPDepobjClause) // Clauses allowed for OpenMP directive 'parallel'. OPENMP_PARALLEL_CLAUSE(if) @@ -1078,6 +1082,10 @@ OPENMP_FLUSH_CLAUSE(acq_rel) OPENMP_FLUSH_CLAUSE(acquire) OPENMP_FLUSH_CLAUSE(release) +// Clauses allowed for OpenMP directive 'depobj'. +OPENMP_DEPOBJ_CLAUSE(depend) + +#undef OPENMP_DEPOBJ_CLAUSE #undef OPENMP_FLUSH_CLAUSE #undef OPENMP_ORDER_KIND #undef OPENMP_LASTPRIVATE_KIND diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td index 2333202..41c6dbd 100644 --- a/clang/include/clang/Basic/StmtNodes.td +++ b/clang/include/clang/Basic/StmtNodes.td @@ -232,6 +232,7 @@ def OMPBarrierDirective : StmtNode; def OMPTaskwaitDirective : StmtNode; def OMPTaskgroupDirective : StmtNode; def OMPFlushDirective : StmtNode; +def OMPDepobjDirective : StmtNode; def OMPOrderedDirective : StmtNode; def OMPAtomicDirective : StmtNode; def OMPTargetDirective : StmtNode; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index f1dfe41..6768089 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -9994,6 +9994,10 @@ public: StmtResult ActOnOpenMPFlushDirective(ArrayRef Clauses, SourceLocation StartLoc, SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp depobj'. + StmtResult ActOnOpenMPDepobjDirective(ArrayRef Clauses, + SourceLocation StartLoc, + SourceLocation EndLoc); /// Called on well-formed '\#pragma omp ordered' after parsing of the /// associated statement. StmtResult ActOnOpenMPOrderedDirective(ArrayRef Clauses, @@ -10452,6 +10456,10 @@ public: SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); + /// Called on well-formed 'depobj' pseudo clause. + OMPClause *ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); /// Called on well-formed 'depend' clause. OMPClause * ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, SourceLocation DepLoc, diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 83af4d1..0767fb8 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1825,6 +1825,7 @@ namespace serialization { STMT_OMP_BARRIER_DIRECTIVE, STMT_OMP_TASKWAIT_DIRECTIVE, STMT_OMP_FLUSH_DIRECTIVE, + STMT_OMP_DEPOBJ_DIRECTIVE, STMT_OMP_ORDERED_DIRECTIVE, STMT_OMP_ATOMIC_DIRECTIVE, STMT_OMP_TARGET_DIRECTIVE, diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp index c5c9bc7..888dc30 100644 --- a/clang/lib/AST/OpenMPClause.cpp +++ b/clang/lib/AST/OpenMPClause.cpp @@ -111,6 +111,7 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) { case OMPC_mergeable: case OMPC_threadprivate: case OMPC_flush: + case OMPC_depobj: case OMPC_read: case OMPC_write: case OMPC_update: @@ -189,6 +190,7 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C) case OMPC_mergeable: case OMPC_threadprivate: case OMPC_flush: + case OMPC_depobj: case OMPC_read: case OMPC_write: case OMPC_update: @@ -835,6 +837,20 @@ OMPFlushClause *OMPFlushClause::CreateEmpty(const ASTContext &C, unsigned N) { return new (Mem) OMPFlushClause(N); } +OMPDepobjClause *OMPDepobjClause::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc, + Expr *Depobj) { + auto *Clause = new (C) OMPDepobjClause(StartLoc, LParenLoc, RParenLoc); + Clause->setDepobj(Depobj); + return Clause; +} + +OMPDepobjClause *OMPDepobjClause::CreateEmpty(const ASTContext &C) { + return new (C) OMPDepobjClause(); +} + OMPDependClause * OMPDependClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, @@ -1597,6 +1613,12 @@ void OMPClausePrinter::VisitOMPFlushClause(OMPFlushClause *Node) { } } +void OMPClausePrinter::VisitOMPDepobjClause(OMPDepobjClause *Node) { + OS << "("; + Node->getDepobj()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + void OMPClausePrinter::VisitOMPDependClause(OMPDependClause *Node) { OS << "depend("; OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), diff --git a/clang/lib/AST/StmtOpenMP.cpp b/clang/lib/AST/StmtOpenMP.cpp index 15bedb9..153d492 100644 --- a/clang/lib/AST/StmtOpenMP.cpp +++ b/clang/lib/AST/StmtOpenMP.cpp @@ -10,9 +10,8 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/StmtOpenMP.h" - #include "clang/AST/ASTContext.h" +#include "clang/AST/StmtOpenMP.h" using namespace clang; using namespace llvm::omp; @@ -759,6 +758,29 @@ OMPFlushDirective *OMPFlushDirective::CreateEmpty(const ASTContext &C, return new (Mem) OMPFlushDirective(NumClauses); } +OMPDepobjDirective *OMPDepobjDirective::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef Clauses) { + unsigned Size = + llvm::alignTo(sizeof(OMPDepobjDirective), alignof(OMPClause *)); + void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size(), + alignof(OMPDepobjDirective)); + auto *Dir = new (Mem) OMPDepobjDirective(StartLoc, EndLoc, Clauses.size()); + Dir->setClauses(Clauses); + return Dir; +} + +OMPDepobjDirective *OMPDepobjDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + EmptyShell) { + unsigned Size = + llvm::alignTo(sizeof(OMPDepobjDirective), alignof(OMPClause *)); + void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses, + alignof(OMPDepobjDirective)); + return new (Mem) OMPDepobjDirective(NumClauses); +} + OMPOrderedDirective *OMPOrderedDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 76295ae..f7a97c2 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -753,6 +753,11 @@ void StmtPrinter::VisitOMPFlushDirective(OMPFlushDirective *Node) { PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPDepobjDirective(OMPDepobjDirective *Node) { + Indent() << "#pragma omp depobj"; + PrintOMPExecutableDirective(Node); +} + void StmtPrinter::VisitOMPOrderedDirective(OMPOrderedDirective *Node) { Indent() << "#pragma omp ordered"; PrintOMPExecutableDirective(Node, Node->hasClausesOfKind()); diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 76c5fe2..bf0cc52 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -719,6 +719,10 @@ OMPClauseProfiler::VisitOMPCopyprivateClause(const OMPCopyprivateClause *C) { void OMPClauseProfiler::VisitOMPFlushClause(const OMPFlushClause *C) { VisitOMPClauseList(C); } +void OMPClauseProfiler::VisitOMPDepobjClause(const OMPDepobjClause *C) { + if (const Expr *Depobj = C->getDepobj()) + Profiler->VisitStmt(Depobj); +} void OMPClauseProfiler::VisitOMPDependClause(const OMPDependClause *C) { VisitOMPClauseList(C); } @@ -885,6 +889,10 @@ void StmtProfiler::VisitOMPFlushDirective(const OMPFlushDirective *S) { VisitOMPExecutableDirective(S); } +void StmtProfiler::VisitOMPDepobjDirective(const OMPDepobjDirective *S) { + VisitOMPExecutableDirective(S); +} + void StmtProfiler::VisitOMPOrderedDirective(const OMPOrderedDirective *S) { VisitOMPExecutableDirective(S); } diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index e7c3a8a..364b755 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -25,7 +25,14 @@ OpenMPClauseKind clang::getOpenMPClauseKind(StringRef Str) { // clause for 'flush' directive. If the 'flush' clause is explicitly specified // the Parser should generate a warning about extra tokens at the end of the // directive. - if (Str == "flush") + // 'depobj' clause cannot be specified explicitly, because this is an implicit + // clause for 'depobj' directive. If the 'depobj' clause is explicitly + // specified the Parser should generate a warning about extra tokens at the + // end of the directive. + if (llvm::StringSwitch(Str) + .Case("flush", true) + .Case("depobj", true) + .Default(false)) return OMPC_unknown; return llvm::StringSwitch(Str) #define OPENMP_CLAUSE(Name, Class) .Case(#Name, OMPC_##Name) @@ -166,6 +173,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, case OMPC_untied: case OMPC_mergeable: case OMPC_flush: + case OMPC_depobj: case OMPC_read: case OMPC_write: case OMPC_update: @@ -380,6 +388,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, case OMPC_untied: case OMPC_mergeable: case OMPC_flush: + case OMPC_depobj: case OMPC_read: case OMPC_write: case OMPC_update: @@ -553,6 +562,20 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, break; } break; + case OMPD_depobj: + if (OpenMPVersion < 50) + return false; + switch (CKind) { +#define OPENMP_DEPOBJ_CLAUSE(Name) \ + case OMPC_##Name: \ + return true; +#include "clang/Basic/OpenMPKinds.def" + case OMPC_depobj: + return true; + default: + break; + } + break; case OMPD_atomic: if (OpenMPVersion < 50 && (CKind == OMPC_acq_rel || CKind == OMPC_acquire || @@ -1195,6 +1218,7 @@ void clang::getOpenMPCaptureRegions( case OMPD_cancellation_point: case OMPD_cancel: case OMPD_flush: + case OMPD_depobj: case OMPD_declare_reduction: case OMPD_declare_mapper: case OMPD_declare_simd: diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 79c2f1b..9fe0306 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -6703,6 +6703,7 @@ emitNumTeamsForTargetDirective(CodeGenFunction &CGF, case OMPD_taskgroup: case OMPD_atomic: case OMPD_flush: + case OMPD_depobj: case OMPD_teams: case OMPD_target_data: case OMPD_target_exit_data: @@ -7014,6 +7015,7 @@ emitNumThreadsForTargetDirective(CodeGenFunction &CGF, case OMPD_taskgroup: case OMPD_atomic: case OMPD_flush: + case OMPD_depobj: case OMPD_teams: case OMPD_target_data: case OMPD_target_exit_data: @@ -8798,6 +8800,7 @@ getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) { case OMPD_taskgroup: case OMPD_atomic: case OMPD_flush: + case OMPD_depobj: case OMPD_teams: case OMPD_target_data: case OMPD_target_exit_data: @@ -9561,6 +9564,7 @@ void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, case OMPD_taskgroup: case OMPD_atomic: case OMPD_flush: + case OMPD_depobj: case OMPD_teams: case OMPD_target_data: case OMPD_target_exit_data: @@ -10201,6 +10205,7 @@ void CGOpenMPRuntime::emitTargetDataStandAloneCall( case OMPD_taskgroup: case OMPD_atomic: case OMPD_flush: + case OMPD_depobj: case OMPD_teams: case OMPD_target_data: case OMPD_distribute: diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp index 867bfb0..b139529 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp @@ -786,6 +786,7 @@ static bool hasNestedSPMDDirective(ASTContext &Ctx, case OMPD_taskgroup: case OMPD_atomic: case OMPD_flush: + case OMPD_depobj: case OMPD_teams: case OMPD_target_data: case OMPD_target_exit_data: @@ -862,6 +863,7 @@ static bool supportsSPMDExecutionMode(ASTContext &Ctx, case OMPD_taskgroup: case OMPD_atomic: case OMPD_flush: + case OMPD_depobj: case OMPD_teams: case OMPD_target_data: case OMPD_target_exit_data: @@ -1031,6 +1033,7 @@ static bool hasNestedLightweightDirective(ASTContext &Ctx, case OMPD_taskgroup: case OMPD_atomic: case OMPD_flush: + case OMPD_depobj: case OMPD_teams: case OMPD_target_data: case OMPD_target_exit_data: @@ -1113,6 +1116,7 @@ static bool supportsLightweightRuntime(ASTContext &Ctx, case OMPD_taskgroup: case OMPD_atomic: case OMPD_flush: + case OMPD_depobj: case OMPD_teams: case OMPD_target_data: case OMPD_target_exit_data: diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 238e049..a334bab 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -247,6 +247,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef Attrs) { case Stmt::OMPFlushDirectiveClass: EmitOMPFlushDirective(cast(*S)); break; + case Stmt::OMPDepobjDirectiveClass: + EmitOMPDepobjDirective(cast(*S)); + break; case Stmt::OMPOrderedDirectiveClass: EmitOMPOrderedDirective(cast(*S)); break; diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index bcd2d06..f5e4788 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -3800,6 +3800,8 @@ void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &S) { S.getBeginLoc(), AO); } +void CodeGenFunction::EmitOMPDepobjDirective(const OMPDepobjDirective &S) {} + void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S, const CodeGenLoopTy &CodeGenLoop, Expr *IncExpr) { @@ -4543,6 +4545,7 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind, case OMPC_copyin: case OMPC_copyprivate: case OMPC_flush: + case OMPC_depobj: case OMPC_proc_bind: case OMPC_schedule: case OMPC_ordered: diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 1411171..907b4d7 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -3262,6 +3262,7 @@ public: void EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S); void EmitOMPTaskgroupDirective(const OMPTaskgroupDirective &S); void EmitOMPFlushDirective(const OMPFlushDirective &S); + void EmitOMPDepobjDirective(const OMPDepobjDirective &S); void EmitOMPOrderedDirective(const OMPOrderedDirective &S); void EmitOMPAtomicDirective(const OMPAtomicDirective &S); void EmitOMPTargetDirective(const OMPTargetDirective &S); diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 8c822ec..3c44c0e 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -1842,6 +1842,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( case OMPD_taskwait: case OMPD_taskgroup: case OMPD_flush: + case OMPD_depobj: case OMPD_for: case OMPD_for_simd: case OMPD_sections: @@ -2064,6 +2065,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { break; } case OMPD_flush: + case OMPD_depobj: case OMPD_taskyield: case OMPD_barrier: case OMPD_taskwait: @@ -2123,10 +2125,13 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { case OMPD_target_teams_distribute_parallel_for: case OMPD_target_teams_distribute_parallel_for_simd: case OMPD_target_teams_distribute_simd: { - // Special processing for flush clause. - Token FlushTok; - if (DKind == OMPD_flush) - FlushTok = Tok; + // Special processing for flush and depobj clauses. + Token ImplicitTok; + bool ImplicitClauseAllowed = false; + if (DKind == OMPD_flush || DKind == OMPD_depobj) { + ImplicitTok = Tok; + ImplicitClauseAllowed = true; + } ConsumeToken(); // Parse directive name of the 'critical' directive if any. if (DKind == OMPD_critical) { @@ -2156,22 +2161,32 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc); while (Tok.isNot(tok::annot_pragma_openmp_end)) { - bool FlushHasClause = false; - if (DKind == OMPD_flush && Tok.is(tok::l_paren)) { - FlushHasClause = true; + bool HasImplicitClause = false; + if (ImplicitClauseAllowed && Tok.is(tok::l_paren)) { + HasImplicitClause = true; // Push copy of the current token back to stream to properly parse - // pseudo-clause OMPFlushClause. + // pseudo-clause OMPFlushClause or OMPDepobjClause. PP.EnterToken(Tok, /*IsReinject*/ true); - PP.EnterToken(FlushTok, /*IsReinject*/ true); + PP.EnterToken(ImplicitTok, /*IsReinject*/ true); ConsumeAnyToken(); } - OpenMPClauseKind CKind = - Tok.isAnnotation() - ? OMPC_unknown - : FlushHasClause ? OMPC_flush - : getOpenMPClauseKind(PP.getSpelling(Tok)); + OpenMPClauseKind CKind = Tok.isAnnotation() + ? OMPC_unknown + : getOpenMPClauseKind(PP.getSpelling(Tok)); + if (HasImplicitClause) { + assert(CKind == OMPC_unknown && "Must be unknown implicit clause."); + if (DKind == OMPD_flush) { + CKind = OMPC_flush; + } else { + assert(DKind == OMPD_depobj && + "Expected flush or depobj directives."); + CKind = OMPC_depobj; + } + } + // No more implicit clauses allowed. + ImplicitClauseAllowed = false; Actions.StartOpenMPClause(CKind); - FlushHasClause = false; + HasImplicitClause = false; OMPClause *Clause = ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt()); FirstClauses[CKind].setInt(true); @@ -2324,7 +2339,8 @@ bool Parser::ParseOpenMPSimpleVarList( /// nogroup-clause | num_tasks-clause | hint-clause | to-clause | /// 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 +/// acq_rel-clause | acquire-clause | release-clause | relaxed-clause | +/// depobj-clause /// OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, bool FirstClause) { @@ -2355,6 +2371,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_num_tasks: case OMPC_hint: case OMPC_allocator: + case OMPC_depobj: // OpenMP [2.5, Restrictions] // At most one num_threads clause can appear on the directive. // OpenMP [2.8.1, simd construct, Restrictions] diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp index 193eaa3..1e892aa 100644 --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -1430,6 +1430,7 @@ CanThrowResult Sema::canThrow(const Stmt *S) { case Stmt::OMPDistributeParallelForSimdDirectiveClass: case Stmt::OMPDistributeSimdDirectiveClass: case Stmt::OMPFlushDirectiveClass: + case Stmt::OMPDepobjDirectiveClass: case Stmt::OMPForDirectiveClass: case Stmt::OMPForSimdDirectiveClass: case Stmt::OMPMasterDirectiveClass: diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index de73257..2555db4 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -266,6 +266,8 @@ private: SmallVector RequiresDecls; /// omp_allocator_handle_t type. QualType OMPAllocatorHandleT; + /// omp_depend_t type. + QualType OMPDependT; /// Expression for the predefined allocators. Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = { nullptr}; @@ -289,6 +291,10 @@ public: Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const { return OMPPredefinedAllocators[AllocatorKind]; } + /// Sets omp_depend_t type. + void setOMPDependT(QualType Ty) { OMPDependT = Ty; } + /// Gets omp_depend_t type. + QualType getOMPDependT() const { return OMPDependT; } bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; } OpenMPClauseKind getClauseParsingMode() const { @@ -3740,6 +3746,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { case OMPD_cancellation_point: case OMPD_cancel: case OMPD_flush: + case OMPD_depobj: case OMPD_declare_reduction: case OMPD_declare_mapper: case OMPD_declare_simd: @@ -4746,6 +4753,11 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( "No associated statement allowed for 'omp flush' directive"); Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc); break; + case OMPD_depobj: + assert(AStmt == nullptr && + "No associated statement allowed for 'omp depobj' directive"); + Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc); + break; case OMPD_ordered: Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); @@ -5032,6 +5044,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( continue; case OMPC_allocator: case OMPC_flush: + case OMPC_depobj: case OMPC_threadprivate: case OMPC_uniform: case OMPC_unknown: @@ -8597,6 +8610,28 @@ StmtResult Sema::ActOnOpenMPFlushDirective(ArrayRef Clauses, return OMPFlushDirective::Create(Context, StartLoc, EndLoc, Clauses); } +StmtResult Sema::ActOnOpenMPDepobjDirective(ArrayRef Clauses, + SourceLocation StartLoc, + SourceLocation EndLoc) { + if (Clauses.empty()) { + Diag(StartLoc, diag::err_omp_depobj_expected); + return StmtError(); + } else if (Clauses[0]->getClauseKind() != OMPC_depobj) { + Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected); + return StmtError(); + } + // Only depobj expression and another single clause is allowed. + if (Clauses.size() > 2) { + Diag(Clauses[2]->getBeginLoc(), + diag::err_omp_depobj_single_clause_expected); + return StmtError(); + } else if (Clauses.size() < 1) { + Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected); + return StmtError(); + } + return OMPDepobjDirective::Create(Context, StartLoc, EndLoc, Clauses); +} + StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, @@ -10890,6 +10925,9 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, case OMPC_hint: Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc); break; + case OMPC_depobj: + Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc); + break; case OMPC_if: case OMPC_default: case OMPC_proc_bind: @@ -11071,6 +11109,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_taskwait: case OMPD_cancellation_point: case OMPD_flush: + case OMPD_depobj: case OMPD_declare_reduction: case OMPD_declare_mapper: case OMPD_declare_simd: @@ -11141,6 +11180,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_taskwait: case OMPD_cancellation_point: case OMPD_flush: + case OMPD_depobj: case OMPD_declare_reduction: case OMPD_declare_mapper: case OMPD_declare_simd: @@ -11216,6 +11256,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_taskwait: case OMPD_cancellation_point: case OMPD_flush: + case OMPD_depobj: case OMPD_declare_reduction: case OMPD_declare_mapper: case OMPD_declare_simd: @@ -11288,6 +11329,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_taskwait: case OMPD_cancellation_point: case OMPD_flush: + case OMPD_depobj: case OMPD_declare_reduction: case OMPD_declare_mapper: case OMPD_declare_simd: @@ -11361,6 +11403,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_taskwait: case OMPD_cancellation_point: case OMPD_flush: + case OMPD_depobj: case OMPD_declare_reduction: case OMPD_declare_mapper: case OMPD_declare_simd: @@ -11433,6 +11476,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_taskwait: case OMPD_cancellation_point: case OMPD_flush: + case OMPD_depobj: case OMPD_declare_reduction: case OMPD_declare_mapper: case OMPD_declare_simd: @@ -11504,6 +11548,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_taskwait: case OMPD_cancellation_point: case OMPD_flush: + case OMPD_depobj: case OMPD_declare_reduction: case OMPD_declare_mapper: case OMPD_declare_simd: @@ -11578,6 +11623,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_taskwait: case OMPD_cancellation_point: case OMPD_flush: + case OMPD_depobj: case OMPD_declare_reduction: case OMPD_declare_mapper: case OMPD_declare_simd: @@ -11627,6 +11673,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPC_threadprivate: case OMPC_allocate: case OMPC_flush: + case OMPC_depobj: case OMPC_read: case OMPC_write: case OMPC_update: @@ -11933,7 +11980,8 @@ static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc, Stack->setAllocator(AllocatorKind, Res.get()); } if (ErrorFound) { - S.Diag(Loc, diag::err_implied_omp_allocator_handle_t_not_found); + S.Diag(Loc, diag::err_omp_implied_type_not_found) + << "omp_allocator_handle_t"; return false; } OMPAllocatorHandleT.addConst(); @@ -12052,6 +12100,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause( case OMPC_threadprivate: case OMPC_allocate: case OMPC_flush: + case OMPC_depobj: case OMPC_read: case OMPC_write: case OMPC_update: @@ -12248,6 +12297,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause( case OMPC_threadprivate: case OMPC_allocate: case OMPC_flush: + case OMPC_depobj: case OMPC_read: case OMPC_write: case OMPC_update: @@ -12487,6 +12537,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind, case OMPC_threadprivate: case OMPC_allocate: case OMPC_flush: + case OMPC_depobj: case OMPC_depend: case OMPC_device: case OMPC_map: @@ -12712,6 +12763,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause( Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc); break; case OMPC_if: + case OMPC_depobj: case OMPC_final: case OMPC_num_threads: case OMPC_safelen: @@ -15120,6 +15172,49 @@ OMPClause *Sema::ActOnOpenMPFlushClause(ArrayRef VarList, return OMPFlushClause::Create(Context, StartLoc, LParenLoc, EndLoc, VarList); } +/// Tries to find omp_depend_t. type. +static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) { + QualType OMPDependT = Stack->getOMPDependT(); + if (!OMPDependT.isNull()) + return true; + IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t"); + ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope()); + if (!PT.getAsOpaquePtr() || PT.get().isNull()) { + S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t"; + return false; + } + Stack->setOMPDependT(PT.get()); + return true; +} + +OMPClause *Sema::ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + if (!Depobj) + return nullptr; + + bool OMPDependTFound = findOMPDependT(*this, StartLoc, DSAStack); + + // OpenMP 5.0, 2.17.10.1 depobj Construct + // depobj is an lvalue expression of type omp_depend_t. + if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() && + !Depobj->isInstantiationDependent() && + !Depobj->containsUnexpandedParameterPack() && + (OMPDependTFound && + !Context.typesAreCompatible(DSAStack->getOMPDependT(), Depobj->getType(), + /*CompareUnqualified=*/true))) { + Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue) + << 0 << Depobj->getType() << Depobj->getSourceRange(); + } + + if (!Depobj->isLValue()) { + Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue) + << 1 << Depobj->getSourceRange(); + } + + return OMPDepobjClause::Create(Context, StartLoc, LParenLoc, EndLoc, Depobj); +} + OMPClause * Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, SourceLocation DepLoc, SourceLocation ColonLoc, diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 6ad1c61..e42404d 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -1811,6 +1811,17 @@ public: EndLoc); } + /// Build a new OpenMP 'depobj' pseudo clause. + /// + /// By default, performs semantic analysis to build the new OpenMP clause. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPDepobjClause(Expr *Depobj, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPDepobjClause(Depobj, StartLoc, LParenLoc, + EndLoc); + } + /// Build a new OpenMP 'depend' pseudo clause. /// /// By default, performs semantic analysis to build the new OpenMP clause. @@ -8265,6 +8276,17 @@ TreeTransform::TransformOMPFlushDirective(OMPFlushDirective *D) { template StmtResult +TreeTransform::TransformOMPDepobjDirective(OMPDepobjDirective *D) { + DeclarationNameInfo DirName; + getDerived().getSema().StartOpenMPDSABlock(OMPD_depobj, DirName, nullptr, + D->getBeginLoc()); + StmtResult Res = getDerived().TransformOMPExecutableDirective(D); + getDerived().getSema().EndOpenMPDSABlock(Res.get()); + return Res; +} + +template +StmtResult TreeTransform::TransformOMPOrderedDirective(OMPOrderedDirective *D) { DeclarationNameInfo DirName; getDerived().getSema().StartOpenMPDSABlock(OMPD_ordered, DirName, nullptr, @@ -9166,6 +9188,16 @@ OMPClause *TreeTransform::TransformOMPFlushClause(OMPFlushClause *C) { template OMPClause * +TreeTransform::TransformOMPDepobjClause(OMPDepobjClause *C) { + ExprResult E = getDerived().TransformExpr(C->getDepobj()); + if (E.isInvalid()) + return nullptr; + return getDerived().RebuildOMPDepobjClause(E.get(), C->getBeginLoc(), + C->getLParenLoc(), C->getEndLoc()); +} + +template +OMPClause * TreeTransform::TransformOMPDependClause(OMPDependClause *C) { llvm::SmallVector Vars; Vars.reserve(C->varlist_size()); diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index a74ccc9..3a8b32c 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -11737,6 +11737,9 @@ OMPClause *OMPClauseReader::readClause() { case OMPC_flush: C = OMPFlushClause::CreateEmpty(Context, Record.readInt()); break; + case OMPC_depobj: + C = OMPDepobjClause::CreateEmpty(Context); + break; case OMPC_depend: { unsigned NumVars = Record.readInt(); unsigned NumLoops = Record.readInt(); @@ -12249,6 +12252,11 @@ void OMPClauseReader::VisitOMPFlushClause(OMPFlushClause *C) { C->setVarRefs(Vars); } +void OMPClauseReader::VisitOMPDepobjClause(OMPDepobjClause *C) { + C->setDepobj(Record.readSubExpr()); + C->setLParenLoc(Record.readSourceLocation()); +} + void OMPClauseReader::VisitOMPDependClause(OMPDependClause *C) { C->setLParenLoc(Record.readSourceLocation()); C->setDependencyKind( diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 3da7a71..fc83dc42 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -2343,6 +2343,13 @@ void ASTStmtReader::VisitOMPFlushDirective(OMPFlushDirective *D) { VisitOMPExecutableDirective(D); } +void ASTStmtReader::VisitOMPDepobjDirective(OMPDepobjDirective *D) { + VisitStmt(D); + // The NumClauses field was read in ReadStmtFromStream. + Record.skipInts(1); + VisitOMPExecutableDirective(D); +} + void ASTStmtReader::VisitOMPOrderedDirective(OMPOrderedDirective *D) { VisitStmt(D); // The NumClauses field was read in ReadStmtFromStream. @@ -3174,6 +3181,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { Context, Record[ASTStmtReader::NumStmtFields], Empty); break; + case STMT_OMP_DEPOBJ_DIRECTIVE: + S = OMPDepobjDirective::CreateEmpty( + Context, Record[ASTStmtReader::NumStmtFields], Empty); + break; + case STMT_OMP_ORDERED_DIRECTIVE: S = OMPOrderedDirective::CreateEmpty( Context, Record[ASTStmtReader::NumStmtFields], Empty); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 6f77d4f..fcc0b98 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -6342,6 +6342,11 @@ void OMPClauseWriter::VisitOMPFlushClause(OMPFlushClause *C) { Record.AddStmt(VE); } +void OMPClauseWriter::VisitOMPDepobjClause(OMPDepobjClause *C) { + Record.AddStmt(C->getDepobj()); + Record.AddSourceLocation(C->getLParenLoc()); +} + void OMPClauseWriter::VisitOMPDependClause(OMPDependClause *C) { Record.push_back(C->varlist_size()); Record.push_back(C->getNumLoops()); diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 9b6e869..d2b1fc2 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -2314,6 +2314,13 @@ void ASTStmtWriter::VisitOMPFlushDirective(OMPFlushDirective *D) { Code = serialization::STMT_OMP_FLUSH_DIRECTIVE; } +void ASTStmtWriter::VisitOMPDepobjDirective(OMPDepobjDirective *D) { + VisitStmt(D); + Record.push_back(D->getNumClauses()); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_DEPOBJ_DIRECTIVE; +} + void ASTStmtWriter::VisitOMPOrderedDirective(OMPOrderedDirective *D) { VisitStmt(D); Record.push_back(D->getNumClauses()); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 801b30a..1b13c49 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1257,6 +1257,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::OMPTaskwaitDirectiveClass: case Stmt::OMPTaskgroupDirectiveClass: case Stmt::OMPFlushDirectiveClass: + case Stmt::OMPDepobjDirectiveClass: case Stmt::OMPOrderedDirectiveClass: case Stmt::OMPAtomicDirectiveClass: case Stmt::OMPTargetDirectiveClass: diff --git a/clang/test/OpenMP/allocate_allocator_messages.cpp b/clang/test/OpenMP/allocate_allocator_messages.cpp index 0c4d36f..3ab735a 100644 --- a/clang/test/OpenMP/allocate_allocator_messages.cpp +++ b/clang/test/OpenMP/allocate_allocator_messages.cpp @@ -10,10 +10,10 @@ int sss; #pragma omp allocate(sss) allocat // expected-warning {{extra tokens at the end of '#pragma omp allocate' are ignored}} #pragma omp allocate(sss) allocate(sss) // expected-error {{unexpected OpenMP clause 'allocate' in directive '#pragma omp allocate'}} #pragma omp allocate(sss) allocator // expected-error {{expected '(' after 'allocator'}} -#pragma omp allocate(sss) allocator(0, // expected-error {{expected ')'}} expected-error {{omp_allocator_handle_t type not found; include }} expected-note {{to match this '('}} -#pragma omp allocate(sss) allocator(0,sss // expected-error {{expected ')'}} expected-error {{omp_allocator_handle_t type not found; include }} expected-note {{to match this '('}} -#pragma omp allocate(sss) allocator(0,sss) // expected-error {{expected ')'}} expected-error {{omp_allocator_handle_t type not found; include }} expected-note {{to match this '('}} -#pragma omp allocate(sss) allocator(sss) // expected-error {{omp_allocator_handle_t type not found; include }} +#pragma omp allocate(sss) allocator(0, // expected-error {{expected ')'}} expected-error {{'omp_allocator_handle_t' type not found; include }} expected-note {{to match this '('}} +#pragma omp allocate(sss) allocator(0,sss // expected-error {{expected ')'}} expected-error {{'omp_allocator_handle_t' type not found; include }} expected-note {{to match this '('}} +#pragma omp allocate(sss) allocator(0,sss) // expected-error {{expected ')'}} expected-error {{'omp_allocator_handle_t' type not found; include }} expected-note {{to match this '('}} +#pragma omp allocate(sss) allocator(sss) // expected-error {{'omp_allocator_handle_t' type not found; include }} typedef void **omp_allocator_handle_t; extern const omp_allocator_handle_t omp_default_mem_alloc; diff --git a/clang/test/OpenMP/depobj_ast_print.cpp b/clang/test/OpenMP/depobj_ast_print.cpp new file mode 100644 index 0000000..5d85cec --- /dev/null +++ b/clang/test/OpenMP/depobj_ast_print.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s + +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER + +typedef void *omp_depend_t; + +void foo() {} + +template +T tmain(T argc) { + static T a; +#pragma omp depobj(a) depend(in:argc) + return argc; +} +// CHECK: static T a; +// CHECK-NEXT: #pragma omp depobj (a) depend(in : argc){{$}} +// CHECK: static void *a; +// CHECK-NEXT: #pragma omp depobj (a) depend(in : argc){{$}} + +int main(int argc, char **argv) { + static omp_depend_t a; + omp_depend_t b; +// CHECK: static omp_depend_t a; +// CHECK-NEXT: omp_depend_t b; +#pragma omp depobj(a) depend(out:argc, argv) +// CHECK-NEXT: #pragma omp depobj (a) depend(out : argc,argv) + (void)tmain(a), tmain(b); + return 0; +} + +#endif diff --git a/clang/test/OpenMP/depobj_messages.cpp b/clang/test/OpenMP/depobj_messages.cpp new file mode 100644 index 0000000..87b619c --- /dev/null +++ b/clang/test/OpenMP/depobj_messages.cpp @@ -0,0 +1,151 @@ +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 -ferror-limit 100 %s -Wuninitialized + +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 -ferror-limit 100 %s -Wuninitialized + +struct S1 { // expected-note 2 {{declared here}} + int a; +} s; + +#pragma omp depobj(0) depend(in:s) // expected-error {{unexpected OpenMP directive '#pragma omp depobj'}} +void foo() { +#pragma omp depobj(0) depend(in:s) // expected-error {{'omp_depend_t' type not found; include }} expected-error {{expected lvalue expression}}} +} + +typedef void *omp_depend_t; + +template +T tmain(T argc) { + omp_depend_t x; +#pragma omp depobj() allocate(argc) // expected-error {{expected expression}} expected-error {{expected depobj expression}} expected-error {{unexpected OpenMP clause 'allocate' in directive '#pragma omp depobj'}} + ; +#pragma omp depobj(x) untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp depobj'}} +#pragma omp depobj(x) unknown // expected-warning {{extra tokens at the end of '#pragma omp depobj' are ignored}} + if (argc) +#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}} + if (argc) { +#pragma omp depobj(x) depend(in:s) + } + while (argc) +#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}} + while (argc) { +#pragma omp depobj(x) depend(in:s) + } + do +#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}} + while (argc) + ; + do { +#pragma omp depobj(x) depend(in:s) + } while (argc); + switch (argc) +#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}} + switch (argc) + case 1: +#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}} + switch (argc) + case 1: { +#pragma omp depobj(x) depend(in:s) + } + switch (argc) { +#pragma omp depobj(x) depend(in:s) + case 1: +#pragma omp depobj(x) depend(in:s) + break; + default: { +#pragma omp depobj(x) depend(in:s) + } break; + } + for (;;) +#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}} + for (;;) { +#pragma omp depobj(x) depend(in:s) + } +label: +#pragma omp depobj(x) depend(in:s) +label1 : { +#pragma omp depobj(x) depend(in:s) +} + +#pragma omp depobj // expected-error {{expected depobj expression}} +#pragma omp depobj( // expected-error {{expected expression}} expected-error {{expected depobj expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} +#pragma omp depobj() // expected-error {{expected expression}} expected-error {{expected depobj expression}} +#pragma omp depobj(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected lvalue expression of 'omp_depend_t' type, not 'int'}}} +#pragma omp depobj(argc, // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected lvalue expression of 'omp_depend_t' type, not 'int'}} +#pragma omp depobj(argc) // expected-error {{expected lvalue expression of 'omp_depend_t' type, not 'int'}} +#pragma omp depobj(S1) // expected-error {{'S1' does not refer to a value}} expected-error {{expected depobj expression}} +#pragma omp depobj(argc) depobj(argc) // expected-warning {{extra tokens at the end of '#pragma omp depobj' are ignored}} expected-error {{expected lvalue expression of 'omp_depend_t' type, not 'int'}}} +#pragma omp parallel depobj(argc) // expected-warning {{extra tokens at the end of '#pragma omp parallel' are ignored}} + ; + return T(); +} + +int main(int argc, char **argv) { +omp_depend_t x; +#pragma omp depobj(x) depend(in:s) + ; +#pragma omp depobj(x) untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp depobj'}} +#pragma omp depobj(x) unknown // expected-warning {{extra tokens at the end of '#pragma omp depobj' are ignored}} + if (argc) +#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}} + if (argc) { +#pragma omp depobj(x) depend(in:s) + } + while (argc) +#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}} + while (argc) { +#pragma omp depobj(x) depend(in:s) + } + do +#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}} + while (argc) + ; + do { +#pragma omp depobj(x) depend(in:s) + } while (argc); + switch (argc) +#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}} + switch (argc) + case 1: +#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}} + switch (argc) + case 1: { +#pragma omp depobj(x) depend(in:s) + } + switch (argc) { +#pragma omp depobj(x) depend(in:s) + case 1: +#pragma omp depobj(x) depend(in:s) + break; + default: { +#pragma omp depobj(x) depend(in:s) + } break; + } + for (;;) +#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}} + for (;;) { +#pragma omp depobj(x) depend(in:s) + } +label: +#pragma omp depobj(x) depend(in:s) +label1 : { +#pragma omp depobj(x) depend(in:s) +} + +#pragma omp depobj // expected-error {{expected depobj expression}} +#pragma omp depobj( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected depobj expression}} +#pragma omp depobj() // expected-error {{expected expression}} expected-error {{expected depobj expression}} +#pragma omp depobj(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected lvalue expression of 'omp_depend_t' type, not 'int'}} +#pragma omp depobj(argc, // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected lvalue expression of 'omp_depend_t' type, not 'int'}} +#pragma omp depobj(argc) // expected-error {{expected lvalue expression of 'omp_depend_t' type, not 'int'}} +#pragma omp depobj(S1) // expected-error {{'S1' does not refer to a value}} expected-error {{expected depobj expression}} +#pragma omp depobj(argc) depobj(argc) // expected-warning {{extra tokens at the end of '#pragma omp depobj' are ignored}} expected-error {{expected lvalue expression of 'omp_depend_t' type, not 'int'}} +#pragma omp parallel depobj(argc) // expected-warning {{extra tokens at the end of '#pragma omp parallel' are ignored}} + ; +#pragma omp depobj(x) seq_cst // expected-error {{unexpected OpenMP clause 'seq_cst' in directive '#pragma omp depobj'}} +#pragma omp depobj(x) depend(in: x) +#pragma omp depobj(x) (x) depend(in: x) // expected-warning {{extra tokens at the end of '#pragma omp depobj' are ignored}} +#pragma omp depobj(x) depend(in: x) depend(out:x) // expected-error {{exactly one of 'depend', 'destroy', or 'update' clauses is expected}} +#pragma omp depend(out:x) depobj(x) // expected-error {{expected an OpenMP directive}} +#pragma omp depobj depend(in:x) (x) // expected-error {{expected depobj expression}} expected-warning {{extra tokens at the end of '#pragma omp depobj' are ignored}} + return tmain(argc); // expected-note {{in instantiation of function template specialization 'tmain' requested here}} +} diff --git a/clang/test/OpenMP/flush_messages.cpp b/clang/test/OpenMP/flush_messages.cpp index 5149724..7d20e38 100644 --- a/clang/test/OpenMP/flush_messages.cpp +++ b/clang/test/OpenMP/flush_messages.cpp @@ -142,7 +142,7 @@ label1 : { #pragma omp flush seq_cst // expected-error {{unexpected OpenMP clause 'seq_cst' in directive '#pragma omp flush'}} #pragma omp flush acq_rel acquire // omp45-error {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp flush'}} omp45-error {{unexpected OpenMP clause 'acquire' in directive '#pragma omp flush'}} omp50-error {{directive '#pragma omp flush' cannot contain more than one 'acq_rel', 'acquire' or 'release' clause}} omp50-note {{'acq_rel' clause used here}} #pragma omp flush release acquire // omp45-error {{unexpected OpenMP clause 'release' in directive '#pragma omp flush'}} omp45-error {{unexpected OpenMP clause 'acquire' in directive '#pragma omp flush'}} omp50-error {{directive '#pragma omp flush' cannot contain more than one 'acq_rel', 'acquire' or 'release' clause}} omp50-note {{'release' clause used here}} -#pragma omp flush acq_rel (argc) // omp45-error {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp flush'}} omp50-error {{'flush' directive with memory order clause 'acq_rel' cannot have the list}} omp50-note {{memory order clause 'acq_rel' is specified here}} +#pragma omp flush acq_rel (argc) // omp45-error {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp flush'}} expected-warning {{extra tokens at the end of '#pragma omp flush' are ignored}} #pragma omp flush(argc) acq_rel // omp45-error {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp flush'}} omp50-error {{'flush' directive with memory order clause 'acq_rel' cannot have the list}} omp50-note {{memory order clause 'acq_rel' is specified here}} return tmain(argc); } diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 6f32240..5445ab2 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -2047,6 +2047,7 @@ public: VisitOMPCancellationPointDirective(const OMPCancellationPointDirective *D); void VisitOMPCancelDirective(const OMPCancelDirective *D); void VisitOMPFlushDirective(const OMPFlushDirective *D); + void VisitOMPDepobjDirective(const OMPDepobjDirective *D); void VisitOMPOrderedDirective(const OMPOrderedDirective *D); void VisitOMPAtomicDirective(const OMPAtomicDirective *D); void VisitOMPTargetDirective(const OMPTargetDirective *D); @@ -2444,6 +2445,9 @@ OMPClauseEnqueue::VisitOMPCopyprivateClause(const OMPCopyprivateClause *C) { void OMPClauseEnqueue::VisitOMPFlushClause(const OMPFlushClause *C) { VisitOMPClauseList(C); } +void OMPClauseEnqueue::VisitOMPDepobjClause(const OMPDepobjClause *C) { + Visitor->AddStmt(C->getDepobj()); +} void OMPClauseEnqueue::VisitOMPDependClause(const OMPDependClause *C) { VisitOMPClauseList(C); } @@ -2871,6 +2875,10 @@ void EnqueueVisitor::VisitOMPFlushDirective(const OMPFlushDirective *D) { VisitOMPExecutableDirective(D); } +void EnqueueVisitor::VisitOMPDepobjDirective(const OMPDepobjDirective *D) { + VisitOMPExecutableDirective(D); +} + void EnqueueVisitor::VisitOMPOrderedDirective(const OMPOrderedDirective *D) { VisitOMPExecutableDirective(D); } @@ -2883,8 +2891,8 @@ void EnqueueVisitor::VisitOMPTargetDirective(const OMPTargetDirective *D) { VisitOMPExecutableDirective(D); } -void EnqueueVisitor::VisitOMPTargetDataDirective(const - OMPTargetDataDirective *D) { +void EnqueueVisitor::VisitOMPTargetDataDirective( + const OMPTargetDataDirective *D) { VisitOMPExecutableDirective(D); } @@ -5503,6 +5511,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return cxstring::createRef("OMPTaskgroupDirective"); case CXCursor_OMPFlushDirective: return cxstring::createRef("OMPFlushDirective"); + case CXCursor_OMPDepobjDirective: + return cxstring::createRef("OMPDepobjDirective"); case CXCursor_OMPOrderedDirective: return cxstring::createRef("OMPOrderedDirective"); case CXCursor_OMPAtomicDirective: diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index 04b713c..e10c742 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -635,6 +635,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent, case Stmt::OMPFlushDirectiveClass: K = CXCursor_OMPFlushDirective; break; + case Stmt::OMPDepobjDirectiveClass: + K = CXCursor_OMPDepobjDirective; + break; case Stmt::OMPOrderedDirectiveClass: K = CXCursor_OMPOrderedDirective; break; diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def index 84f4ae7..20e5b95 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def +++ b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def @@ -91,6 +91,7 @@ __OMP_DIRECTIVE_EXT(parallel_master_taskloop, "parallel master taskloop") __OMP_DIRECTIVE_EXT(master_taskloop_simd, "master taskloop simd") __OMP_DIRECTIVE_EXT(parallel_master_taskloop_simd, "parallel master taskloop simd") +__OMP_DIRECTIVE(depobj) // Has to be the last because Clang implicitly expects it to be. __OMP_DIRECTIVE(unknown) @@ -130,7 +131,7 @@ __OMP_TYPE(Int32Ptr) #define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) #endif -#define __OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \ +#define __OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \ OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) __OMP_ARRAY_TYPE(KmpCriticalName, Int32, 8) -- 2.7.4