Index: clang/include/clang/AST/OpenMPClause.h =================================================================== --- clang/include/clang/AST/OpenMPClause.h +++ clang/include/clang/AST/OpenMPClause.h @@ -5745,7 +5745,7 @@ size_t numTrailingObjects(OverloadToken) const { // There are varlist_size() of expressions, and varlist_size() of // user-defined mappers. - return 2 * varlist_size(); + return 2 * varlist_size() + 1; } size_t numTrailingObjects(OverloadToken) const { return getUniqueDeclarationsNum(); @@ -5759,7 +5759,7 @@ OpenMPMapModifierKind MapTypeModifiers[NumberOfOMPMapClauseModifiers] = { OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown, - OMPC_MAP_MODIFIER_unknown}; + OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown}; /// Location of map-type-modifiers for the 'map' clause. SourceLocation MapTypeModifiersLoc[NumberOfOMPMapClauseModifiers]; @@ -5860,6 +5860,11 @@ /// Set colon location. void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } + /// Set iterator modifier. + void setIteratorModifier(Expr *IteratorModifier) { + getTrailingObjects()[2 * varlist_size()] = IteratorModifier; + } + public: /// Creates clause with a list of variables \a VL. /// @@ -5872,6 +5877,7 @@ /// \param ComponentLists Component lists used in the clause. /// \param UDMapperRefs References to user-defined mappers associated with /// expressions used in the clause. + /// \param IteratorModifier Iterator modifier. /// \param MapModifiers Map-type-modifiers. /// \param MapModifiersLoc Location of map-type-modifiers. /// \param UDMQualifierLoc C++ nested name specifier for the associated @@ -5884,7 +5890,7 @@ Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef Vars, ArrayRef Declarations, MappableExprComponentListsRef ComponentLists, - ArrayRef UDMapperRefs, + ArrayRef UDMapperRefs, Expr *IteratorModifier, ArrayRef MapModifiers, ArrayRef MapModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId, @@ -5903,6 +5909,11 @@ static OMPMapClause *CreateEmpty(const ASTContext &C, const OMPMappableExprListSizeTy &Sizes); + /// Fetches Expr * of iterator modifier. + Expr *getIteratorModifier() { + return getTrailingObjects()[2 * varlist_size()]; + } + /// Fetches mapping kind for the clause. OpenMPMapClauseKind getMapType() const LLVM_READONLY { return MapType; } Index: clang/include/clang/Basic/DiagnosticParseKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticParseKinds.td +++ clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1362,7 +1362,7 @@ "incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'">; def err_omp_unknown_map_type_modifier : Error< "incorrect map type modifier, expected one of: 'always', 'close', 'mapper'" - "%select{|, 'present'}0%select{|, 'ompx_hold'}1">; + "%select{|, 'present'|, 'present', 'iterator'}0%select{|, 'ompx_hold'}1">; def err_omp_map_type_missing : Error< "missing map type">; def err_omp_map_type_modifier_missing : Error< Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10849,6 +10849,8 @@ "depend modifier cannot be used with 'sink' or 'source' depend type">; def err_omp_depend_modifier_not_iterator : Error< "expected iterator specification as depend modifier">; +def err_omp_map_modifier_not_iterator : Error< + "expected iterator specification as map modifier">; def err_omp_linear_ordered : Error< "'linear' clause cannot be specified along with 'ordered' clause with a parameter">; def err_omp_unexpected_schedule_modifier : Error< Index: clang/include/clang/Basic/OpenMPKinds.h =================================================================== --- clang/include/clang/Basic/OpenMPKinds.h +++ clang/include/clang/Basic/OpenMPKinds.h @@ -83,7 +83,7 @@ OMPC_MAP_MODIFIER_last }; - /// Number of allowed map-type-modifiers. +/// Number of allowed map-type-modifiers. static constexpr unsigned NumberOfOMPMapClauseModifiers = OMPC_MAP_MODIFIER_last - OMPC_MAP_MODIFIER_unknown - 1; Index: clang/include/clang/Basic/OpenMPKinds.def =================================================================== --- clang/include/clang/Basic/OpenMPKinds.def +++ clang/include/clang/Basic/OpenMPKinds.def @@ -154,6 +154,7 @@ OPENMP_MAP_MODIFIER_KIND(always) OPENMP_MAP_MODIFIER_KIND(close) OPENMP_MAP_MODIFIER_KIND(mapper) +OPENMP_MAP_MODIFIER_KIND(iterator) OPENMP_MAP_MODIFIER_KIND(present) // This is an OpenMP extension for the sake of OpenACC support. OPENMP_MAP_MODIFIER_KIND(ompx_hold) Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -11133,6 +11133,7 @@ QualType MapperType, SourceLocation StartLoc, DeclarationName VN); + void ActOnOpenMPIteratorVarDecl(VarDecl *VD); bool isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const; const ValueDecl *getOpenMPDeclareMapperVarName() const; @@ -11877,6 +11878,7 @@ /// Data used for processing a list of variables in OpenMP clauses. struct OpenMPVarListDataTy final { Expr *DepModOrTailExpr = nullptr; + Expr *IteratorExpr = nullptr; SourceLocation ColonLoc; SourceLocation RLoc; CXXScopeSpec ReductionOrMapperIdScopeSpec; @@ -12003,7 +12005,7 @@ SourceLocation EndLoc); /// Called on well-formed 'map' clause. OMPClause *ActOnOpenMPMapClause( - ArrayRef MapTypeModifiers, + Expr *IteratorModifier, ArrayRef MapTypeModifiers, ArrayRef MapTypeModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, Index: clang/lib/AST/OpenMPClause.cpp =================================================================== --- clang/lib/AST/OpenMPClause.cpp +++ clang/lib/AST/OpenMPClause.cpp @@ -1133,7 +1133,7 @@ const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef Vars, ArrayRef Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef UDMapperRefs, - ArrayRef MapModifiers, + Expr *IteratorModifier, ArrayRef MapModifiers, ArrayRef MapModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId, OpenMPMapClauseKind Type, bool TypeIsImplicit, SourceLocation TypeLoc) { @@ -1156,7 +1156,7 @@ void *Mem = C.Allocate( totalSizeToAlloc( - 2 * Sizes.NumVars, Sizes.NumUniqueDeclarations, + 2 * Sizes.NumVars + 1, Sizes.NumUniqueDeclarations, Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, Sizes.NumComponents)); OMPMapClause *Clause = new (Mem) @@ -1165,6 +1165,7 @@ Clause->setVarRefs(Vars); Clause->setUDMapperRefs(UDMapperRefs); + Clause->setIteratorModifier(IteratorModifier); Clause->setClauseInfo(Declarations, ComponentLists); Clause->setMapType(Type); Clause->setMapLoc(TypeLoc); @@ -1177,10 +1178,12 @@ void *Mem = C.Allocate( totalSizeToAlloc( - 2 * Sizes.NumVars, Sizes.NumUniqueDeclarations, + 2 * Sizes.NumVars + 1, Sizes.NumUniqueDeclarations, Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, Sizes.NumComponents)); - return new (Mem) OMPMapClause(Sizes); + OMPMapClause *Clause = new (Mem) OMPMapClause(Sizes); + Clause->setIteratorModifier(nullptr); + return Clause; } OMPToClause *OMPToClause::Create( @@ -2248,16 +2251,27 @@ OS << Node->getMapperIdInfo() << ')'; } +template +static void PrintIterator(raw_ostream &OS, T *Node, + const PrintingPolicy &Policy) { + if (Expr *IteratorModifier = Node->getIteratorModifier()) + IteratorModifier->printPretty(OS, nullptr, Policy); +} + void OMPClausePrinter::VisitOMPMapClause(OMPMapClause *Node) { if (!Node->varlist_empty()) { OS << "map("; if (Node->getMapType() != OMPC_MAP_unknown) { for (unsigned I = 0; I < NumberOfOMPMapClauseModifiers; ++I) { if (Node->getMapTypeModifier(I) != OMPC_MAP_MODIFIER_unknown) { - OS << getOpenMPSimpleClauseTypeName(OMPC_map, - Node->getMapTypeModifier(I)); - if (Node->getMapTypeModifier(I) == OMPC_MAP_MODIFIER_mapper) - PrintMapper(OS, Node, Policy); + if (Node->getMapTypeModifier(I) == OMPC_MAP_MODIFIER_iterator) { + PrintIterator(OS, Node, Policy); + } else { + OS << getOpenMPSimpleClauseTypeName(OMPC_map, + Node->getMapTypeModifier(I)); + if (Node->getMapTypeModifier(I) == OMPC_MAP_MODIFIER_mapper) + PrintMapper(OS, Node, Policy); + } OS << ','; } } Index: clang/lib/Parse/ParseOpenMP.cpp =================================================================== --- clang/lib/Parse/ParseOpenMP.cpp +++ clang/lib/Parse/ParseOpenMP.cpp @@ -4130,7 +4130,8 @@ if (PP.LookAhead(0).is(tok::colon)) return false; Diag(Tok, diag::err_omp_unknown_map_type_modifier) - << (getLangOpts().OpenMP >= 51 ? 1 : 0) + << (getLangOpts().OpenMP >= 51 ? (getLangOpts().OpenMP >= 52 ? 2 : 1) + : 0) << getLangOpts().OpenMPExtensions; ConsumeToken(); } @@ -4319,6 +4320,7 @@ return true; bool HasIterator = false; + bool InvalidIterator = false; bool NeedRParenForLinear = false; BalancedDelimiterTracker LinearT(*this, tok::l_paren, tok::annot_pragma_openmp_end); @@ -4424,6 +4426,23 @@ Data.ColonLoc = ConsumeToken(); } } else if (Kind == OMPC_map) { + // Handle optional iterator map modifier. + if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") { + HasIterator = true; + EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope); + Data.MapTypeModifiers.push_back(OMPC_MAP_MODIFIER_iterator); + Data.MapTypeModifiersLoc.push_back(Tok.getLocation()); + ExprResult IteratorRes = ParseOpenMPIteratorsExpr(); + Data.IteratorExpr = IteratorRes.get(); + // Parse ',' + ExpectAndConsume(tok::comma); + if (getLangOpts().OpenMP < 52) { + Diag(Tok, diag::err_omp_unknown_map_type_modifier) + << (getLangOpts().OpenMP >= 51 ? 1 : 0) + << getLangOpts().OpenMPExtensions; + InvalidIterator = true; + } + } // Handle map type for map clause. ColonProtectionRAIIObject ColonRAII(*this); @@ -4621,7 +4640,7 @@ ExitScope(); return (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) || (MustHaveTail && !Data.DepModOrTailExpr) || InvalidReductionId || - IsInvalidMapperModifier; + IsInvalidMapperModifier || InvalidIterator; } /// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate', Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -351,7 +351,8 @@ // [OpenMP 5.0], 2.19.7.3. declare mapper Directive, Restrictions // List-items in map clauses on this construct may only refer to the declared // variable var and entities that could be referenced by a procedure defined - // at the same location + // at the same location. + // [OpenMP 5.2] Also allow iterator declared variables. if (LangOpts.OpenMP && isa(D) && !isOpenMPDeclareMapperVarDeclAllowed(cast(D))) { Diag(Loc, diag::err_omp_declare_mapper_wrong_var) @@ -5419,6 +5420,10 @@ } else { CurContext->addDecl(VD); } + + /// Act on the iterator variable declaration. + ActOnOpenMPIteratorVarDecl(VD); + Expr *Begin = D.Range.Begin; if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) { ExprResult BeginRes = Index: clang/lib/Sema/SemaOpenMP.cpp =================================================================== --- clang/lib/Sema/SemaOpenMP.cpp +++ clang/lib/Sema/SemaOpenMP.cpp @@ -214,6 +214,7 @@ llvm::SmallVector ImplicitDefaultFirstprivateFDs; Expr *DeclareMapperVar = nullptr; + SmallVector IteratorVarDecls; SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name, Scope *CurScope, SourceLocation Loc) : Directive(DKind), DirectiveName(Name), CurScope(CurScope), @@ -1150,6 +1151,22 @@ const SharingMapTy *Top = getTopOfStackOrNull(); return Top ? Top->DeclareMapperVar : nullptr; } + + /// Add a new iterator variable. + void addIteratorVarDecl(VarDecl *VD) { + SharingMapTy &StackElem = getTopOfStack(); + StackElem.IteratorVarDecls.push_back(VD->getCanonicalDecl()); + } + /// Check if variable declaration is an iterator VarDecl. + bool isIteratorVarDecl(const VarDecl *VD) const { + const SharingMapTy *Top = getTopOfStackOrNull(); + if (!Top) + return false; + + return llvm::any_of(Top->IteratorVarDecls, [VD](const VarDecl *IteratorVD) { + return IteratorVD == VD->getCanonicalDecl(); + }); + } /// get captured field from ImplicitDefaultFirstprivateFDs VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const { const_iterator I = begin(); @@ -6070,7 +6087,7 @@ CXXScopeSpec MapperIdScopeSpec; DeclarationNameInfo MapperId; if (OMPClause *NewClause = S.ActOnOpenMPMapClause( - C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(), + nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(), MapperIdScopeSpec, MapperId, C->getMapType(), /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), SubExprs, OMPVarListLocTy())) @@ -6212,8 +6229,8 @@ CXXScopeSpec MapperIdScopeSpec; DeclarationNameInfo MapperId; if (OMPClause *Implicit = ActOnOpenMPMapClause( - OMPC_MAP_MODIFIER_unknown, SourceLocation(), MapperIdScopeSpec, - MapperId, OMPC_MAP_tofrom, + nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(), + MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom, /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true)) ClausesWithImplicit.emplace_back(Implicit); @@ -6229,7 +6246,7 @@ DeclarationNameInfo MapperId; auto Kind = static_cast(ClauseKindCnt); if (OMPClause *Implicit = ActOnOpenMPMapClause( - ImplicitMapModifiers[I], ImplicitMapModifiersLoc[I], + nullptr, ImplicitMapModifiers[I], ImplicitMapModifiersLoc[I], MapperIdScopeSpec, MapperId, Kind, /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), ImplicitMap, OMPVarListLocTy())) { @@ -17770,7 +17787,7 @@ assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown && "Unexpected map modifier."); Res = ActOnOpenMPMapClause( - Data.MapTypeModifiers, Data.MapTypeModifiersLoc, + Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc, Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, static_cast(ExtraModifier), Data.IsMapTypeImplicit, ExtraModifierLoc, ColonLoc, VarList, Locs); @@ -21936,7 +21953,7 @@ } OMPClause *Sema::ActOnOpenMPMapClause( - ArrayRef MapTypeModifiers, + Expr *IteratorModifier, ArrayRef MapTypeModifiers, ArrayRef MapTypeModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc, @@ -21946,9 +21963,14 @@ OpenMPMapModifierKind Modifiers[] = { OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown, - OMPC_MAP_MODIFIER_unknown}; + OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown}; SourceLocation ModifiersLoc[NumberOfOMPMapClauseModifiers]; + if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType( + BuiltinType::OMPIterator)) + Diag(IteratorModifier->getExprLoc(), + diag::err_omp_map_modifier_not_iterator); + // Process map-type-modifiers, flag errors for duplicate modifiers. unsigned Count = 0; for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) { @@ -21972,11 +21994,11 @@ // We need to produce a map clause even if we don't have variables so that // other diagnostics related with non-existing map clauses are accurate. - return OMPMapClause::Create(Context, Locs, MVLI.ProcessedVarList, - MVLI.VarBaseDeclarations, MVLI.VarComponents, - MVLI.UDMapperList, Modifiers, ModifiersLoc, - MapperIdScopeSpec.getWithLocInContext(Context), - MapperId, MapType, IsMapTypeImplicit, MapLoc); + return OMPMapClause::Create( + Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations, + MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers, + ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(Context), MapperId, + MapType, IsMapTypeImplicit, MapLoc); } QualType Sema::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, @@ -22370,6 +22392,11 @@ return E; } +void Sema::ActOnOpenMPIteratorVarDecl(VarDecl *VD) { + if (DSAStack->getDeclareMapperVarRef()) + DSAStack->addIteratorVarDecl(VD); +} + bool Sema::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const { assert(LangOpts.OpenMP && "Expected OpenMP mode."); const Expr *Ref = DSAStack->getDeclareMapperVarRef(); @@ -22378,6 +22405,8 @@ return true; if (VD->isUsableInConstantExpressions(Context)) return true; + if (LangOpts.OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD)) + return true; return false; } return true; Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3682,9 +3682,10 @@ OMPVarListLocTy Locs(OldC->getBeginLoc(), OldC->getLParenLoc(), OldC->getEndLoc()); OMPClause *NewC = SemaRef.ActOnOpenMPMapClause( - OldC->getMapTypeModifiers(), OldC->getMapTypeModifiersLoc(), SS, - NewNameInfo, OldC->getMapType(), OldC->isImplicitMapType(), - OldC->getMapLoc(), OldC->getColonLoc(), NewVars, Locs); + OldC->getIteratorModifier(), OldC->getMapTypeModifiers(), + OldC->getMapTypeModifiersLoc(), SS, NewNameInfo, OldC->getMapType(), + OldC->isImplicitMapType(), OldC->getMapLoc(), OldC->getColonLoc(), + NewVars, Locs); Clauses.push_back(NewC); } SemaRef.EndOpenMPDSABlock(nullptr); Index: clang/lib/Sema/TreeTransform.h =================================================================== --- clang/lib/Sema/TreeTransform.h +++ clang/lib/Sema/TreeTransform.h @@ -1988,15 +1988,16 @@ /// By default, performs semantic analysis to build the new OpenMP clause. /// Subclasses may override this routine to provide different behavior. OMPClause *RebuildOMPMapClause( - ArrayRef MapTypeModifiers, + Expr *IteratorModifier, ArrayRef MapTypeModifiers, ArrayRef MapTypeModifiersLoc, CXXScopeSpec MapperIdScopeSpec, DeclarationNameInfo MapperId, OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef VarList, const OMPVarListLocTy &Locs, ArrayRef UnresolvedMappers) { return getSema().ActOnOpenMPMapClause( - MapTypeModifiers, MapTypeModifiersLoc, MapperIdScopeSpec, MapperId, - MapType, IsMapTypeImplicit, MapLoc, ColonLoc, VarList, Locs, + IteratorModifier, MapTypeModifiers, MapTypeModifiersLoc, + MapperIdScopeSpec, MapperId, MapType, IsMapTypeImplicit, MapLoc, + ColonLoc, VarList, Locs, /*NoDiagnose=*/false, UnresolvedMappers); } @@ -10315,6 +10316,13 @@ OMPClause *TreeTransform::TransformOMPMapClause(OMPMapClause *C) { OMPVarListLocTy Locs(C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); llvm::SmallVector Vars; + Expr *IteratorModifier = C->getIteratorModifier(); + if (IteratorModifier) { + ExprResult MapModRes = getDerived().TransformExpr(IteratorModifier); + if (MapModRes.isInvalid()) + return nullptr; + IteratorModifier = MapModRes.get(); + } CXXScopeSpec MapperIdScopeSpec; DeclarationNameInfo MapperIdInfo; llvm::SmallVector UnresolvedMappers; @@ -10322,9 +10330,9 @@ *this, C, Vars, MapperIdScopeSpec, MapperIdInfo, UnresolvedMappers)) return nullptr; return getDerived().RebuildOMPMapClause( - C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(), MapperIdScopeSpec, - MapperIdInfo, C->getMapType(), C->isImplicitMapType(), C->getMapLoc(), - C->getColonLoc(), Vars, Locs, UnresolvedMappers); + IteratorModifier, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(), + MapperIdScopeSpec, MapperIdInfo, C->getMapType(), C->isImplicitMapType(), + C->getMapLoc(), C->getColonLoc(), Vars, Locs, UnresolvedMappers); } template Index: clang/lib/Serialization/ASTReader.cpp =================================================================== --- clang/lib/Serialization/ASTReader.cpp +++ clang/lib/Serialization/ASTReader.cpp @@ -10769,10 +10769,13 @@ void OMPClauseReader::VisitOMPMapClause(OMPMapClause *C) { C->setLParenLoc(Record.readSourceLocation()); + bool HasIteratorModifier = false; for (unsigned I = 0; I < NumberOfOMPMapClauseModifiers; ++I) { C->setMapTypeModifier( I, static_cast(Record.readInt())); C->setMapTypeModifierLoc(I, Record.readSourceLocation()); + if (C->getMapTypeModifier(I) == OMPC_MAP_MODIFIER_iterator) + HasIteratorModifier = true; } C->setMapperQualifierLoc(Record.readNestedNameSpecifierLoc()); C->setMapperIdInfo(Record.readDeclarationNameInfo()); @@ -10797,6 +10800,9 @@ UDMappers.push_back(Record.readExpr()); C->setUDMapperRefs(UDMappers); + if (HasIteratorModifier) + C->setIteratorModifier(Record.readExpr()); + SmallVector Decls; Decls.reserve(UniqueDecls); for (unsigned i = 0; i < UniqueDecls; ++i) Index: clang/lib/Serialization/ASTWriter.cpp =================================================================== --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -6789,9 +6789,12 @@ Record.push_back(C->getTotalComponentListNum()); Record.push_back(C->getTotalComponentsNum()); Record.AddSourceLocation(C->getLParenLoc()); + bool HasIteratorModifier = false; for (unsigned I = 0; I < NumberOfOMPMapClauseModifiers; ++I) { Record.push_back(C->getMapTypeModifier(I)); Record.AddSourceLocation(C->getMapTypeModifierLoc(I)); + if (C->getMapTypeModifier(I) == OMPC_MAP_MODIFIER_iterator) + HasIteratorModifier = true; } Record.AddNestedNameSpecifierLoc(C->getMapperQualifierLoc()); Record.AddDeclarationNameInfo(C->getMapperIdInfo()); @@ -6802,6 +6805,8 @@ Record.AddStmt(E); for (auto *E : C->mapperlists()) Record.AddStmt(E); + if (HasIteratorModifier) + Record.AddStmt(C->getIteratorModifier()); for (auto *D : C->all_decls()) Record.AddDeclRef(D); for (auto N : C->all_num_lists()) Index: clang/test/OpenMP/declare_mapper_ast_print.c =================================================================== --- clang/test/OpenMP/declare_mapper_ast_print.c +++ clang/test/OpenMP/declare_mapper_ast_print.c @@ -13,6 +13,14 @@ // RUN: %clang_cc1 -DOMP51 -verify -fopenmp-simd -fopenmp-version=51 -ast-print %s | FileCheck -check-prefixes=CHECK,OMP51 %s // RUN: %clang_cc1 -DOMP51 -fopenmp-simd -fopenmp-version=51 -emit-pch -o %t %s // RUN: %clang_cc1 -DOMP51 -fopenmp-simd -fopenmp-version=51 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck -check-prefixes=CHECK,OMP51 %s + +// RUN: %clang_cc1 -DOMP52 -verify -fopenmp -fopenmp-version=52 -ast-print %s | FileCheck -check-prefixes=CHECK,OMP52 %s +// RUN: %clang_cc1 -DOMP52 -fopenmp -fopenmp-version=52 -emit-pch -o %t %s +// RUN: %clang_cc1 -DOMP52 -fopenmp -fopenmp-version=52 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck -check-prefixes=CHECK,OMP52 %s + +// RUN: %clang_cc1 -DOMP52 -verify -fopenmp-simd -fopenmp-version=52 -ast-print %s | FileCheck -check-prefixes=CHECK,OMP52 %s +// RUN: %clang_cc1 -DOMP52 -fopenmp-simd -fopenmp-version=52 -emit-pch -o %t %s +// RUN: %clang_cc1 -DOMP52 -fopenmp-simd -fopenmp-version=52 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck -check-prefixes=CHECK,OMP52 %s // expected-no-diagnostics #ifndef HEADER @@ -65,6 +73,10 @@ // OMP51: #pragma omp target update to(present, mapper(id): vv) from(present, mapper(default): dd[0:10]) #endif } +#ifdef OMP52 +#pragma omp declare mapper(id1: struct vec vvec) map(iterator(it=0:vvec.len:2), tofrom:vvec.data[it]) +// OMP52: #pragma omp declare mapper (id1 : struct vec vvec) map(iterator(int it = 0:vvec.len:2),tofrom: vvec.data[it]); +#endif return 0; } // CHECK: } Index: clang/test/OpenMP/declare_mapper_messages.c =================================================================== --- clang/test/OpenMP/declare_mapper_messages.c +++ clang/test/OpenMP/declare_mapper_messages.c @@ -1,5 +1,7 @@ // RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=52 -ferror-limit 100 -DOMP52 %s + // RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s int temp; // expected-note {{'temp' declared here}} @@ -27,6 +29,18 @@ #pragma omp declare mapper(default : struct vec kk) map(kk.data[0:2]) // expected-note {{previous definition is here}} #pragma omp declare mapper(struct vec v) map(v.len) // expected-error {{redefinition of user-defined mapper for type 'struct vec' with name 'default'}} #pragma omp declare mapper(int v) map(v) // expected-error {{mapper type must be of struct, union or class type}} +#ifdef OMP52 +#pragma omp declare mapper(id2: struct vec vvec) map(iterator(it=0:vvec.len:2), tofrom:vvec.data[it]) +int var; // expected-note {{'var' declared here}} +// expected-error@+1 {{only variable 'vvec' is allowed in map clauses of this 'omp declare mapper' directive}} +#pragma omp declare mapper(id3: struct vec vvec) map(iterator(it=0:vvec.len:2), tofrom:vvec.data[var]) +#else +// expected-error@+4 {{expected at least one clause on '#pragma omp declare mapper' directive}} +// expected-note@+3 {{'it' declared here}} +// expected-error@+2 {{only variable 'vvec' is allowed in map clauses of this 'omp declare mapper' directive}} +// expected-error@+1 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'ompx_hold'}} +#pragma omp declare mapper(id2: struct vec vvec) map(iterator(it=0:vvec.len:2), tofrom:vvec.data[it]) +#endif // OMP52 int fun(int arg) { #pragma omp declare mapper(id: struct vec v) map(v.len) @@ -64,7 +78,11 @@ #pragma omp target update to(mapper(aa :vv) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} #pragma omp target update to(mapper(ab):vv) // expected-error {{cannot find a valid user-defined mapper for type 'struct vec' with name 'ab'}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} #pragma omp target update to(mapper(ab):arr[0:2]) // expected-error {{cannot find a valid user-defined mapper for type 'struct vec' with name 'ab'}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#ifdef OMP52 +#pragma omp target update to(mapper(aa) a:vv) // expected-warning {{missing ':' after motion modifier - ignoring}} +#else #pragma omp target update to(mapper(aa) a:vv) // expected-warning {{missing ':' after ) - ignoring}} +#endif #pragma omp target update to(mapper(aa):d) // expected-error {{mapper type must be of struct, union or class type}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} #pragma omp target update to(mapper(aa):vv) to(mapper(aa):arr[0]) @@ -75,7 +93,11 @@ #pragma omp target update from(mapper(aa :vv) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} #pragma omp target update from(mapper(ab):vv) // expected-error {{cannot find a valid user-defined mapper for type 'struct vec' with name 'ab'}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} #pragma omp target update from(mapper(ab):arr[0:2]) // expected-error {{cannot find a valid user-defined mapper for type 'struct vec' with name 'ab'}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#ifdef OMP52 +#pragma omp target update from(mapper(aa) a:vv) // expected-warning {{missing ':' after motion modifier - ignoring}} +#else #pragma omp target update from(mapper(aa) a:vv) // expected-warning {{missing ':' after ) - ignoring}} +#endif #pragma omp target update from(mapper(aa):d) // expected-error {{mapper type must be of struct, union or class type}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} #pragma omp target update from(mapper(aa):vv) from(mapper(aa):arr[0]) } Index: clang/test/OpenMP/target_ast_print.cpp =================================================================== --- clang/test/OpenMP/target_ast_print.cpp +++ clang/test/OpenMP/target_ast_print.cpp @@ -1139,6 +1139,60 @@ } #endif // OMP51 +#ifdef OMP52 + +///==========================================================================/// +// RUN: %clang_cc1 -DOMP52 -verify -fopenmp -fopenmp-version=52 -ast-print %s | FileCheck %s --check-prefix OMP52 +// RUN: %clang_cc1 -DOMP52 -fopenmp -fopenmp-version=52 -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -DOMP52 -fopenmp -fopenmp-version=52 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s --check-prefix OMP52 + +// RUN: %clang_cc1 -DOMP52 -verify -fopenmp-simd -fopenmp-version=52 -ast-print %s | FileCheck %s --check-prefix OMP52 +// RUN: %clang_cc1 -DOMP52 -fopenmp-simd -fopenmp-version=52 -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -DOMP52 -fopenmp-simd -fopenmp-version=52 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s --check-prefix OMP52 + +void foo() {} + +template +T tmain(T argc, T *argv) { + int N = 100; + int v[N]; + #pragma omp target map(iterator(it = 0:N:2), to: v[it]) + foo(); + #pragma omp target map(iterator(it = 0:N:4), from: v[it]) + foo(); + + return 0; +} + +// OMP52: template T tmain(T argc, T *argv) { +// OMP52-NEXT: int N = 100; +// OMP52-NEXT: int v[N]; +// OMP52-NEXT: #pragma omp target map(iterator(int it = 0:N:2),to: v[it]) +// OMP52-NEXT: foo() +// OMP52-NEXT: #pragma omp target map(iterator(int it = 0:N:4),from: v[it]) +// OMP52-NEXT: foo() + +// OMP52-LABEL: int main(int argc, char **argv) { +int main (int argc, char **argv) { + int i, j, a[20], always, close; +// OMP52-NEXT: int i, j, a[20] +#pragma omp target +// OMP52-NEXT: #pragma omp target + foo(); +// OMP52-NEXT: foo(); +#pragma omp target map(iterator(it = 0:20:2), to: a[it]) +// OMP52-NEXT: #pragma omp target map(iterator(int it = 0:20:2),to: a[it]) + foo(); +// OMP52-NEXT: foo(); +#pragma omp target map(iterator(it = 0:20:4), from: a[it]) +// OMP52-NEXT: #pragma omp target map(iterator(int it = 0:20:4),from: a[it]) +foo(); +// OMP52-NEXT: foo(); + + return tmain(argc, &argc) + tmain(argv[0][0], argv[0]); +} +#endif // OMP52 + #ifdef OMPX // RUN: %clang_cc1 -DOMPX -verify -fopenmp -fopenmp-extensions -ast-print %s | FileCheck %s --check-prefix=OMPX Index: clang/test/OpenMP/target_map_messages.cpp =================================================================== --- clang/test/OpenMP/target_map_messages.cpp +++ clang/test/OpenMP/target_map_messages.cpp @@ -4,6 +4,7 @@ // RUN: %clang_cc1 -verify=expected,lt50,lt51,omp,lt51-omp -fopenmp -fno-openmp-extensions -fopenmp-version=45 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized // RUN: %clang_cc1 -verify=expected,ge50,lt51,omp,lt51-omp -fopenmp -fno-openmp-extensions -fopenmp-version=50 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized // RUN: %clang_cc1 -verify=expected,ge50,ge51,omp,ge51-omp -fopenmp -fno-openmp-extensions -fopenmp-version=51 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized +// RUN: %clang_cc1 -verify=expected,ge50,ge51,ge52,omp,ge52-omp -fopenmp -fno-openmp-extensions -fopenmp-version=52 -ferror-limit 300 %s -Wno-openmp-target -Wuninitialized // RUN: %clang_cc1 -DCCODE -verify -fopenmp -fno-openmp-extensions -ferror-limit 300 -x c %s -Wno-openmp -Wuninitialized // -fopenmp-simd, -fno-openmp-extensions @@ -158,23 +159,28 @@ // expected-error@+1 {{use of undeclared identifier 'present'}} #pragma omp target map(present) {} + // ge52-omp-error@+3 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}} // ge51-omp-error@+2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} // lt51-omp-error@+1 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} #pragma omp target map(ompx_hold, tofrom: c,f) {} + // ge52-omp-error@+3 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}} // ge51-omp-error@+2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} // lt51-omp-error@+1 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} #pragma omp target map(ompx_hold, tofrom: c[1:2],f) {} + // ge52-omp-error@+3 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}} // ge51-omp-error@+2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} // lt51-omp-error@+1 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} #pragma omp target map(ompx_hold, tofrom: c,f[1:2]) {} + // ge52-omp-error@+4 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}} // expected-error@+3 {{section length is unspecified and cannot be inferred because subscripted value is not an array}} // ge51-omp-error@+2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} // lt51-omp-error@+1 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} #pragma omp target map(ompx_hold, tofrom: c[:],f) {} + // ge52-omp-error@+4 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}} // expected-error@+3 {{section length is unspecified and cannot be inferred because subscripted value is not an array}} // ge51-omp-error@+2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} // lt51-omp-error@+1 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} @@ -191,11 +197,15 @@ // lt51-error@+1 2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} #pragma omp target map(present, present, tofrom: a) {} + // ge52-omp-error@+5 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}} + // ge52-omp-error@+4 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}} // ompx-error@+3 {{same map type modifier has been specified more than once}} // ge51-omp-error@+2 2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} // lt51-omp-error@+1 2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} #pragma omp target map(ompx_hold, ompx_hold, tofrom: a) {} + // ge52-omp-error@+9 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}} + // ge52-omp-error@+8 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}} // expected-error@+7 2 {{same map type modifier has been specified more than once}} // ge51-error@+6 {{same map type modifier has been specified more than once}} // lt51-ompx-error@+5 2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'ompx_hold'}} @@ -239,6 +249,36 @@ {} #pragma omp target map(([b[I]][bf])f) // lt50-error {{expected ',' or ']' in lambda capture list}} lt50-error {{expected ')'}} lt50-note {{to match this '('}} {} + // ge51-ompx-error@+4 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'ompx_hold'}} + // lt51-ompx-error@+3 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'ompx_hold'}} + // ge51-omp-error@+2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} + // lt51-omp-error@+1 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} + #pragma omp target map(iterator(it=0:10), tofrom:a) + {} + // ompx-error@+8 {{redefinition of 'it'}} + // ompx-note@+7 {{previous definition is here}} + // omp-error@+6 {{redefinition of 'it'}} + // omp-note@+5 {{previous definition is here}} + // ge51-ompx-error@+4 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'ompx_hold'}} + // lt51-ompx-error@+3 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'ompx_hold'}} + // ge51-omp-error@+2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} + // lt51-omp-error@+1 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} + #pragma omp target map(iterator(it=0:10, it=0:20), tofrom:a) + {} + // ge51-ompx-error@+6 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'ompx_hold'}} + // lt51-ompx-error@+5 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'ompx_hold'}} + // lt51-error@+4 {{expected '(' after 'iterator'}} + // ge51-error@+3 {{expected '(' after 'iterator'}} + // ge51-omp-error@+2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} + // lt51-omp-error@+1 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} + #pragma omp target map(iterator, tofrom:a) + {} + // ge51-ompx-error@+4 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'ompx_hold'}} + // lt51-ompx-error@+3 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'ompx_hold'}} + // ge51-omp-error@+2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} + // lt51-omp-error@+1 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} + #pragma omp target map(iterator(), tofrom:a) + {} return; } }; @@ -920,6 +960,24 @@ pos(i).y = i+1; } + // ge51-ompx-error@+4 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'ompx_hold'}} + // lt51-ompx-error@+3 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'ompx_hold'}} + // ge51-omp-error@+2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} + // lt51-omp-error@+1 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} + #pragma omp target map(iterator(it=0:10), tofrom:a[it]) + {} + + // ompx-error@+8 {{use of undeclared identifier 'itt'; did you mean 'it'?}} + // ompx-note@+7 {{'it' declared here}} + // omp-error@+6 {{use of undeclared identifier 'itt'; did you mean 'it'?}} + // omp-note@+5 {{'it' declared here}} + // ge51-ompx-error@+4 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'ompx_hold'}} + // lt51-ompx-error@+3 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'ompx_hold'}} + // ge51-omp-error@+2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}} + // lt51-omp-error@+1 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} + #pragma omp target map(iterator(it=0:10), tofrom:a[itt]) + {} + return tmain(argc)+tmain(argc); // expected-note {{in instantiation of function template specialization 'tmain' requested here}} expected-note {{in instantiation of function template specialization 'tmain' requested here}} } #endif