From 9cc10fc926526139559a88d1ac2b13f563cba7f3 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Tue, 12 Mar 2019 18:52:33 +0000 Subject: [PATCH] [OPENMP 5.0]Initial support for 'allocator' clause. Added parsing/sema analysis/serialization/deserialization for the 'allocator' clause of the 'allocate' directive. llvm-svn: 355952 --- clang/include/clang/AST/ASTNodeTraverser.h | 2 + clang/include/clang/AST/DeclOpenMP.h | 52 +++++++++++- clang/include/clang/AST/OpenMPClause.h | 52 ++++++++++++ clang/include/clang/AST/RecursiveASTVisitor.h | 12 ++- clang/include/clang/Basic/Attr.td | 1 + clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 + clang/include/clang/Basic/OpenMPKinds.def | 8 ++ clang/include/clang/Sema/Sema.h | 8 ++ clang/lib/AST/DeclOpenMP.cpp | 27 ++++-- clang/lib/AST/DeclPrinter.cpp | 6 ++ clang/lib/AST/OpenMPClause.cpp | 8 ++ clang/lib/AST/StmtProfile.cpp | 5 ++ clang/lib/Basic/OpenMPKinds.cpp | 13 ++- clang/lib/CodeGen/CGStmtOpenMP.cpp | 1 + clang/lib/Parse/ParseOpenMP.cpp | 98 ++++++++++++++++++---- clang/lib/Sema/SemaOpenMP.cpp | 66 +++++++++++++-- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 15 +++- clang/lib/Sema/TreeTransform.h | 20 +++++ clang/lib/Serialization/ASTReader.cpp | 8 ++ clang/lib/Serialization/ASTReaderDecl.cpp | 18 +++- clang/lib/Serialization/ASTWriter.cpp | 6 ++ clang/lib/Serialization/ASTWriterDecl.cpp | 4 + clang/test/OpenMP/allocate_allocator_ast_print.cpp | 89 ++++++++++++++++++++ clang/test/OpenMP/allocate_allocator_messages.cpp | 27 ++++++ clang/test/PCH/chain-openmp-allocate.cpp | 7 +- clang/tools/libclang/CIndex.cpp | 4 + 26 files changed, 512 insertions(+), 47 deletions(-) create mode 100644 clang/test/OpenMP/allocate_allocator_ast_print.cpp create mode 100644 clang/test/OpenMP/allocate_allocator_messages.cpp diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index f5b48be..6268df8 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -396,6 +396,8 @@ public: void VisitOMPAllocateDecl(const OMPAllocateDecl *D) { for (const auto *E : D->varlists()) Visit(E); + for (const auto *C : D->clauselists()) + Visit(C); } template diff --git a/clang/include/clang/AST/DeclOpenMP.h b/clang/include/clang/AST/DeclOpenMP.h index 92690f5..437feab 100644 --- a/clang/include/clang/AST/DeclOpenMP.h +++ b/clang/include/clang/AST/DeclOpenMP.h @@ -421,12 +421,21 @@ public: /// class OMPAllocateDecl final : public Decl, - private llvm::TrailingObjects { + private llvm::TrailingObjects { friend class ASTDeclReader; friend TrailingObjects; /// Number of variable within the allocate directive. unsigned NumVars = 0; + /// Number of clauses associated with the allocate directive. + unsigned NumClauses = 0; + + size_t numTrailingObjects(OverloadToken) const { + return NumVars; + } + size_t numTrailingObjects(OverloadToken) const { + return NumClauses; + } virtual void anchor(); @@ -443,19 +452,41 @@ class OMPAllocateDecl final void setVars(ArrayRef VL); + /// Returns an array of immutable clauses associated with this directive. + ArrayRef getClauses() const { + return llvm::makeArrayRef(getTrailingObjects(), NumClauses); + } + + /// Returns an array of clauses associated with this directive. + MutableArrayRef getClauses() { + return MutableArrayRef(getTrailingObjects(), + NumClauses); + } + + /// Sets an array of clauses to this requires declaration + void setClauses(ArrayRef CL); + public: static OMPAllocateDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, ArrayRef VL); + SourceLocation L, ArrayRef VL, + ArrayRef CL); static OMPAllocateDecl *CreateDeserialized(ASTContext &C, unsigned ID, - unsigned N); + unsigned NVars, unsigned NClauses); typedef MutableArrayRef::iterator varlist_iterator; typedef ArrayRef::iterator varlist_const_iterator; typedef llvm::iterator_range varlist_range; typedef llvm::iterator_range varlist_const_range; + using clauselist_iterator = MutableArrayRef::iterator; + using clauselist_const_iterator = ArrayRef::iterator; + using clauselist_range = llvm::iterator_range; + using clauselist_const_range = llvm::iterator_range; + unsigned varlist_size() const { return NumVars; } bool varlist_empty() const { return NumVars == 0; } + unsigned clauselist_size() const { return NumClauses; } + bool clauselist_empty() const { return NumClauses == 0; } varlist_range varlists() { return varlist_range(varlist_begin(), varlist_end()); @@ -468,6 +499,21 @@ public: varlist_const_iterator varlist_begin() const { return getVars().begin(); } varlist_const_iterator varlist_end() const { return getVars().end(); } + clauselist_range clauselists() { + return clauselist_range(clauselist_begin(), clauselist_end()); + } + clauselist_const_range clauselists() const { + return clauselist_const_range(clauselist_begin(), clauselist_end()); + } + clauselist_iterator clauselist_begin() { return getClauses().begin(); } + clauselist_iterator clauselist_end() { return getClauses().end(); } + clauselist_const_iterator clauselist_begin() const { + return getClauses().begin(); + } + clauselist_const_iterator clauselist_end() const { + return getClauses().end(); + } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == OMPAllocate; } }; diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h index 746a24f..3d5ccdf 100644 --- a/clang/include/clang/AST/OpenMPClause.h +++ b/clang/include/clang/AST/OpenMPClause.h @@ -243,6 +243,58 @@ public: } }; +/// This represents 'allocator' clause in the '#pragma omp ...' +/// directive. +/// +/// \code +/// #pragma omp allocate(a) allocator(omp_default_mem_alloc) +/// \endcode +/// In this example directive '#pragma omp allocate' has simple 'allocator' +/// clause with the allocator 'omp_default_mem_alloc'. +class OMPAllocatorClause : public OMPClause { + friend class OMPClauseReader; + + /// Location of '('. + SourceLocation LParenLoc; + + /// Expression with the allocator. + Stmt *Allocator = nullptr; + + /// Set allocator. + void setAllocator(Expr *A) { Allocator = A; } + +public: + /// Build 'allocator' clause with the given allocator. + /// + /// \param A Allocator. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + OMPAllocatorClause(Expr *A, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : OMPClause(OMPC_allocator, StartLoc, EndLoc), LParenLoc(LParenLoc), + Allocator(A) {} + + /// Build an empty clause. + OMPAllocatorClause() + : OMPClause(OMPC_allocator, SourceLocation(), SourceLocation()) {} + + /// Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + + /// Returns the location of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// Returns allocator. + Expr *getAllocator() const { return cast_or_null(Allocator); } + + child_range children() { return child_range(&Allocator, &Allocator + 1); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_allocator; + } +}; + /// This represents 'if' clause in the '#pragma omp ...' directive. /// /// \code diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index a5098d8..2bfebcb 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -1614,9 +1614,10 @@ DEF_TRAVERSE_DECL(OMPDeclareMapperDecl, { DEF_TRAVERSE_DECL(OMPCapturedExprDecl, { TRY_TO(TraverseVarHelper(D)); }) DEF_TRAVERSE_DECL(OMPAllocateDecl, { - for (auto *I : D->varlists()) { + for (auto *I : D->varlists()) TRY_TO(TraverseStmt(I)); - } + for (auto *C : D->clauselists()) + TRY_TO(TraverseOMPClause(C)); }) // A helper method for TemplateDecl's children. @@ -2827,6 +2828,13 @@ bool RecursiveASTVisitor::VisitOMPClauseWithPostUpdate( } template +bool RecursiveASTVisitor::VisitOMPAllocatorClause( + OMPAllocatorClause *C) { + TRY_TO(TraverseStmt(C->getAllocator())); + return true; +} + +template bool RecursiveASTVisitor::VisitOMPIfClause(OMPIfClause *C) { TRY_TO(VisitOMPClauseWithPreInit(C)); TRY_TO(TraverseStmt(C->getCondition())); diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 523b89d..379e2f5 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3156,6 +3156,7 @@ def OMPAllocateDecl : InheritableAttr { // This attribute has no spellings as it is only ever created implicitly. let Spellings = []; let SemaHandler = 0; + let Args = [ExprArgument<"Allocator">]; let Documentation = [Undocumented]; } diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 5e6eacc..aaa041d 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9135,6 +9135,8 @@ 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 ">; } // end of OpenMP category let CategoryName = "Related Result Type Issue" in { diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def index 2237bd7..914eee0 100644 --- a/clang/include/clang/Basic/OpenMPKinds.def +++ b/clang/include/clang/Basic/OpenMPKinds.def @@ -188,6 +188,9 @@ #ifndef OPENMP_DECLARE_MAPPER_CLAUSE #define OPENMP_DECLARE_MAPPER_CLAUSE(Name) #endif +#ifndef OPENMP_ALLOCATE_CLAUSE +# define OPENMP_ALLOCATE_CLAUSE(Name) +#endif // OpenMP directives. OPENMP_DIRECTIVE(threadprivate) @@ -247,6 +250,7 @@ OPENMP_DIRECTIVE_EXT(target_teams_distribute_simd, "target teams distribute simd OPENMP_DIRECTIVE(allocate) // OpenMP clauses. +OPENMP_CLAUSE(allocator, OMPAllocatorClause) OPENMP_CLAUSE(if, OMPIfClause) OPENMP_CLAUSE(final, OMPFinalClause) OPENMP_CLAUSE(num_threads, OMPNumThreadsClause) @@ -489,6 +493,9 @@ OPENMP_REQUIRES_CLAUSE(reverse_offload) OPENMP_REQUIRES_CLAUSE(dynamic_allocators) OPENMP_REQUIRES_CLAUSE(atomic_default_mem_order) +// Clauses allowed for OpenMP directive 'allocate'. +OPENMP_ALLOCATE_CLAUSE(allocator) + // Modifiers for 'atomic_default_mem_order' clause. OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND(seq_cst) OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND(acq_rel) @@ -910,6 +917,7 @@ OPENMP_TASKGROUP_CLAUSE(task_reduction) // Clauses allowed for OpenMP directive 'declare mapper'. OPENMP_DECLARE_MAPPER_CLAUSE(map) +#undef OPENMP_ALLOCATE_CLAUSE #undef OPENMP_DECLARE_MAPPER_CLAUSE #undef OPENMP_TASKGROUP_CLAUSE #undef OPENMP_TASKLOOP_SIMD_CLAUSE diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 5ead2c0..b32f1bb 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -8781,6 +8781,8 @@ public: // private: void *VarDataSharingAttributesStack; + /// omp_allocator_handle_t type. + QualType OMPAllocatorHandleT; /// Number of nested '#pragma omp declare target' directives. unsigned DeclareTargetNestingLevel = 0; /// Initialization of data-sharing attributes stack. @@ -8892,6 +8894,7 @@ public: /// Called on well-formed '#pragma omp allocate'. DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef VarList, + ArrayRef Clauses, DeclContext *Owner = nullptr); /// Called on well-formed '#pragma omp requires'. DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc, @@ -9247,6 +9250,11 @@ public: SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); + /// Called on well-formed 'allocator' clause. + OMPClause *ActOnOpenMPAllocatorClause(Expr *Allocator, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); /// Called on well-formed 'if' clause. OMPClause *ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc, diff --git a/clang/lib/AST/DeclOpenMP.cpp b/clang/lib/AST/DeclOpenMP.cpp index f50775b..af32128 100644 --- a/clang/lib/AST/DeclOpenMP.cpp +++ b/clang/lib/AST/DeclOpenMP.cpp @@ -59,20 +59,26 @@ void OMPThreadPrivateDecl::setVars(ArrayRef VL) { void OMPAllocateDecl::anchor() { } OMPAllocateDecl *OMPAllocateDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation L, - ArrayRef VL) { - OMPAllocateDecl *D = new (C, DC, additionalSizeToAlloc(VL.size())) + SourceLocation L, ArrayRef VL, + ArrayRef CL) { + OMPAllocateDecl *D = new ( + C, DC, additionalSizeToAlloc(VL.size(), CL.size())) OMPAllocateDecl(OMPAllocate, DC, L); D->NumVars = VL.size(); D->setVars(VL); + D->NumClauses = CL.size(); + D->setClauses(CL); return D; } OMPAllocateDecl *OMPAllocateDecl::CreateDeserialized(ASTContext &C, unsigned ID, - unsigned N) { - OMPAllocateDecl *D = new (C, ID, additionalSizeToAlloc(N)) - OMPAllocateDecl(OMPAllocate, nullptr, SourceLocation()); - D->NumVars = N; + unsigned NVars, + unsigned NClauses) { + OMPAllocateDecl *D = + new (C, ID, additionalSizeToAlloc(NVars, NClauses)) + OMPAllocateDecl(OMPAllocate, nullptr, SourceLocation()); + D->NumVars = NVars; + D->NumClauses = NClauses; return D; } @@ -82,6 +88,13 @@ void OMPAllocateDecl::setVars(ArrayRef VL) { std::uninitialized_copy(VL.begin(), VL.end(), getTrailingObjects()); } +void OMPAllocateDecl::setClauses(ArrayRef CL) { + assert(CL.size() == NumClauses && + "Number of variables is not the same as the preallocated buffer"); + std::uninitialized_copy(CL.begin(), CL.end(), + getTrailingObjects()); +} + //===----------------------------------------------------------------------===// // OMPRequiresDecl Implementation. //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index d023a03..2009673 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -1560,6 +1560,12 @@ void DeclPrinter::VisitOMPAllocateDecl(OMPAllocateDecl *D) { } Out << ")"; } + if (!D->clauselist_empty()) { + Out << " "; + OMPClausePrinter Printer(Out, Policy); + for (OMPClause *C : D->clauselists()) + Printer.Visit(C); + } } void DeclPrinter::VisitOMPRequiresDecl(OMPRequiresDecl *D) { diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp index 4016dd0..5ee10fb 100644 --- a/clang/lib/AST/OpenMPClause.cpp +++ b/clang/lib/AST/OpenMPClause.cpp @@ -73,6 +73,7 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) { case OMPC_final: case OMPC_safelen: case OMPC_simdlen: + case OMPC_allocator: case OMPC_collapse: case OMPC_private: case OMPC_shared: @@ -145,6 +146,7 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C) case OMPC_num_threads: case OMPC_safelen: case OMPC_simdlen: + case OMPC_allocator: case OMPC_collapse: case OMPC_private: case OMPC_shared: @@ -1086,6 +1088,12 @@ void OMPClausePrinter::VisitOMPSimdlenClause(OMPSimdlenClause *Node) { OS << ")"; } +void OMPClausePrinter::VisitOMPAllocatorClause(OMPAllocatorClause *Node) { + OS << "allocator("; + Node->getAllocator()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + void OMPClausePrinter::VisitOMPCollapseClause(OMPCollapseClause *Node) { OS << "collapse("; Node->getNumForLoops()->printPretty(OS, nullptr, Policy, 0); diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index c064ea90a..53655a1 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -457,6 +457,11 @@ void OMPClauseProfiler::VisitOMPSimdlenClause(const OMPSimdlenClause *C) { Profiler->VisitStmt(C->getSimdlen()); } +void OMPClauseProfiler::VisitOMPAllocatorClause(const OMPAllocatorClause *C) { + if (C->getAllocator()) + Profiler->VisitStmt(C->getAllocator()); +} + void OMPClauseProfiler::VisitOMPCollapseClause(const OMPCollapseClause *C) { if (C->getNumForLoops()) Profiler->VisitStmt(C->getNumForLoops()); diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index 9698287..e4e8add 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -155,6 +155,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, case OMPC_num_threads: case OMPC_safelen: case OMPC_simdlen: + case OMPC_allocator: case OMPC_collapse: case OMPC_private: case OMPC_firstprivate: @@ -337,6 +338,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, case OMPC_num_threads: case OMPC_safelen: case OMPC_simdlen: + case OMPC_allocator: case OMPC_collapse: case OMPC_private: case OMPC_firstprivate: @@ -810,11 +812,20 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, break; } break; + case OMPD_allocate: + switch (CKind) { +#define OPENMP_ALLOCATE_CLAUSE(Name) \ + case OMPC_##Name: \ + return true; +#include "clang/Basic/OpenMPKinds.def" + default: + break; + } + break; case OMPD_declare_target: case OMPD_end_declare_target: case OMPD_unknown: case OMPD_threadprivate: - case OMPD_allocate: case OMPD_section: case OMPD_master: case OMPD_taskyield: diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 6827222..ed66c25 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -3948,6 +3948,7 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind, case OMPC_in_reduction: case OMPC_safelen: case OMPC_simdlen: + case OMPC_allocator: case OMPC_collapse: case OMPC_default: case OMPC_seq_cst: diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index fa41896..572863c 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -842,7 +842,7 @@ void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind, /// annot_pragma_openmp_end /// /// allocate-directive: -/// annot_pragma_openmp 'allocate' simple-variable-list +/// annot_pragma_openmp 'allocate' simple-variable-list [] /// annot_pragma_openmp_end /// /// declare-reduction-directive: @@ -897,16 +897,44 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( DeclDirectiveListParserHelper Helper(this, DKind); if (!ParseOpenMPSimpleVarList(DKind, Helper, /*AllowScopeSpecifier=*/true)) { - // The last seen token is annot_pragma_openmp_end - need to check for - // extra tokens. + SmallVector Clauses; if (Tok.isNot(tok::annot_pragma_openmp_end)) { - Diag(Tok, diag::warn_omp_extra_tokens_at_eol) - << getOpenMPDirectiveName(DKind); - SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); + SmallVector, + OMPC_unknown + 1> + FirstClauses(OMPC_unknown + 1); + while (Tok.isNot(tok::annot_pragma_openmp_end)) { + OpenMPClauseKind CKind = + Tok.isAnnotation() ? OMPC_unknown + : getOpenMPClauseKind(PP.getSpelling(Tok)); + Actions.StartOpenMPClause(CKind); + OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind, + !FirstClauses[CKind].getInt()); + SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, + StopBeforeMatch); + FirstClauses[CKind].setInt(true); + if (Clause != nullptr) + Clauses.push_back(Clause); + if (Tok.is(tok::annot_pragma_openmp_end)) { + Actions.EndOpenMPClause(); + break; + } + // Skip ',' if any. + if (Tok.is(tok::comma)) + ConsumeToken(); + Actions.EndOpenMPClause(); + } + // The last seen token is annot_pragma_openmp_end - need to check for + // extra tokens. + if (Tok.isNot(tok::annot_pragma_openmp_end)) { + Diag(Tok, diag::warn_omp_extra_tokens_at_eol) + << getOpenMPDirectiveName(DKind); + SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); + } } // Skip the last annot_pragma_openmp_end. ConsumeAnnotationToken(); - return Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers()); + return Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers(), + Clauses); } break; } @@ -925,9 +953,10 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( ? OMPC_unknown : getOpenMPClauseKind(PP.getSpelling(Tok)); Actions.StartOpenMPClause(CKind); - OMPClause *Clause = - ParseOpenMPClause(OMPD_requires, CKind, !FirstClauses[CKind].getInt()); - SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, StopBeforeMatch); + OMPClause *Clause = ParseOpenMPClause(OMPD_requires, CKind, + !FirstClauses[CKind].getInt()); + SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, + StopBeforeMatch); FirstClauses[CKind].setInt(true); if (Clause != nullptr) Clauses.push_back(Clause); @@ -1214,15 +1243,42 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { DeclDirectiveListParserHelper Helper(this, DKind); if (!ParseOpenMPSimpleVarList(DKind, Helper, /*AllowScopeSpecifier=*/false)) { - // The last seen token is annot_pragma_openmp_end - need to check for - // extra tokens. + SmallVector Clauses; if (Tok.isNot(tok::annot_pragma_openmp_end)) { - Diag(Tok, diag::warn_omp_extra_tokens_at_eol) - << getOpenMPDirectiveName(DKind); - SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); + SmallVector, + OMPC_unknown + 1> + FirstClauses(OMPC_unknown + 1); + while (Tok.isNot(tok::annot_pragma_openmp_end)) { + OpenMPClauseKind CKind = + Tok.isAnnotation() ? OMPC_unknown + : getOpenMPClauseKind(PP.getSpelling(Tok)); + Actions.StartOpenMPClause(CKind); + OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind, + !FirstClauses[CKind].getInt()); + SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, + StopBeforeMatch); + FirstClauses[CKind].setInt(true); + if (Clause != nullptr) + Clauses.push_back(Clause); + if (Tok.is(tok::annot_pragma_openmp_end)) { + Actions.EndOpenMPClause(); + break; + } + // Skip ',' if any. + if (Tok.is(tok::comma)) + ConsumeToken(); + Actions.EndOpenMPClause(); + } + // The last seen token is annot_pragma_openmp_end - need to check for + // extra tokens. + if (Tok.isNot(tok::annot_pragma_openmp_end)) { + Diag(Tok, diag::warn_omp_extra_tokens_at_eol) + << getOpenMPDirectiveName(DKind); + SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); + } } - DeclGroupPtrTy Res = - Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers()); + DeclGroupPtrTy Res = Actions.ActOnOpenMPAllocateDirective( + Loc, Helper.getIdentifiers(), Clauses); Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); } SkipUntil(tok::annot_pragma_openmp_end); @@ -1506,7 +1562,7 @@ bool Parser::ParseOpenMPSimpleVarList( /// thread_limit-clause | priority-clause | grainsize-clause | /// nogroup-clause | num_tasks-clause | hint-clause | to-clause | /// from-clause | is_device_ptr-clause | task_reduction-clause | -/// in_reduction-clause +/// in_reduction-clause | allocator-clause /// OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, bool FirstClause) { @@ -1535,6 +1591,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_grainsize: case OMPC_num_tasks: case OMPC_hint: + case OMPC_allocator: // OpenMP [2.5, Restrictions] // At most one num_threads clause can appear on the directive. // OpenMP [2.8.1, simd construct, Restrictions] @@ -1555,6 +1612,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, // At most one grainsize clause can appear on the directive. // OpenMP [2.9.2, taskloop Construct, Restrictions] // At most one num_tasks clause can appear on the directive. + // OpenMP [2.11.3, allocate Directive, Restrictions] + // At most one allocator clause can appear on the directive. if (!FirstClause) { Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; @@ -1722,6 +1781,9 @@ ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName, /// hint-clause: /// 'hint' '(' expression ')' /// +/// allocator-clause: +/// 'allocator' '(' expression ')' +/// OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind, bool ParseOnly) { SourceLocation Loc = ConsumeToken(); diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 32e493e..68ee887 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -2194,9 +2194,13 @@ Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef VarList) { return D; } -Sema::DeclGroupPtrTy -Sema::ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef VarList, - DeclContext *Owner) { +Sema::DeclGroupPtrTy Sema::ActOnOpenMPAllocateDirective( + SourceLocation Loc, ArrayRef VarList, + ArrayRef Clauses, DeclContext *Owner) { + assert(Clauses.size() <= 1 && "Expected at most one clause."); + Expr *Allocator = nullptr; + if (!Clauses.empty()) + Allocator = cast(Clauses.back())->getAllocator(); SmallVector Vars; for (Expr *RefExpr : VarList) { auto *DE = cast(RefExpr); @@ -2213,17 +2217,18 @@ Sema::ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef VarList, continue; Vars.push_back(RefExpr); - VD->addAttr( - OMPAllocateDeclAttr::CreateImplicit(Context, DE->getSourceRange())); + Attr *A = OMPAllocateDeclAttr::CreateImplicit(Context, Allocator, + DE->getSourceRange()); + VD->addAttr(A); if (ASTMutationListener *ML = Context.getASTMutationListener()) - ML->DeclarationMarkedOpenMPAllocate(VD, - VD->getAttr()); + ML->DeclarationMarkedOpenMPAllocate(VD, A); } if (Vars.empty()) return nullptr; if (!Owner) Owner = getCurLexicalContext(); - OMPAllocateDecl *D = OMPAllocateDecl::Create(Context, Owner, Loc, Vars); + OMPAllocateDecl *D = + OMPAllocateDecl::Create(Context, Owner, Loc, Vars, Clauses); D->setAccess(AS_public); Owner->addDecl(D); return DeclGroupPtrTy::make(DeclGroupRef(D)); @@ -8436,6 +8441,9 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, case OMPC_simdlen: Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc); break; + case OMPC_allocator: + Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc); + break; case OMPC_collapse: Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc); break; @@ -9009,6 +9017,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPC_final: case OMPC_safelen: case OMPC_simdlen: + case OMPC_allocator: case OMPC_collapse: case OMPC_private: case OMPC_shared: @@ -9259,6 +9268,43 @@ OMPClause *Sema::ActOnOpenMPSimdlenClause(Expr *Len, SourceLocation StartLoc, OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc); } +/// Tries to find omp_allocator_handle_t type. +static bool FindOMPAllocatorHandleT(Sema &S, SourceLocation Loc, + QualType &OMPAllocatorHandleT) { + if (!OMPAllocatorHandleT.isNull()) + return true; + DeclarationName OMPAllocatorHandleTName = + &S.getASTContext().Idents.get("omp_allocator_handle_t"); + auto *TD = dyn_cast_or_null(S.LookupSingleName( + S.TUScope, OMPAllocatorHandleTName, Loc, Sema::LookupAnyName)); + if (!TD) { + S.Diag(Loc, diag::err_implied_omp_allocator_handle_t_not_found); + return false; + } + OMPAllocatorHandleT = S.getASTContext().getTypeDeclType(TD); + return true; +} + +OMPClause *Sema::ActOnOpenMPAllocatorClause(Expr *A, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + // OpenMP [2.11.3, allocate Directive, Description] + // allocator is an expression of omp_allocator_handle_t type. + if (!FindOMPAllocatorHandleT(*this, A->getExprLoc(), OMPAllocatorHandleT)) + return nullptr; + + ExprResult Allocator = DefaultLvalueConversion(A); + if (Allocator.isInvalid()) + return nullptr; + Allocator = PerformImplicitConversion(Allocator.get(), OMPAllocatorHandleT, + Sema::AA_Initializing, + /*AllowExplicit=*/true); + if (Allocator.isInvalid()) + return nullptr; + return new (Context) + OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc); +} + OMPClause *Sema::ActOnOpenMPCollapseClause(Expr *NumForLoops, SourceLocation StartLoc, SourceLocation LParenLoc, @@ -9326,6 +9372,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause( case OMPC_num_threads: case OMPC_safelen: case OMPC_simdlen: + case OMPC_allocator: case OMPC_collapse: case OMPC_schedule: case OMPC_private: @@ -9503,6 +9550,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause( case OMPC_num_threads: case OMPC_safelen: case OMPC_simdlen: + case OMPC_allocator: case OMPC_collapse: case OMPC_default: case OMPC_proc_bind: @@ -9724,6 +9772,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind, case OMPC_num_threads: case OMPC_safelen: case OMPC_simdlen: + case OMPC_allocator: case OMPC_collapse: case OMPC_schedule: case OMPC_private: @@ -9928,6 +9977,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause( case OMPC_num_threads: case OMPC_safelen: case OMPC_simdlen: + case OMPC_allocator: case OMPC_collapse: case OMPC_default: case OMPC_proc_bind: diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 73909fe..eb3444e 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2883,9 +2883,20 @@ Decl *TemplateDeclInstantiator::VisitOMPAllocateDecl(OMPAllocateDecl *D) { assert(isa(Var) && "allocate arg is not a DeclRefExpr"); Vars.push_back(Var); } + SmallVector Clauses; + // Copy map clauses from the original mapper. + for (OMPClause *C : D->clauselists()) { + auto *AC = cast(C); + ExprResult NewE = SemaRef.SubstExpr(AC->getAllocator(), TemplateArgs); + if (!NewE.isUsable()) + continue; + OMPClause *IC = SemaRef.ActOnOpenMPAllocatorClause( + NewE.get(), AC->getBeginLoc(), AC->getLParenLoc(), AC->getEndLoc()); + Clauses.push_back(IC); + } - Sema::DeclGroupPtrTy Res = - SemaRef.ActOnOpenMPAllocateDirective(D->getLocation(), Vars, Owner); + Sema::DeclGroupPtrTy Res = SemaRef.ActOnOpenMPAllocateDirective( + D->getLocation(), Vars, Clauses, Owner); if (Res.get().isNull()) return nullptr; return Res.get().getSingleDecl(); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 605d523..93c5bdf 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -1554,6 +1554,16 @@ public: return getSema().ActOnOpenMPSimdlenClause(Len, StartLoc, LParenLoc, EndLoc); } + /// Build a new OpenMP 'allocator' clause. + /// + /// By default, performs semantic analysis to build the new OpenMP clause. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPAllocatorClause(Expr *A, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPAllocatorClause(A, StartLoc, LParenLoc, EndLoc); + } + /// Build a new OpenMP 'collapse' clause. /// /// By default, performs semantic analysis to build the new OpenMP clause. @@ -8345,6 +8355,16 @@ TreeTransform::TransformOMPSafelenClause(OMPSafelenClause *C) { template OMPClause * +TreeTransform::TransformOMPAllocatorClause(OMPAllocatorClause *C) { + ExprResult E = getDerived().TransformExpr(C->getAllocator()); + if (E.isInvalid()) + return nullptr; + return getDerived().RebuildOMPAllocatorClause( + E.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); +} + +template +OMPClause * TreeTransform::TransformOMPSimdlenClause(OMPSimdlenClause *C) { ExprResult E = getDerived().TransformExpr(C->getSimdlen()); if (E.isInvalid()) diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 1ab6a75..5ca5e8d 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -11704,6 +11704,9 @@ OMPClause *OMPClauseReader::readClause() { case OMPC_simdlen: C = new (Context) OMPSimdlenClause(); break; + case OMPC_allocator: + C = new (Context) OMPAllocatorClause(); + break; case OMPC_collapse: C = new (Context) OMPCollapseClause(); break; @@ -11929,6 +11932,11 @@ void OMPClauseReader::VisitOMPSimdlenClause(OMPSimdlenClause *C) { C->setLParenLoc(Record.readSourceLocation()); } +void OMPClauseReader::VisitOMPAllocatorClause(OMPAllocatorClause *C) { + C->setAllocator(Record.readExpr()); + C->setLParenLoc(Record.readSourceLocation()); +} + void OMPClauseReader::VisitOMPCollapseClause(OMPCollapseClause *C) { C->setNumForLoops(Record.readSubExpr()); C->setLParenLoc(Record.readSourceLocation()); diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 760489d..f37372f 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -2637,12 +2637,19 @@ void ASTDeclReader::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { void ASTDeclReader::VisitOMPAllocateDecl(OMPAllocateDecl *D) { VisitDecl(D); unsigned NumVars = D->varlist_size(); + unsigned NumClauses = D->clauselist_size(); SmallVector Vars; Vars.reserve(NumVars); for (unsigned i = 0; i != NumVars; ++i) { Vars.push_back(Record.readExpr()); } D->setVars(Vars); + SmallVector Clauses; + Clauses.reserve(NumClauses); + OMPClauseReader ClauseReader(Record); + for (unsigned I = 0; I != NumClauses; ++I) + Clauses.push_back(ClauseReader.readClause()); + D->setClauses(Clauses); } void ASTDeclReader::VisitOMPRequiresDecl(OMPRequiresDecl * D) { @@ -3878,9 +3885,12 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { case DECL_OMP_THREADPRIVATE: D = OMPThreadPrivateDecl::CreateDeserialized(Context, ID, Record.readInt()); break; - case DECL_OMP_ALLOCATE: - D = OMPAllocateDecl::CreateDeserialized(Context, ID, Record.readInt()); + case DECL_OMP_ALLOCATE: { + unsigned NumVars = Record.readInt(); + unsigned NumClauses = Record.readInt(); + D = OMPAllocateDecl::CreateDeserialized(Context, ID, NumVars, NumClauses); break; + } case DECL_OMP_REQUIRES: D = OMPRequiresDecl::CreateDeserialized(Context, ID, Record.readInt()); break; @@ -4481,8 +4491,8 @@ void ASTDeclReader::UpdateDecl(Decl *D, break; case UPD_DECL_MARKED_OPENMP_ALLOCATE: - D->addAttr(OMPAllocateDeclAttr::CreateImplicit(Reader.getContext(), - ReadSourceRange())); + D->addAttr(OMPAllocateDeclAttr::CreateImplicit( + Reader.getContext(), Record.readExpr(), ReadSourceRange())); break; case UPD_DECL_EXPORTED: { diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 933cc6b..0395605 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -5291,6 +5291,7 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { break; case UPD_DECL_MARKED_OPENMP_ALLOCATE: + Record.AddStmt(D->getAttr()->getAllocator()); Record.AddSourceRange(D->getAttr()->getRange()); break; @@ -6534,6 +6535,11 @@ void OMPClauseWriter::VisitOMPSimdlenClause(OMPSimdlenClause *C) { Record.AddSourceLocation(C->getLParenLoc()); } +void OMPClauseWriter::VisitOMPAllocatorClause(OMPAllocatorClause *C) { + Record.AddStmt(C->getAllocator()); + Record.AddSourceLocation(C->getLParenLoc()); +} + void OMPClauseWriter::VisitOMPCollapseClause(OMPCollapseClause *C) { Record.AddStmt(C->getNumForLoops()); Record.AddSourceLocation(C->getLParenLoc()); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index cfcd81b..37173e8 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1747,9 +1747,13 @@ void ASTDeclWriter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { void ASTDeclWriter::VisitOMPAllocateDecl(OMPAllocateDecl *D) { Record.push_back(D->varlist_size()); + Record.push_back(D->clauselist_size()); VisitDecl(D); for (auto *I : D->varlists()) Record.AddStmt(I); + OMPClauseWriter ClauseWriter(Record); + for (OMPClause *C : D->clauselists()) + ClauseWriter.writeClause(C); Code = serialization::DECL_OMP_ALLOCATE; } diff --git a/clang/test/OpenMP/allocate_allocator_ast_print.cpp b/clang/test/OpenMP/allocate_allocator_ast_print.cpp new file mode 100644 index 0000000..7a42dda --- /dev/null +++ b/clang/test/OpenMP/allocate_allocator_ast_print.cpp @@ -0,0 +1,89 @@ +// RUN: %clang_cc1 -verify -fopenmp -triple x86_64-apple-darwin10.6.0 -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp -triple x86_64-apple-darwin10.6.0 -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -triple x86_64-apple-darwin10.6.0 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print +// RUN: %clang_cc1 -verify -fopenmp -triple x86_64-unknown-linux-gnu -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print + +// RUN: %clang_cc1 -verify -fopenmp-simd -triple x86_64-apple-darwin10.6.0 -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp-simd -triple x86_64-apple-darwin10.6.0 -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp-simd -triple x86_64-apple-darwin10.6.0 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print +// RUN: %clang_cc1 -verify -fopenmp-simd -triple x86_64-unknown-linux-gnu -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp-simd -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp-simd -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER + +typedef void **omp_allocator_handle_t; +extern const omp_allocator_handle_t omp_default_mem_alloc; +extern const omp_allocator_handle_t omp_large_cap_mem_alloc; +extern const omp_allocator_handle_t omp_const_mem_alloc; +extern const omp_allocator_handle_t omp_high_bw_mem_alloc; +extern const omp_allocator_handle_t omp_low_lat_mem_alloc; +extern const omp_allocator_handle_t omp_cgroup_mem_alloc; +extern const omp_allocator_handle_t omp_pteam_mem_alloc; +extern const omp_allocator_handle_t omp_thread_mem_alloc; + +struct St{ + int a; +}; + +struct St1{ + int a; + static int b; +// CHECK: static int b; +#pragma omp allocate(b) allocator(omp_default_mem_alloc) +// CHECK-NEXT: #pragma omp allocate(St1::b) allocator(omp_default_mem_alloc){{$}} +} d; + +int a, b; +// CHECK: int a; +// CHECK: int b; +#pragma omp allocate(a) allocator(omp_large_cap_mem_alloc) +#pragma omp allocate(a) allocator(omp_const_mem_alloc) +// CHECK-NEXT: #pragma omp allocate(a) allocator(omp_large_cap_mem_alloc) +// CHECK-NEXT: #pragma omp allocate(a) allocator(omp_const_mem_alloc) +#pragma omp allocate(d, b) allocator(omp_high_bw_mem_alloc) +// CHECK-NEXT: #pragma omp allocate(d,b) allocator(omp_high_bw_mem_alloc) + +template +struct ST { + static T m; + #pragma omp allocate(m) allocator(omp_low_lat_mem_alloc) +}; + +template T foo() { + T v; + #pragma omp allocate(v) allocator(omp_cgroup_mem_alloc) + v = ST::m; + return v; +} +//CHECK: template T foo() { +//CHECK-NEXT: T v; +//CHECK-NEXT: #pragma omp allocate(v) allocator(omp_cgroup_mem_alloc) +//CHECK: template<> int foo() { +//CHECK-NEXT: int v; +//CHECK-NEXT: #pragma omp allocate(v) allocator(omp_cgroup_mem_alloc) + +namespace ns{ + int a; +} +// CHECK: namespace ns { +// CHECK-NEXT: int a; +// CHECK-NEXT: } +#pragma omp allocate(ns::a) allocator(omp_pteam_mem_alloc) +// CHECK-NEXT: #pragma omp allocate(ns::a) allocator(omp_pteam_mem_alloc) + +int main () { + static int a; +// CHECK: static int a; +#pragma omp allocate(a) allocator(omp_thread_mem_alloc) +// CHECK-NEXT: #pragma omp allocate(a) allocator(omp_thread_mem_alloc) + a=2; + return (foo()); +} + +extern template int ST::m; +#endif diff --git a/clang/test/OpenMP/allocate_allocator_messages.cpp b/clang/test/OpenMP/allocate_allocator_messages.cpp new file mode 100644 index 0000000..0f616df --- /dev/null +++ b/clang/test/OpenMP/allocate_allocator_messages.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s + +// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s + +struct St{ + int a; +}; + +int sss; +#pragma omp allocate(sss) allocate // expected-warning {{extra tokens at the end of '#pragma omp allocate' are ignored}} +#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 }} + +typedef void *omp_allocator_handle_t; + +struct St1{ + int a; + static int b; +#pragma omp allocate(b) allocator(sss) // expected-error {{initializing 'omp_allocator_handle_t' (aka 'void *') with an expression of incompatible type 'int'}} +} d; + +#pragma omp allocate(d) allocator(nullptr) +extern void *allocator; +#pragma omp allocate(d) allocator(allocator) diff --git a/clang/test/PCH/chain-openmp-allocate.cpp b/clang/test/PCH/chain-openmp-allocate.cpp index ea529b5..1383d0f 100644 --- a/clang/test/PCH/chain-openmp-allocate.cpp +++ b/clang/test/PCH/chain-openmp-allocate.cpp @@ -12,14 +12,17 @@ #if !defined(PASS1) #define PASS1 +typedef void **omp_allocator_handle_t; +extern const omp_allocator_handle_t omp_default_mem_alloc; + int a; // CHECK: int a; #elif !defined(PASS2) #define PASS2 -#pragma omp allocate(a) -// CHECK: #pragma omp allocate(a) +#pragma omp allocate(a) allocator(omp_default_mem_alloc) +// CHECK: #pragma omp allocate(a) allocator(omp_default_mem_alloc) #else diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index fa4ac48..ab9087a 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -2168,6 +2168,10 @@ void OMPClauseEnqueue::VisitOMPSimdlenClause(const OMPSimdlenClause *C) { Visitor->AddStmt(C->getSimdlen()); } +void OMPClauseEnqueue::VisitOMPAllocatorClause(const OMPAllocatorClause *C) { + Visitor->AddStmt(C->getAllocator()); +} + void OMPClauseEnqueue::VisitOMPCollapseClause(const OMPCollapseClause *C) { Visitor->AddStmt(C->getNumForLoops()); } -- 2.7.4