From 25ed0c07c1ce7835c2bca9d72e34aefda5294f40 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Thu, 7 Mar 2019 17:54:44 +0000 Subject: [PATCH] [OPENMP 5.0]Add initial support for 'allocate' directive. Added parsing/sema analysis/serialization/deserialization support for 'allocate' directive. llvm-svn: 355614 --- clang/include/clang/AST/ASTMutationListener.h | 5 + clang/include/clang/AST/ASTNodeTraverser.h | 5 + clang/include/clang/AST/DeclOpenMP.h | 67 +++++++++++ clang/include/clang/AST/RecursiveASTVisitor.h | 7 ++ clang/include/clang/Basic/Attr.td | 7 ++ clang/include/clang/Basic/DeclNodes.td | 1 + clang/include/clang/Basic/OpenMPKinds.def | 1 + clang/include/clang/Basic/OpenMPKinds.h | 1 + clang/include/clang/Sema/Sema.h | 10 +- clang/include/clang/Serialization/ASTBitCodes.h | 5 +- clang/include/clang/Serialization/ASTWriter.h | 1 + clang/lib/AST/ASTContext.cpp | 4 +- clang/lib/AST/DeclBase.cpp | 1 + clang/lib/AST/DeclOpenMP.cpp | 30 +++++ clang/lib/AST/DeclPrinter.cpp | 18 ++- clang/lib/AST/OpenMPClause.cpp | 2 + clang/lib/Basic/OpenMPKinds.cpp | 6 + clang/lib/CodeGen/CGDecl.cpp | 1 + clang/lib/CodeGen/CGOpenMPRuntime.cpp | 3 + clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp | 6 +- clang/lib/CodeGen/CGStmtOpenMP.cpp | 1 + clang/lib/CodeGen/CodeGenModule.cpp | 3 + clang/lib/Frontend/MultiplexConsumer.cpp | 6 + clang/lib/Parse/ParseDecl.cpp | 3 +- clang/lib/Parse/ParseOpenMP.cpp | 76 ++++++++++-- clang/lib/Parse/Parser.cpp | 3 +- clang/lib/Sema/SemaOpenMP.cpp | 75 ++++++++++-- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 15 +++ clang/lib/Serialization/ASTCommon.cpp | 1 + clang/lib/Serialization/ASTCommon.h | 1 + clang/lib/Serialization/ASTReaderDecl.cpp | 22 +++- clang/lib/Serialization/ASTWriter.cpp | 14 +++ clang/lib/Serialization/ASTWriterDecl.cpp | 11 +- clang/test/OpenMP/allocate_ast_print.cpp | 79 +++++++++++++ clang/test/OpenMP/allocate_messages.cpp | 149 ++++++++++++++++++++++++ clang/test/PCH/chain-openmp-allocate.cpp | 36 ++++++ clang/tools/libclang/CIndex.cpp | 1 + 37 files changed, 644 insertions(+), 33 deletions(-) create mode 100644 clang/test/OpenMP/allocate_ast_print.cpp create mode 100644 clang/test/OpenMP/allocate_messages.cpp create mode 100644 clang/test/PCH/chain-openmp-allocate.cpp diff --git a/clang/include/clang/AST/ASTMutationListener.h b/clang/include/clang/AST/ASTMutationListener.h index ac115d4..8879f9f 100644 --- a/clang/include/clang/AST/ASTMutationListener.h +++ b/clang/include/clang/AST/ASTMutationListener.h @@ -127,6 +127,11 @@ public: virtual void DeclarationMarkedOpenMPDeclareTarget(const Decl *D, const Attr *Attr) {} + /// A declaration is marked as a variable with OpenMP allocator. + /// + /// \param D the declaration marked as a variable with OpenMP allocator. + virtual void DeclarationMarkedOpenMPAllocate(const Decl *D, const Attr *A) {} + /// A definition has been made visible by being redefined locally. /// /// \param D The definition that was previously not visible. diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index 44c6f54..f5b48be 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -393,6 +393,11 @@ public: Visit(D->getInit()); } + void VisitOMPAllocateDecl(const OMPAllocateDecl *D) { + for (const auto *E : D->varlists()) + Visit(E); + } + template void dumpTemplateDeclSpecialization(const SpecializationDecl *D) { for (const auto *RedeclWithBadType : D->redecls()) { diff --git a/clang/include/clang/AST/DeclOpenMP.h b/clang/include/clang/AST/DeclOpenMP.h index 6bdb4dd..92690f5 100644 --- a/clang/include/clang/AST/DeclOpenMP.h +++ b/clang/include/clang/AST/DeclOpenMP.h @@ -405,6 +405,73 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == OMPRequires; } }; + +/// This represents '#pragma omp allocate ...' directive. +/// For example, in the following, the default allocator is used for both 'a' +/// and 'A::b': +/// +/// \code +/// int a; +/// #pragma omp allocate(a) +/// struct A { +/// static int b; +/// #pragma omp allocate(b) +/// }; +/// \endcode +/// +class OMPAllocateDecl final + : public Decl, + private llvm::TrailingObjects { + friend class ASTDeclReader; + friend TrailingObjects; + + /// Number of variable within the allocate directive. + unsigned NumVars = 0; + + virtual void anchor(); + + OMPAllocateDecl(Kind DK, DeclContext *DC, SourceLocation L) + : Decl(DK, DC, L) {} + + ArrayRef getVars() const { + return llvm::makeArrayRef(getTrailingObjects(), NumVars); + } + + MutableArrayRef getVars() { + return MutableArrayRef(getTrailingObjects(), NumVars); + } + + void setVars(ArrayRef VL); + +public: + static OMPAllocateDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, ArrayRef VL); + static OMPAllocateDecl *CreateDeserialized(ASTContext &C, unsigned ID, + unsigned N); + + typedef MutableArrayRef::iterator varlist_iterator; + typedef ArrayRef::iterator varlist_const_iterator; + typedef llvm::iterator_range varlist_range; + typedef llvm::iterator_range varlist_const_range; + + unsigned varlist_size() const { return NumVars; } + bool varlist_empty() const { return NumVars == 0; } + + varlist_range varlists() { + return varlist_range(varlist_begin(), varlist_end()); + } + varlist_const_range varlists() const { + return varlist_const_range(varlist_begin(), varlist_end()); + } + varlist_iterator varlist_begin() { return getVars().begin(); } + varlist_iterator varlist_end() { return getVars().end(); } + varlist_const_iterator varlist_begin() const { return getVars().begin(); } + varlist_const_iterator varlist_end() const { return getVars().end(); } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == OMPAllocate; } +}; + } // end namespace clang #endif diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index c96da1e..a5098d8 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -1613,6 +1613,12 @@ DEF_TRAVERSE_DECL(OMPDeclareMapperDecl, { DEF_TRAVERSE_DECL(OMPCapturedExprDecl, { TRY_TO(TraverseVarHelper(D)); }) +DEF_TRAVERSE_DECL(OMPAllocateDecl, { + for (auto *I : D->varlists()) { + TRY_TO(TraverseStmt(I)); + } +}) + // A helper method for TemplateDecl's children. template bool RecursiveASTVisitor::TraverseTemplateParameterListHelper( @@ -2797,6 +2803,7 @@ bool RecursiveASTVisitor::TraverseOMPClause(OMPClause *C) { break; #include "clang/Basic/OpenMPKinds.def" case OMPC_threadprivate: + case OMPC_allocate: case OMPC_uniform: case OMPC_unknown: break; diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index c36ec26..523b89d 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3152,6 +3152,13 @@ def OMPDeclareTargetDecl : InheritableAttr { }]; } +def OMPAllocateDecl : InheritableAttr { + // This attribute has no spellings as it is only ever created implicitly. + let Spellings = []; + let SemaHandler = 0; + let Documentation = [Undocumented]; +} + def InternalLinkage : InheritableAttr { let Spellings = [Clang<"internal_linkage">]; let Subjects = SubjectList<[Var, Function, CXXRecord]>; diff --git a/clang/include/clang/Basic/DeclNodes.td b/clang/include/clang/Basic/DeclNodes.td index 74a6bf3..45eba45 100644 --- a/clang/include/clang/Basic/DeclNodes.td +++ b/clang/include/clang/Basic/DeclNodes.td @@ -98,6 +98,7 @@ def Captured : Decl, DeclContext; def ClassScopeFunctionSpecialization : Decl; def Import : Decl; def OMPThreadPrivate : Decl; +def OMPAllocate : Decl; def OMPRequires : Decl; def Empty : Decl; diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def index 0aef6fe..2237bd7 100644 --- a/clang/include/clang/Basic/OpenMPKinds.def +++ b/clang/include/clang/Basic/OpenMPKinds.def @@ -244,6 +244,7 @@ OPENMP_DIRECTIVE_EXT(target_teams_distribute, "target teams distribute") OPENMP_DIRECTIVE_EXT(target_teams_distribute_parallel_for, "target teams distribute parallel for") OPENMP_DIRECTIVE_EXT(target_teams_distribute_parallel_for_simd, "target teams distribute parallel for simd") OPENMP_DIRECTIVE_EXT(target_teams_distribute_simd, "target teams distribute simd") +OPENMP_DIRECTIVE(allocate) // OpenMP clauses. OPENMP_CLAUSE(if, OMPIfClause) diff --git a/clang/include/clang/Basic/OpenMPKinds.h b/clang/include/clang/Basic/OpenMPKinds.h index d8dee23..603ff40 100644 --- a/clang/include/clang/Basic/OpenMPKinds.h +++ b/clang/include/clang/Basic/OpenMPKinds.h @@ -35,6 +35,7 @@ enum OpenMPClauseKind { #include "clang/Basic/OpenMPKinds.def" OMPC_threadprivate, OMPC_uniform, + OMPC_allocate, OMPC_unknown }; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 3408c94..5ead2c0 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -8879,9 +8879,9 @@ public: // OpenMP directives and clauses. /// Called on correct id-expression from the '#pragma omp /// threadprivate'. - ExprResult ActOnOpenMPIdExpression(Scope *CurScope, - CXXScopeSpec &ScopeSpec, - const DeclarationNameInfo &Id); + ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec, + const DeclarationNameInfo &Id, + OpenMPDirectiveKind Kind); /// Called on well-formed '#pragma omp threadprivate'. DeclGroupPtrTy ActOnOpenMPThreadprivateDirective( SourceLocation Loc, @@ -8889,6 +8889,10 @@ public: /// Builds a new OpenMPThreadPrivateDecl and checks its correctness. OMPThreadPrivateDecl *CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef VarList); + /// Called on well-formed '#pragma omp allocate'. + DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, + ArrayRef VarList, + DeclContext *Owner = nullptr); /// Called on well-formed '#pragma omp requires'. DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc, ArrayRef ClauseList); diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index a1ab611..0365e3a 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1521,7 +1521,10 @@ namespace serialization { /// An OMPRequiresDecl record. DECL_OMP_REQUIRES, - + + /// An OMPAllocateDcl record. + DECL_OMP_ALLOCATE, + /// An EmptyDecl record. DECL_EMPTY, diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index 32c02bd..ed512ef 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -737,6 +737,7 @@ private: void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) override; void DeclarationMarkedOpenMPDeclareTarget(const Decl *D, const Attr *Attr) override; + void DeclarationMarkedOpenMPAllocate(const Decl *D, const Attr *A) override; void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) override; void AddedAttributeToRecord(const Attr *Attr, const RecordDecl *Record) override; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 41efa95..dee12a5 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -9798,12 +9798,12 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { return false; } else if (isa(D)) return true; - else if (isa(D)) - return true; else if (isa(D)) return true; else if (isa(D)) return !D->getDeclContext()->isDependentContext(); + else if (isa(D)) + return !D->getDeclContext()->isDependentContext(); else if (isa(D)) return !D->getDeclContext()->isDependentContext(); else if (isa(D)) diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index a44c839..e1b5161 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -812,6 +812,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case ObjCCategoryImpl: case Import: case OMPThreadPrivate: + case OMPAllocate: case OMPRequires: case OMPCapturedExpr: case Empty: diff --git a/clang/lib/AST/DeclOpenMP.cpp b/clang/lib/AST/DeclOpenMP.cpp index 39cb467..f50775b 100644 --- a/clang/lib/AST/DeclOpenMP.cpp +++ b/clang/lib/AST/DeclOpenMP.cpp @@ -53,6 +53,36 @@ void OMPThreadPrivateDecl::setVars(ArrayRef VL) { } //===----------------------------------------------------------------------===// +// OMPAllocateDecl Implementation. +//===----------------------------------------------------------------------===// + +void OMPAllocateDecl::anchor() { } + +OMPAllocateDecl *OMPAllocateDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation L, + ArrayRef VL) { + OMPAllocateDecl *D = new (C, DC, additionalSizeToAlloc(VL.size())) + OMPAllocateDecl(OMPAllocate, DC, L); + D->NumVars = VL.size(); + D->setVars(VL); + 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; + return D; +} + +void OMPAllocateDecl::setVars(ArrayRef VL) { + assert(VL.size() == NumVars && + "Number of variables is not the same as the preallocated buffer"); + std::uninitialized_copy(VL.begin(), VL.end(), getTrailingObjects()); +} + +//===----------------------------------------------------------------------===// // OMPRequiresDecl Implementation. //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index 4606989..d023a03 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -99,6 +99,7 @@ namespace { void VisitUsingDecl(UsingDecl *D); void VisitUsingShadowDecl(UsingShadowDecl *D); void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D); + void VisitOMPAllocateDecl(OMPAllocateDecl *D); void VisitOMPRequiresDecl(OMPRequiresDecl *D); void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D); void VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D); @@ -424,7 +425,8 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { // FIXME: Need to be able to tell the DeclPrinter when const char *Terminator = nullptr; if (isa(*D) || isa(*D) || - isa(*D) || isa(*D)) + isa(*D) || isa(*D) || + isa(*D)) Terminator = nullptr; else if (isa(*D) && cast(*D)->hasBody()) Terminator = nullptr; @@ -1546,6 +1548,20 @@ void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { } } +void DeclPrinter::VisitOMPAllocateDecl(OMPAllocateDecl *D) { + Out << "#pragma omp allocate"; + if (!D->varlist_empty()) { + for (OMPAllocateDecl::varlist_iterator I = D->varlist_begin(), + E = D->varlist_end(); + I != E; ++I) { + Out << (I == D->varlist_begin() ? '(' : ','); + NamedDecl *ND = cast(*I)->getDecl(); + ND->printQualifiedName(Out); + } + Out << ")"; + } +} + void DeclPrinter::VisitOMPRequiresDecl(OMPRequiresDecl *D) { Out << "#pragma omp requires "; if (!D->clauselist_empty()) { diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp index a50e2de..4016dd0 100644 --- a/clang/lib/AST/OpenMPClause.cpp +++ b/clang/lib/AST/OpenMPClause.cpp @@ -84,6 +84,7 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) { case OMPC_untied: case OMPC_mergeable: case OMPC_threadprivate: + case OMPC_allocate: case OMPC_flush: case OMPC_read: case OMPC_write: @@ -155,6 +156,7 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C) case OMPC_untied: case OMPC_mergeable: case OMPC_threadprivate: + case OMPC_allocate: case OMPC_flush: case OMPC_read: case OMPC_write: diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index 493ac7b..9698287 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -71,6 +71,8 @@ const char *clang::getOpenMPClauseName(OpenMPClauseKind Kind) { return "uniform"; case OMPC_threadprivate: return "threadprivate or thread local"; + case OMPC_allocate: + return "allocate"; } llvm_unreachable("Invalid OpenMP clause kind"); } @@ -147,6 +149,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, .Default(OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown); case OMPC_unknown: case OMPC_threadprivate: + case OMPC_allocate: case OMPC_if: case OMPC_final: case OMPC_num_threads: @@ -328,6 +331,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, llvm_unreachable("Invalid OpenMP 'atomic_default_mem_order' clause type"); case OMPC_unknown: case OMPC_threadprivate: + case OMPC_allocate: case OMPC_if: case OMPC_final: case OMPC_num_threads: @@ -810,6 +814,7 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, case OMPD_end_declare_target: case OMPD_unknown: case OMPD_threadprivate: + case OMPD_allocate: case OMPD_section: case OMPD_master: case OMPD_taskyield: @@ -1033,6 +1038,7 @@ void clang::getOpenMPCaptureRegions( CaptureRegions.push_back(OMPD_unknown); break; case OMPD_threadprivate: + case OMPD_allocate: case OMPD_taskyield: case OMPD_barrier: case OMPD_taskwait: diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index a008ad0..4acfb15 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -103,6 +103,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) { case Decl::Label: // __label__ x; case Decl::Import: case Decl::OMPThreadPrivate: + case Decl::OMPAllocate: case Decl::OMPCapturedExpr: case Decl::OMPRequires: case Decl::Empty: diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 64fdefd..0beb134 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -8215,6 +8215,7 @@ getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) { case OMPD_cancellation_point: case OMPD_ordered: case OMPD_threadprivate: + case OMPD_allocate: case OMPD_task: case OMPD_simd: case OMPD_sections: @@ -8638,6 +8639,7 @@ void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, case OMPD_cancellation_point: case OMPD_ordered: case OMPD_threadprivate: + case OMPD_allocate: case OMPD_task: case OMPD_simd: case OMPD_sections: @@ -9156,6 +9158,7 @@ void CGOpenMPRuntime::emitTargetDataStandAloneCall( case OMPD_cancellation_point: case OMPD_ordered: case OMPD_threadprivate: + case OMPD_allocate: case OMPD_task: case OMPD_simd: case OMPD_sections: diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp index 534f91c..5eaa0f0 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp @@ -743,7 +743,7 @@ static const Stmt *getSingleCompoundChild(ASTContext &Ctx, const Stmt *Body) { isa(D) || isa(D) || isa(D) || isa(D) || - isa(D)) + isa(D) || isa(D)) return true; const auto *VD = dyn_cast(D); if (!VD) @@ -835,6 +835,7 @@ static bool hasNestedSPMDDirective(ASTContext &Ctx, case OMPD_cancellation_point: case OMPD_ordered: case OMPD_threadprivate: + case OMPD_allocate: case OMPD_task: case OMPD_simd: case OMPD_sections: @@ -904,6 +905,7 @@ static bool supportsSPMDExecutionMode(ASTContext &Ctx, case OMPD_cancellation_point: case OMPD_ordered: case OMPD_threadprivate: + case OMPD_allocate: case OMPD_task: case OMPD_simd: case OMPD_sections: @@ -1055,6 +1057,7 @@ static bool hasNestedLightweightDirective(ASTContext &Ctx, case OMPD_cancellation_point: case OMPD_ordered: case OMPD_threadprivate: + case OMPD_allocate: case OMPD_task: case OMPD_simd: case OMPD_sections: @@ -1129,6 +1132,7 @@ static bool supportsLightweightRuntime(ASTContext &Ctx, case OMPD_cancellation_point: case OMPD_ordered: case OMPD_threadprivate: + case OMPD_allocate: case OMPD_task: case OMPD_simd: case OMPD_sections: diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 020f0b2..6827222 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -3963,6 +3963,7 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind, case OMPC_nowait: case OMPC_untied: case OMPC_threadprivate: + case OMPC_allocate: case OMPC_depend: case OMPC_mergeable: case OMPC_device: diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 13fa3e7..7abffa3 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -5062,6 +5062,9 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { EmitOMPThreadPrivateDecl(cast(D)); break; + case Decl::OMPAllocate: + break; + case Decl::OMPDeclareReduction: EmitOMPDeclareReduction(cast(D)); break; diff --git a/clang/lib/Frontend/MultiplexConsumer.cpp b/clang/lib/Frontend/MultiplexConsumer.cpp index baa7f50..ed70287 100644 --- a/clang/lib/Frontend/MultiplexConsumer.cpp +++ b/clang/lib/Frontend/MultiplexConsumer.cpp @@ -103,6 +103,7 @@ public: const ObjCInterfaceDecl *IFD) override; void DeclarationMarkedUsed(const Decl *D) override; void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) override; + void DeclarationMarkedOpenMPAllocate(const Decl *D, const Attr *A) override; void DeclarationMarkedOpenMPDeclareTarget(const Decl *D, const Attr *Attr) override; void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) override; @@ -208,6 +209,11 @@ void MultiplexASTMutationListener::DeclarationMarkedOpenMPThreadPrivate( for (size_t i = 0, e = Listeners.size(); i != e; ++i) Listeners[i]->DeclarationMarkedOpenMPThreadPrivate(D); } +void MultiplexASTMutationListener::DeclarationMarkedOpenMPAllocate( + const Decl *D, const Attr *A) { + for (ASTMutationListener *L : Listeners) + L->DeclarationMarkedOpenMPAllocate(D, A); +} void MultiplexASTMutationListener::DeclarationMarkedOpenMPDeclareTarget( const Decl *D, const Attr *Attr) { for (auto *L : Listeners) diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 84d79d9..0cca269 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -1734,7 +1734,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context, /// [C++11] attribute-specifier-seq decl-specifier-seq[opt] /// init-declarator-list ';' ///[C90/C++]init-declarator-list ';' [TODO] -/// [OMP] threadprivate-directive [TODO] +/// [OMP] threadprivate-directive +/// [OMP] allocate-directive [TODO] /// /// for-range-declaration: [C++11 6.5p1: stmt.ranged] /// attribute-specifier-seq[opt] type-specifier-seq declarator diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 2740730..fa41896 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -44,15 +44,17 @@ enum OpenMPDirectiveKindEx { OMPD_mapper, }; -class ThreadprivateListParserHelper final { +class DeclDirectiveListParserHelper final { SmallVector Identifiers; Parser *P; + OpenMPDirectiveKind Kind; public: - ThreadprivateListParserHelper(Parser *P) : P(P) {} + DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind) + : P(P), Kind(Kind) {} void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { - ExprResult Res = - P->getActions().ActOnOpenMPIdExpression(P->getCurScope(), SS, NameInfo); + ExprResult Res = P->getActions().ActOnOpenMPIdExpression( + P->getCurScope(), SS, NameInfo, Kind); if (Res.isUsable()) Identifiers.push_back(Res.get()); } @@ -839,6 +841,10 @@ void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind, /// annot_pragma_openmp 'threadprivate' simple-variable-list /// annot_pragma_openmp_end /// +/// allocate-directive: +/// annot_pragma_openmp 'allocate' simple-variable-list +/// annot_pragma_openmp_end +/// /// declare-reduction-directive: /// annot_pragma_openmp 'declare' 'reduction' [...] /// annot_pragma_openmp_end @@ -869,13 +875,14 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( switch (DKind) { case OMPD_threadprivate: { ConsumeToken(); - ThreadprivateListParserHelper Helper(this); - if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, true)) { + 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. if (Tok.isNot(tok::annot_pragma_openmp_end)) { Diag(Tok, diag::warn_omp_extra_tokens_at_eol) - << getOpenMPDirectiveName(OMPD_threadprivate); + << getOpenMPDirectiveName(DKind); SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); } // Skip the last annot_pragma_openmp_end. @@ -885,6 +892,24 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( } break; } + case OMPD_allocate: { + ConsumeToken(); + 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. + 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()); + } + break; + } case OMPD_requires: { SourceLocation StartLoc = ConsumeToken(); SmallVector Clauses; @@ -1098,6 +1123,10 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( /// annot_pragma_openmp 'threadprivate' simple-variable-list /// annot_pragma_openmp_end /// +/// allocate-directive: +/// annot_pragma_openmp 'allocate' simple-variable-list +/// annot_pragma_openmp_end +/// /// declare-reduction-directive: /// annot_pragma_openmp 'declare' 'reduction' '(' ':' /// {',' } ':' ')' ['initializer' '(' @@ -1157,13 +1186,14 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { << getOpenMPDirectiveName(DKind) << 0; } ConsumeToken(); - ThreadprivateListParserHelper Helper(this); - if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, false)) { + 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. if (Tok.isNot(tok::annot_pragma_openmp_end)) { Diag(Tok, diag::warn_omp_extra_tokens_at_eol) - << getOpenMPDirectiveName(OMPD_threadprivate); + << getOpenMPDirectiveName(DKind); SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); } DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective( @@ -1173,6 +1203,31 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { SkipUntil(tok::annot_pragma_openmp_end); break; } + case OMPD_allocate: { + // FIXME: Should this be permitted in C++? + if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) == + ParsedStmtContext()) { + Diag(Tok, diag::err_omp_immediate_directive) + << getOpenMPDirectiveName(DKind) << 0; + } + ConsumeToken(); + 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. + 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()); + Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); + } + SkipUntil(tok::annot_pragma_openmp_end); + break; + } case OMPD_declare_reduction: ConsumeToken(); if (DeclGroupPtrTy Res = @@ -1602,6 +1657,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); break; case OMPC_threadprivate: + case OMPC_allocate: case OMPC_uniform: if (!WrongDirective) Diag(Tok, diag::err_omp_unexpected_clause) diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index bd7f6db..5d8cffa 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -913,7 +913,8 @@ bool Parser::isStartOfFunctionDefinition(const ParsingDeclarator &Declarator) { /// declaration: [C99 6.7] /// declaration-specifiers init-declarator-list[opt] ';' /// [!C99] init-declarator-list ';' [TODO: warn in c99 mode] -/// [OMP] threadprivate-directive [TODO] +/// [OMP] threadprivate-directive +/// [OMP] allocate-directive [TODO] /// Parser::DeclGroupPtrTy Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs, diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 7fed372..6c4c4a8 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -1908,7 +1908,8 @@ public: explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {} bool ValidateCandidate(const TypoCorrection &Candidate) override { NamedDecl *ND = Candidate.getCorrectionDecl(); - if (ND && (isa(ND) || isa(ND))) { + if (ND && ((isa(ND) && ND->getKind() == Decl::Var) || + isa(ND))) { return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(), SemaRef.getCurScope()); } @@ -1920,7 +1921,8 @@ public: ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec, - const DeclarationNameInfo &Id) { + const DeclarationNameInfo &Id, + OpenMPDirectiveKind Kind) { LookupResult Lookup(*this, Id, LookupOrdinaryName); LookupParsedName(Lookup, CurScope, &ScopeSpec, true); @@ -1953,9 +1955,9 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope, // OpenMP [2.9.2, Syntax, C/C++] // Variables must be file-scope, namespace-scope, or static block-scope. - if (!VD->hasGlobalStorage()) { + if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) { Diag(Id.getLoc(), diag::err_omp_global_var_arg) - << getOpenMPDirectiveName(OMPD_threadprivate) << !VD->isStaticLocal(); + << getOpenMPDirectiveName(Kind) << !VD->isStaticLocal(); bool IsDecl = VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; Diag(VD->getLocation(), @@ -1972,7 +1974,7 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope, if (CanonicalVD->getDeclContext()->isTranslationUnit() && !getCurLexicalContext()->isTranslationUnit()) { Diag(Id.getLoc(), diag::err_omp_var_scope) - << getOpenMPDirectiveName(OMPD_threadprivate) << VD; + << getOpenMPDirectiveName(Kind) << VD; bool IsDecl = VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; Diag(VD->getLocation(), @@ -1987,7 +1989,7 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope, if (CanonicalVD->isStaticDataMember() && !CanonicalVD->getDeclContext()->Equals(getCurLexicalContext())) { Diag(Id.getLoc(), diag::err_omp_var_scope) - << getOpenMPDirectiveName(OMPD_threadprivate) << VD; + << getOpenMPDirectiveName(Kind) << VD; bool IsDecl = VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; Diag(VD->getLocation(), @@ -2003,7 +2005,7 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope, (!getCurLexicalContext()->isFileContext() || !getCurLexicalContext()->Encloses(CanonicalVD->getDeclContext()))) { Diag(Id.getLoc(), diag::err_omp_var_scope) - << getOpenMPDirectiveName(OMPD_threadprivate) << VD; + << getOpenMPDirectiveName(Kind) << VD; bool IsDecl = VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; Diag(VD->getLocation(), @@ -2014,10 +2016,10 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope, // OpenMP [2.9.2, Restrictions, C/C++, p.6] // A threadprivate directive for static block-scope variables must appear // in the scope of the variable and not in a nested scope. - if (CanonicalVD->isStaticLocal() && CurScope && + if (CanonicalVD->isLocalVarDecl() && CurScope && !isDeclInScope(ND, getCurLexicalContext(), CurScope)) { Diag(Id.getLoc(), diag::err_omp_var_scope) - << getOpenMPDirectiveName(OMPD_threadprivate) << VD; + << getOpenMPDirectiveName(Kind) << VD; bool IsDecl = VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; Diag(VD->getLocation(), @@ -2029,9 +2031,10 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope, // OpenMP [2.9.2, Restrictions, C/C++, p.2-6] // A threadprivate directive must lexically precede all references to any // of the variables in its list. - if (VD->isUsed() && !DSAStack->isThreadPrivate(VD)) { + if (Kind == OMPD_threadprivate && VD->isUsed() && + !DSAStack->isThreadPrivate(VD)) { Diag(Id.getLoc(), diag::err_omp_var_used) - << getOpenMPDirectiveName(OMPD_threadprivate) << VD; + << getOpenMPDirectiveName(Kind) << VD; return ExprError(); } @@ -2164,6 +2167,41 @@ Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef VarList) { } Sema::DeclGroupPtrTy +Sema::ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef VarList, + DeclContext *Owner) { + SmallVector Vars; + for (Expr *RefExpr : VarList) { + auto *DE = cast(RefExpr); + auto *VD = cast(DE->getDecl()); + + // Check if this is a TLS variable or global register. + if (VD->getTLSKind() != VarDecl::TLS_None || + VD->hasAttr() || + (VD->getStorageClass() == SC_Register && VD->hasAttr() && + !VD->isLocalVarDecl())) + continue; + // Do not apply for parameters. + if (isa(VD)) + continue; + + Vars.push_back(RefExpr); + VD->addAttr( + OMPAllocateDeclAttr::CreateImplicit(Context, DE->getSourceRange())); + if (ASTMutationListener *ML = Context.getASTMutationListener()) + ML->DeclarationMarkedOpenMPAllocate(VD, + VD->getAttr()); + } + if (Vars.empty()) + return nullptr; + if (!Owner) + Owner = getCurLexicalContext(); + OMPAllocateDecl *D = OMPAllocateDecl::Create(Context, Owner, Loc, Vars); + D->setAccess(AS_public); + Owner->addDecl(D); + return DeclGroupPtrTy::make(DeclGroupRef(D)); +} + +Sema::DeclGroupPtrTy Sema::ActOnOpenMPRequiresDirective(SourceLocation Loc, ArrayRef ClauseList) { OMPRequiresDecl *D = nullptr; @@ -2863,6 +2901,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { break; } case OMPD_threadprivate: + case OMPD_allocate: case OMPD_taskyield: case OMPD_barrier: case OMPD_taskwait: @@ -3719,6 +3758,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( case OMPD_declare_target: case OMPD_end_declare_target: case OMPD_threadprivate: + case OMPD_allocate: case OMPD_declare_reduction: case OMPD_declare_mapper: case OMPD_declare_simd: @@ -8398,6 +8438,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, case OMPC_untied: case OMPC_mergeable: case OMPC_threadprivate: + case OMPC_allocate: case OMPC_flush: case OMPC_read: case OMPC_write: @@ -8482,6 +8523,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( // Do not capture if-clause expressions. break; case OMPD_threadprivate: + case OMPD_allocate: case OMPD_taskyield: case OMPD_barrier: case OMPD_taskwait: @@ -8549,6 +8591,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_taskloop: case OMPD_taskloop_simd: case OMPD_threadprivate: + case OMPD_allocate: case OMPD_taskyield: case OMPD_barrier: case OMPD_taskwait: @@ -8617,6 +8660,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_target_parallel_for: case OMPD_target_parallel_for_simd: case OMPD_threadprivate: + case OMPD_allocate: case OMPD_taskyield: case OMPD_barrier: case OMPD_taskwait: @@ -8682,6 +8726,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_target_parallel_for: case OMPD_target_parallel_for_simd: case OMPD_threadprivate: + case OMPD_allocate: case OMPD_taskyield: case OMPD_barrier: case OMPD_taskwait: @@ -8748,6 +8793,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_parallel: case OMPD_parallel_sections: case OMPD_threadprivate: + case OMPD_allocate: case OMPD_taskyield: case OMPD_barrier: case OMPD_taskwait: @@ -8813,6 +8859,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_parallel: case OMPD_parallel_sections: case OMPD_threadprivate: + case OMPD_allocate: case OMPD_taskyield: case OMPD_barrier: case OMPD_taskwait: @@ -8877,6 +8924,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_parallel_for: case OMPD_parallel_for_simd: case OMPD_threadprivate: + case OMPD_allocate: case OMPD_taskyield: case OMPD_barrier: case OMPD_taskwait: @@ -8928,6 +8976,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPC_untied: case OMPC_mergeable: case OMPC_threadprivate: + case OMPC_allocate: case OMPC_flush: case OMPC_read: case OMPC_write: @@ -9251,6 +9300,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause( case OMPC_untied: case OMPC_mergeable: case OMPC_threadprivate: + case OMPC_allocate: case OMPC_flush: case OMPC_read: case OMPC_write: @@ -9428,6 +9478,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause( case OMPC_untied: case OMPC_mergeable: case OMPC_threadprivate: + case OMPC_allocate: case OMPC_flush: case OMPC_read: case OMPC_write: @@ -9645,6 +9696,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind, case OMPC_default: case OMPC_proc_bind: case OMPC_threadprivate: + case OMPC_allocate: case OMPC_flush: case OMPC_depend: case OMPC_device: @@ -9841,6 +9893,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause( case OMPC_untied: case OMPC_mergeable: case OMPC_threadprivate: + case OMPC_allocate: case OMPC_read: case OMPC_write: case OMPC_update: diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index db63529..73909fe 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2876,6 +2876,21 @@ Decl *TemplateDeclInstantiator::VisitOMPThreadPrivateDecl( return TD; } +Decl *TemplateDeclInstantiator::VisitOMPAllocateDecl(OMPAllocateDecl *D) { + SmallVector Vars; + for (auto *I : D->varlists()) { + Expr *Var = SemaRef.SubstExpr(I, TemplateArgs).get(); + assert(isa(Var) && "allocate arg is not a DeclRefExpr"); + Vars.push_back(Var); + } + + Sema::DeclGroupPtrTy Res = + SemaRef.ActOnOpenMPAllocateDirective(D->getLocation(), Vars, Owner); + if (Res.get().isNull()) + return nullptr; + return Res.get().getSingleDecl(); +} + Decl *TemplateDeclInstantiator::VisitOMPRequiresDecl(OMPRequiresDecl *D) { llvm_unreachable( "Requires directive cannot be instantiated within a dependent context"); diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp index 1e15cb4..de95825 100644 --- a/clang/lib/Serialization/ASTCommon.cpp +++ b/clang/lib/Serialization/ASTCommon.cpp @@ -387,6 +387,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) { case Decl::ClassScopeFunctionSpecialization: case Decl::Import: case Decl::OMPThreadPrivate: + case Decl::OMPAllocate: case Decl::OMPRequires: case Decl::OMPCapturedExpr: case Decl::OMPDeclareReduction: diff --git a/clang/lib/Serialization/ASTCommon.h b/clang/lib/Serialization/ASTCommon.h index 2678103..296642e 100644 --- a/clang/lib/Serialization/ASTCommon.h +++ b/clang/lib/Serialization/ASTCommon.h @@ -38,6 +38,7 @@ enum DeclUpdateKind { UPD_MANGLING_NUMBER, UPD_STATIC_LOCAL_NUMBER, UPD_DECL_MARKED_OPENMP_THREADPRIVATE, + UPD_DECL_MARKED_OPENMP_ALLOCATE, UPD_DECL_MARKED_OPENMP_DECLARETARGET, UPD_DECL_EXPORTED, UPD_ADDED_ATTR_TO_RECORD diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index fb56170..760489d 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -444,6 +444,7 @@ namespace clang { void VisitObjCPropertyDecl(ObjCPropertyDecl *D); void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D); + void VisitOMPAllocateDecl(OMPAllocateDecl *D); void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D); void VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D); void VisitOMPRequiresDecl(OMPRequiresDecl *D); @@ -2633,6 +2634,17 @@ void ASTDeclReader::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { D->setVars(Vars); } +void ASTDeclReader::VisitOMPAllocateDecl(OMPAllocateDecl *D) { + VisitDecl(D); + unsigned NumVars = D->varlist_size(); + SmallVector Vars; + Vars.reserve(NumVars); + for (unsigned i = 0; i != NumVars; ++i) { + Vars.push_back(Record.readExpr()); + } + D->setVars(Vars); +} + void ASTDeclReader::VisitOMPRequiresDecl(OMPRequiresDecl * D) { VisitDecl(D); unsigned NumClauses = D->clauselist_size(); @@ -2795,7 +2807,7 @@ static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) { isa(D)) return true; if (isa(D) || isa(D) || - isa(D)) + isa(D) || isa(D)) return !D->getDeclContext()->isFunctionOrMethod(); if (const auto *Var = dyn_cast(D)) return Var->isFileVarDecl() && @@ -3866,6 +3878,9 @@ 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()); + break; case DECL_OMP_REQUIRES: D = OMPRequiresDecl::CreateDeserialized(Context, ID, Record.readInt()); break; @@ -4465,6 +4480,11 @@ void ASTDeclReader::UpdateDecl(Decl *D, ReadSourceRange())); break; + case UPD_DECL_MARKED_OPENMP_ALLOCATE: + D->addAttr(OMPAllocateDeclAttr::CreateImplicit(Reader.getContext(), + ReadSourceRange())); + break; + case UPD_DECL_EXPORTED: { unsigned SubmoduleID = readSubmoduleID(); auto *Exported = cast(D); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 3d19c9d..06c477e 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -1298,6 +1298,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(DECL_PRAGMA_COMMENT); RECORD(DECL_PRAGMA_DETECT_MISMATCH); RECORD(DECL_OMP_DECLARE_REDUCTION); + RECORD(DECL_OMP_ALLOCATE); // Statements and Exprs can occur in the Decls and Types block. AddStmtsExprs(Stream, Record); @@ -5287,6 +5288,10 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { D->getAttr()->getRange()); break; + case UPD_DECL_MARKED_OPENMP_ALLOCATE: + Record.AddSourceRange(D->getAttr()->getRange()); + break; + case UPD_DECL_MARKED_OPENMP_DECLARETARGET: Record.push_back(D->getAttr()->getMapType()); Record.AddSourceRange( @@ -6404,6 +6409,15 @@ void ASTWriter::DeclarationMarkedOpenMPThreadPrivate(const Decl *D) { DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_OPENMP_THREADPRIVATE)); } +void ASTWriter::DeclarationMarkedOpenMPAllocate(const Decl *D, const Attr *A) { + if (Chain && Chain->isProcessingUpdateRecords()) return; + assert(!WritingAST && "Already writing the AST!"); + if (!D->isFromASTFile()) + return; + + DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_OPENMP_ALLOCATE, A)); +} + void ASTWriter::DeclarationMarkedOpenMPDeclareTarget(const Decl *D, const Attr *Attr) { if (Chain && Chain->isProcessingUpdateRecords()) return; diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 6de1320..cfcd81b 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -144,6 +144,7 @@ namespace clang { void VisitObjCPropertyDecl(ObjCPropertyDecl *D); void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D); + void VisitOMPAllocateDecl(OMPAllocateDecl *D); void VisitOMPRequiresDecl(OMPRequiresDecl *D); void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D); void VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D); @@ -1744,10 +1745,18 @@ void ASTDeclWriter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { Code = serialization::DECL_OMP_THREADPRIVATE; } +void ASTDeclWriter::VisitOMPAllocateDecl(OMPAllocateDecl *D) { + Record.push_back(D->varlist_size()); + VisitDecl(D); + for (auto *I : D->varlists()) + Record.AddStmt(I); + Code = serialization::DECL_OMP_ALLOCATE; +} + void ASTDeclWriter::VisitOMPRequiresDecl(OMPRequiresDecl *D) { Record.push_back(D->clauselist_size()); VisitDecl(D); - OMPClauseWriter ClauseWriter(Record); + OMPClauseWriter ClauseWriter(Record); for (OMPClause *C : D->clauselists()) ClauseWriter.writeClause(C); Code = serialization::DECL_OMP_REQUIRES; diff --git a/clang/test/OpenMP/allocate_ast_print.cpp b/clang/test/OpenMP/allocate_ast_print.cpp new file mode 100644 index 0000000..bd0a7e8 --- /dev/null +++ b/clang/test/OpenMP/allocate_ast_print.cpp @@ -0,0 +1,79 @@ +// 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 + +struct St{ + int a; +}; + +struct St1{ + int a; + static int b; +// CHECK: static int b; +#pragma omp allocate(b) +// CHECK-NEXT: #pragma omp allocate(St1::b){{$}} +} d; + +int a, b; +// CHECK: int a; +// CHECK: int b; +#pragma omp allocate(a) +#pragma omp allocate(a) +// CHECK-NEXT: #pragma omp allocate(a) +// CHECK-NEXT: #pragma omp allocate(a) +#pragma omp allocate(d, b) +// CHECK-NEXT: #pragma omp allocate(d,b) + +template +struct ST { + static T m; + #pragma omp allocate(m) +}; + +template T foo() { + T v; + #pragma omp allocate(v) + v = ST::m; + return v; +} +//CHECK: template T foo() { +//CHECK-NEXT: T v; +//CHECK-NEXT: #pragma omp allocate(v) +//CHECK: template<> int foo() { +//CHECK-NEXT: int v; +//CHECK-NEXT: #pragma omp allocate(v) + +namespace ns{ + int a; +} +// CHECK: namespace ns { +// CHECK-NEXT: int a; +// CHECK-NEXT: } +#pragma omp allocate(ns::a) +// CHECK-NEXT: #pragma omp allocate(ns::a) + +int main () { + static int a; +// CHECK: static int a; +#pragma omp allocate(a) +// CHECK-NEXT: #pragma omp allocate(a) + a=2; + return (foo()); +} + +extern template int ST::m; +#endif diff --git a/clang/test/OpenMP/allocate_messages.cpp b/clang/test/OpenMP/allocate_messages.cpp new file mode 100644 index 0000000..2d40f79 --- /dev/null +++ b/clang/test/OpenMP/allocate_messages.cpp @@ -0,0 +1,149 @@ +// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -fnoopenmp-use-tls -ferror-limit 100 -emit-llvm -o - %s +// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -emit-llvm -o - %s + +// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -fnoopenmp-use-tls -ferror-limit 100 -emit-llvm -o - %s +// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -emit-llvm -o - %s + +#pragma omp allocate // expected-error {{expected '(' after 'allocate'}} +#pragma omp allocate( // expected-error {{expected identifier}} expected-error {{expected ')'}} expected-note {{to match this '('}} +#pragma omp allocate() // expected-error {{expected identifier}} +#pragma omp allocate(1) // expected-error {{expected unqualified-id}} +struct CompleteSt { + int a; +}; + +struct CompleteSt1 { +#pragma omp allocate(1) // expected-error {{expected unqualified-id}} + int a; +} d; // expected-note {{'d' defined here}} + +int a; // expected-note {{'a' defined here}} + +#pragma omp allocate(a) +#pragma omp allocate(u) // expected-error {{use of undeclared identifier 'u'}} +#pragma omp allocate(d, a) +int foo() { // expected-note {{declared here}} + static int l; +#pragma omp allocate(l)) // expected-warning {{extra tokens at the end of '#pragma omp allocate' are ignored}} + return (a); +} + +#pragma omp allocate(a)( +// expected-warning@-1 {{extra tokens at the end of '#pragma omp allocate' are ignored}} +#pragma omp allocate(a)[ // expected-warning {{extra tokens at the end of '#pragma omp allocate' are ignored}} +#pragma omp allocate(a) { // expected-warning {{extra tokens at the end of '#pragma omp allocate' are ignored}} +#pragma omp allocate(a)) // expected-warning {{extra tokens at the end of '#pragma omp allocate' are ignored}} +#pragma omp allocate(a)] // expected-warning {{extra tokens at the end of '#pragma omp allocate' are ignored}} +#pragma omp allocate(a) } // expected-warning {{extra tokens at the end of '#pragma omp allocate' are ignored}} +#pragma omp allocate a // expected-error {{expected '(' after 'allocate'}} +#pragma omp allocate(d // expected-error {{expected ')'}} expected-note {{to match this '('}} +#pragma omp allocate(d)) // expected-warning {{extra tokens at the end of '#pragma omp allocate' are ignored}} +int x, y; +#pragma omp allocate(x)) // expected-warning {{extra tokens at the end of '#pragma omp allocate' are ignored}} +#pragma omp allocate(y)), +// expected-warning@-1 {{extra tokens at the end of '#pragma omp allocate' are ignored}} +#pragma omp allocate(a, d) +#pragma omp allocate(d.a) // expected-error {{expected identifier}} +#pragma omp allocate((float)a) // expected-error {{expected unqualified-id}} +int foa; // expected-note {{'foa' declared here}} +#pragma omp allocate(faa) // expected-error {{use of undeclared identifier 'faa'; did you mean 'foa'?}} +#pragma omp allocate(foo) // expected-error {{'foo' is not a global variable, static local variable or static data member}} +#pragma omp allocate(int a = 2) // expected-error {{expected unqualified-id}} + +struct IncompleteSt; + +extern IncompleteSt e; +#pragma omp allocate(e) + +int &f = a; +#pragma omp allocate(f) + +class TestClass { +private: + int a; // expected-note {{declared here}} + static int b; // expected-note {{'b' declared here}} + TestClass() : a(0) {} + +public: + TestClass(int aaa) : a(aaa) {} +#pragma omp allocate(b, a) // expected-error {{'a' is not a global variable, static local variable or static data member}} +} g(10); +#pragma omp allocate(b) // expected-error {{use of undeclared identifier 'b'}} +#pragma omp allocate(TestClass::b) // expected-error {{'#pragma omp allocate' must appear in the scope of the 'TestClass::b' variable declaration}} +#pragma omp allocate(g) + +namespace ns { +int m; +#pragma omp allocate(m, m) +} // namespace ns +#pragma omp allocate(m) // expected-error {{use of undeclared identifier 'm'}} +#pragma omp allocate(ns::m) +#pragma omp allocate(ns \ + : m) // expected-error {{unexpected ':' in nested name specifier; did you mean '::'?}} + +const int h = 12; +const volatile int i = 10; +#pragma omp allocate(h, i) + +template +class TempClass { +private: + T a; + TempClass() : a() {} + +public: + TempClass(T aaa) : a(aaa) {} + static T s; +#pragma omp allocate(s) +}; +#pragma omp allocate(s) // expected-error {{use of undeclared identifier 's'}} + +static __thread int t; +#pragma omp allocate(t) + +// Register "0" is currently an invalid register for global register variables. +// Use "esp" instead of "0". +// register int reg0 __asm__("0"); +register int reg0 __asm__("esp"); +#pragma omp allocate(reg0) + +int o; // expected-note {{candidate found by name lookup is 'o'}} +#pragma omp allocate(o) +namespace { +int o; // expected-note {{candidate found by name lookup is '(anonymous namespace)::o'}} +#pragma omp allocate(o) +#pragma omp allocate(o) +} // namespace +#pragma omp allocate(o) // expected-error {{reference to 'o' is ambiguous}} +#pragma omp allocate(::o) + +int main(int argc, char **argv) { + + int x, y = argc; + static double d1; + static double d2; + static double d3; // expected-note {{'d3' defined here}} + static double d4; + static TestClass LocalClass(y); +#pragma omp allocate(LocalClass) + + d.a = a; + d2++; + ; +#pragma omp allocate(argc + y) // expected-error {{expected identifier}} +#pragma omp allocate(argc, y) +#pragma omp allocate(d2) +#pragma omp allocate(d1) + { + ++a; + d2 = 0; +#pragma omp allocate(d3) // expected-error {{'#pragma omp allocate' must appear in the scope of the 'd3' variable declaration}} + } +#pragma omp allocate(d3) +label: +#pragma omp allocate(d4) // expected-error {{'#pragma omp allocate' cannot be an immediate substatement}} + +#pragma omp allocate(a) // expected-error {{'#pragma omp allocate' must appear in the scope of the 'a' variable declaration}} + return (y); +#pragma omp allocate(d) // expected-error {{'#pragma omp allocate' must appear in the scope of the 'd' variable declaration}} +} diff --git a/clang/test/PCH/chain-openmp-allocate.cpp b/clang/test/PCH/chain-openmp-allocate.cpp new file mode 100644 index 0000000..ea529b5 --- /dev/null +++ b/clang/test/PCH/chain-openmp-allocate.cpp @@ -0,0 +1,36 @@ +// no PCH +// RUN: %clang_cc1 -fopenmp -fnoopenmp-use-tls -ast-print -include %s -include %s %s -o - | FileCheck %s +// with PCH +// RUN: %clang_cc1 -fopenmp -fnoopenmp-use-tls -ast-print -chain-include %s -chain-include %s %s -o - | FileCheck %s +// no PCH +// RUN: %clang_cc1 -fopenmp -ast-print -include %s -include %s %s -o - | FileCheck %s -check-prefix=CHECK-ALLOC-1 +// RUN: %clang_cc1 -fopenmp -ast-print -include %s -include %s %s -o - | FileCheck %s -check-prefix=CHECK-ALLOC-2 +// with PCH +// RUN: %clang_cc1 -fopenmp -ast-print -chain-include %s -chain-include %s %s -o - | FileCheck %s -check-prefix=CHECK-ALLOC-1 +// RUN: %clang_cc1 -fopenmp -ast-print -chain-include %s -chain-include %s %s -o - | FileCheck %s -check-prefix=CHECK-ALLOC-2 + +#if !defined(PASS1) +#define PASS1 + +int a; +// CHECK: int a; + +#elif !defined(PASS2) +#define PASS2 + +#pragma omp allocate(a) +// CHECK: #pragma omp allocate(a) + +#else + +// CHECK-LABEL: foo +// CHECK-ALLOC-LABEL: foo +int foo() { + return a; + // CHECK: return a; + // CHECK-ALLOC-1: return a; +} + +// CHECK-ALLOC-2: return a; + +#endif diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 07e052b..fa4ac48 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -6233,6 +6233,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) { case Decl::CXXDeductionGuide: case Decl::Import: case Decl::OMPThreadPrivate: + case Decl::OMPAllocate: case Decl::OMPDeclareReduction: case Decl::OMPDeclareMapper: case Decl::OMPRequires: -- 2.7.4