Index: include/clang/AST/OpenMPClause.h =================================================================== --- include/clang/AST/OpenMPClause.h +++ include/clang/AST/OpenMPClause.h @@ -4003,6 +4003,109 @@ return child_range(child_iterator(), child_iterator()); } }; + +/// \brief This represents clause 'to' in the '#pragma omp ...' +/// directives. +/// +/// \code +/// #pragma omp target update to(a,b) +/// \endcode +/// In this example directive '#pragma omp target update' has clause 'to' +/// with the variables 'a' and 'b'. +/// +class OMPToClause final : public OMPMappableExprListClause, + private llvm::TrailingObjects< + OMPToClause, Expr *, ValueDecl *, unsigned, + OMPClauseMappableExprCommon::MappableComponent> { + friend TrailingObjects; + friend OMPVarListClause; + friend OMPMappableExprListClause; + friend class OMPClauseReader; + + /// Define the sizes of each trailing object array except the last one. This + /// is required for TrailingObjects to work properly. + size_t numTrailingObjects(OverloadToken) const { + return varlist_size(); + } + size_t numTrailingObjects(OverloadToken) const { + return getUniqueDeclarationsNum(); + } + size_t numTrailingObjects(OverloadToken) const { + return getUniqueDeclarationsNum() + getTotalComponentListNum(); + } + + /// \brief Build clause with number of variables \a NumVars. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + /// \param NumVars Number of expressions listed in this clause. + /// \param NumUniqueDeclarations Number of unique base declarations in this + /// clause. + /// \param NumComponentLists Number of component lists in this clause. + /// \param NumComponents Total number of expression components in the clause. + /// + explicit OMPToClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, unsigned NumVars, + unsigned NumUniqueDeclarations, + unsigned NumComponentLists, unsigned NumComponents) + : OMPMappableExprListClause(OMPC_to, StartLoc, LParenLoc, EndLoc, NumVars, + NumUniqueDeclarations, NumComponentLists, + NumComponents) {} + + /// \brief Build an empty clause. + /// + /// \param NumVars Number of expressions listed in this clause. + /// \param NumUniqueDeclarations Number of unique base declarations in this + /// clause. + /// \param NumComponentLists Number of component lists in this clause. + /// \param NumComponents Total number of expression components in the clause. + /// + explicit OMPToClause(unsigned NumVars, unsigned NumUniqueDeclarations, + unsigned NumComponentLists, unsigned NumComponents) + : OMPMappableExprListClause( + OMPC_to, SourceLocation(), SourceLocation(), SourceLocation(), + NumVars, NumUniqueDeclarations, NumComponentLists, NumComponents) {} + +public: + /// \brief Creates clause with a list of variables \a Vars. + /// + /// \param C AST context. + /// \brief StartLoc Starting location of the clause. + /// \brief EndLoc Ending location of the clause. + /// \param Vars The original expression used in the clause. + /// \param Declarations Declarations used in the clause. + /// \param ComponentLists Component lists used in the clause. + /// + static OMPToClause *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc, + ArrayRef Vars, + ArrayRef Declarations, + MappableExprComponentListsRef ComponentLists); + + /// \brief Creates an empty clause with the place for \a NumVars variables. + /// + /// \param C AST context. + /// \param NumVars Number of expressions listed in the clause. + /// \param NumUniqueDeclarations Number of unique base declarations in this + /// clause. + /// \param NumComponentLists Number of unique base declarations in this + /// clause. + /// \param NumComponents Total number of expression components in the clause. + /// + static OMPToClause *CreateEmpty(const ASTContext &C, unsigned NumVars, + unsigned NumUniqueDeclarations, + unsigned NumComponentLists, + unsigned NumComponents); + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_to; + } + + child_range children() { + return child_range(reinterpret_cast(varlist_begin()), + reinterpret_cast(varlist_end())); + } +}; } // end namespace clang #endif // LLVM_CLANG_AST_OPENMPCLAUSE_H Index: include/clang/AST/RecursiveASTVisitor.h =================================================================== --- include/clang/AST/RecursiveASTVisitor.h +++ include/clang/AST/RecursiveASTVisitor.h @@ -2884,6 +2884,12 @@ return true; } +template +bool RecursiveASTVisitor::VisitOMPToClause(OMPToClause *C) { + TRY_TO(VisitOMPClauseList(C)); + return true; +} + // FIXME: look at the following tricky-seeming exprs to see if we // need to recurse on anything. These are ones that have methods // returning decls or qualtypes or nestednamespecifier -- though I'm Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -7931,8 +7931,8 @@ "expected variable name%select{|, data member of current class}0, array element or array section">; def err_omp_expected_named_var_member_or_array_expression: Error< "expected expression containing only member accesses and/or array sections based on named variables">; -def err_omp_bit_fields_forbidden_in_map_clause : Error< - "bit fields cannot be used to specify storage in a map clause">; +def err_omp_bit_fields_forbidden_in_clause : Error< + "bit fields cannot be used to specify storage in a '%0' clause">; def err_array_section_does_not_specify_contiguous_storage : Error< "array section does not specify contiguous storage">; def err_omp_union_type_not_allowed : Error< @@ -8073,6 +8073,8 @@ "arguments of OpenMP clause 'reduction' with bitwise operators cannot be of floating type">; def err_omp_once_referenced : Error< "variable can appear only once in OpenMP '%0' clause">; +def err_omp_once_referenced_in_target_update : Error< + "variable can appear only once in OpenMP 'target update' construct">; def note_omp_referenced : Note< "previously referenced here">; def err_omp_reduction_in_task : Error< @@ -8210,8 +8212,8 @@ "mappable type cannot be polymorphic">; def note_omp_static_member_in_target : Note< "mappable type cannot contain static members">; -def err_omp_threadprivate_in_map : Error< - "threadprivate variables are not allowed in map clause">; +def err_omp_threadprivate_in_clause : Error< + "threadprivate variables are not allowed in '%0' clause">; def err_omp_wrong_ordered_loop_count : Error< "the parameter of the 'ordered' clause must be greater than or equal to the parameter of the 'collapse' clause">; def note_collapse_loop_count : Note< Index: include/clang/Basic/OpenMPKinds.def =================================================================== --- include/clang/Basic/OpenMPKinds.def +++ include/clang/Basic/OpenMPKinds.def @@ -210,6 +210,7 @@ OPENMP_CLAUSE(hint, OMPHintClause) OPENMP_CLAUSE(dist_schedule, OMPDistScheduleClause) OPENMP_CLAUSE(defaultmap, OMPDefaultmapClause) +OPENMP_CLAUSE(to, OMPToClause) // Clauses allowed for OpenMP directive 'parallel'. OPENMP_PARALLEL_CLAUSE(if) @@ -450,6 +451,7 @@ // TODO More clauses for 'target update' directive. OPENMP_TARGET_UPDATE_CLAUSE(if) OPENMP_TARGET_UPDATE_CLAUSE(device) +OPENMP_TARGET_UPDATE_CLAUSE(to) // Clauses allowed for OpenMP directive 'teams'. // TODO More clauses for 'teams' directive. Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -8417,6 +8417,11 @@ OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc); + /// \brief Called on well-formed 'to' clause. + OMPClause *ActOnOpenMPToClause(ArrayRef VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); /// \brief The kind of conversion being performed. enum CheckedConversionKind { Index: lib/AST/OpenMPClause.cpp =================================================================== --- lib/AST/OpenMPClause.cpp +++ lib/AST/OpenMPClause.cpp @@ -87,6 +87,7 @@ case OMPC_defaultmap: case OMPC_unknown: case OMPC_uniform: + case OMPC_to: break; } @@ -148,6 +149,7 @@ case OMPC_defaultmap: case OMPC_unknown: case OMPC_uniform: + case OMPC_to: break; } @@ -605,3 +607,52 @@ return new (Mem) OMPMapClause(NumVars, NumUniqueDeclarations, NumComponentLists, NumComponents); } + +OMPToClause *OMPToClause::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef Vars, + ArrayRef Declarations, + MappableExprComponentListsRef ComponentLists) { + unsigned NumVars = Vars.size(); + unsigned NumUniqueDeclarations = + getUniqueDeclarationsTotalNumber(Declarations); + unsigned NumComponentLists = ComponentLists.size(); + unsigned NumComponents = getComponentsTotalNumber(ComponentLists); + + // We need to allocate: + // NumVars x Expr* - we have an original list expression for each clause list + // entry. + // NumUniqueDeclarations x ValueDecl* - unique base declarations associated + // with each component list. + // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the + // number of lists for each unique declaration and the size of each component + // list. + // NumComponents x MappableComponent - the total of all the components in all + // the lists. + void *Mem = C.Allocate( + totalSizeToAlloc( + NumVars, NumUniqueDeclarations, + NumUniqueDeclarations + NumComponentLists, NumComponents)); + + OMPToClause *Clause = new (Mem) + OMPToClause(StartLoc, LParenLoc, EndLoc, NumVars, NumUniqueDeclarations, + NumComponentLists, NumComponents); + + Clause->setVarRefs(Vars); + Clause->setClauseInfo(Declarations, ComponentLists); + return Clause; +} + +OMPToClause *OMPToClause::CreateEmpty(const ASTContext &C, unsigned NumVars, + unsigned NumUniqueDeclarations, + unsigned NumComponentLists, + unsigned NumComponents) { + void *Mem = C.Allocate( + totalSizeToAlloc( + NumVars, NumUniqueDeclarations, + NumUniqueDeclarations + NumComponentLists, NumComponents)); + return new (Mem) OMPToClause(NumVars, NumUniqueDeclarations, + NumComponentLists, NumComponents); +} Index: lib/AST/StmtPrinter.cpp =================================================================== --- lib/AST/StmtPrinter.cpp +++ lib/AST/StmtPrinter.cpp @@ -912,6 +912,14 @@ } } +void OMPClausePrinter::VisitOMPToClause(OMPToClause *Node) { + if (!Node->varlist_empty()) { + OS << "to"; + VisitOMPClauseList(Node, '('); + OS << ")"; + } +} + void OMPClausePrinter::VisitOMPDistScheduleClause(OMPDistScheduleClause *Node) { OS << "dist_schedule(" << getOpenMPSimpleClauseTypeName( OMPC_dist_schedule, Node->getDistScheduleKind()); Index: lib/AST/StmtProfile.cpp =================================================================== --- lib/AST/StmtProfile.cpp +++ lib/AST/StmtProfile.cpp @@ -491,6 +491,9 @@ void OMPClauseProfiler::VisitOMPHintClause(const OMPHintClause *C) { Profiler->VisitStmt(C->getHint()); } +void OMPClauseProfiler::VisitOMPToClause(const OMPToClause *C) { + VisitOMPClauseList(C); +} } void Index: lib/Basic/OpenMPKinds.cpp =================================================================== --- lib/Basic/OpenMPKinds.cpp +++ lib/Basic/OpenMPKinds.cpp @@ -162,6 +162,7 @@ case OMPC_num_tasks: case OMPC_hint: case OMPC_uniform: + case OMPC_to: break; } llvm_unreachable("Invalid OpenMP simple clause kind"); @@ -297,6 +298,7 @@ case OMPC_num_tasks: case OMPC_hint: case OMPC_uniform: + case OMPC_to: break; } llvm_unreachable("Invalid OpenMP simple clause kind"); Index: lib/CodeGen/CGStmtOpenMP.cpp =================================================================== --- lib/CodeGen/CGStmtOpenMP.cpp +++ lib/CodeGen/CGStmtOpenMP.cpp @@ -3124,6 +3124,7 @@ case OMPC_dist_schedule: case OMPC_defaultmap: case OMPC_uniform: + case OMPC_to: llvm_unreachable("Clause is not allowed in 'omp atomic'."); } } Index: lib/Parse/ParseOpenMP.cpp =================================================================== --- lib/Parse/ParseOpenMP.cpp +++ lib/Parse/ParseOpenMP.cpp @@ -1043,7 +1043,7 @@ /// update-clause | capture-clause | seq_cst-clause | device-clause | /// simdlen-clause | threads-clause | simd-clause | num_teams-clause | /// thread_limit-clause | priority-clause | grainsize-clause | -/// nogroup-clause | num_tasks-clause | hint-clause +/// nogroup-clause | num_tasks-clause | hint-clause | to-clause /// OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, bool FirstClause) { @@ -1167,6 +1167,7 @@ case OMPC_flush: case OMPC_depend: case OMPC_map: + case OMPC_to: Clause = ParseOpenMPVarListClause(DKind, CKind); break; case OMPC_unknown: @@ -1727,6 +1728,8 @@ /// map-clause: /// 'map' '(' [ [ always , ] /// to | from | tofrom | alloc | release | delete ':' ] list ')'; +/// to-clause: +/// 'to' '(' list ')' /// /// For 'linear' clause linear-list may have the following forms: /// list Index: lib/Sema/SemaOpenMP.cpp =================================================================== --- lib/Sema/SemaOpenMP.cpp +++ lib/Sema/SemaOpenMP.cpp @@ -6448,10 +6448,11 @@ StmtResult Sema::ActOnOpenMPTargetUpdateDirective(ArrayRef Clauses, SourceLocation StartLoc, SourceLocation EndLoc) { - // TODO: Set this flag accordingly when we add support for the 'to' and 'from' - // clauses. bool seenMotionClause = false; - + for (auto *C : Clauses) { + if (C->getClauseKind() == OMPC_to) + seenMotionClause = true; + } if (!seenMotionClause) { Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required); return StmtError(); @@ -6725,6 +6726,7 @@ case OMPC_defaultmap: case OMPC_unknown: case OMPC_uniform: + case OMPC_to: llvm_unreachable("Clause is not allowed."); } return Res; @@ -7011,6 +7013,7 @@ case OMPC_defaultmap: case OMPC_unknown: case OMPC_uniform: + case OMPC_to: llvm_unreachable("Clause is not allowed."); } return Res; @@ -7162,6 +7165,7 @@ case OMPC_hint: case OMPC_unknown: case OMPC_uniform: + case OMPC_to: llvm_unreachable("Clause is not allowed."); } return Res; @@ -7346,6 +7350,7 @@ case OMPC_defaultmap: case OMPC_unknown: case OMPC_uniform: + case OMPC_to: llvm_unreachable("Clause is not allowed."); } return Res; @@ -7459,6 +7464,9 @@ DepLinMapLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc); break; + case OMPC_to: + Res = ActOnOpenMPToClause(VarList, StartLoc, LParenLoc, EndLoc); + break; case OMPC_if: case OMPC_final: case OMPC_num_threads: @@ -9796,13 +9804,14 @@ return ConstLength.getSExtValue() != 1; } -// Return the expression of the base of the map clause or null if it cannot -// be determined and do all the necessary checks to see if the expression is -// valid as a standalone map clause expression. In the process, record all the +// Return the expression of the base of the mappable expression or null if it +// cannot be determined and do all the necessary checks to see if the expression +// is valid as a standalone mappable expression. In the process, record all the // components of the expression. static Expr *CheckMapClauseExpressionBase( Sema &SemaRef, Expr *E, - OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents) { + OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents, + OpenMPClauseKind CKind) { SourceLocation ELoc = E->getExprLoc(); SourceRange ERange = E->getSourceRange(); @@ -9888,8 +9897,8 @@ // A bit-field cannot appear in a map clause. // if (FD->isBitField()) { - SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_map_clause) - << CurE->getSourceRange(); + SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause) + << CurE->getSourceRange() << getOpenMPClauseName(CKind); break; } @@ -10011,7 +10020,8 @@ static bool CheckMapConflicts( Sema &SemaRef, DSAStackTy *DSAS, ValueDecl *VD, Expr *E, bool CurrentRegionOnly, - OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents) { + OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents, + OpenMPClauseKind CKind) { assert(VD && E); SourceLocation ELoc = E->getExprLoc(); SourceRange ERange = E->getSourceRange(); @@ -10086,7 +10096,13 @@ // other, it means they are sharing storage. if (CI == CE && SI == SE) { if (CurrentRegionOnly) { - SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange; + if (CKind == OMPC_map) + SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange; + else { + assert(CKind == OMPC_to); + SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update) + << ERange; + } SemaRef.Diag(RE->getExprLoc(), diag::note_used_here) << RE->getSourceRange(); return true; @@ -10141,7 +10157,13 @@ // // An expression is a subset of the other. if (CurrentRegionOnly && (CI == CE || SI == SE)) { - SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange; + if (CKind == OMPC_map) + SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange; + else { + assert(CKind == OMPC_to); + SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update) + << ERange; + } SemaRef.Diag(RE->getExprLoc(), diag::note_used_here) << RE->getSourceRange(); return true; @@ -10186,27 +10208,32 @@ return FoundError; } -OMPClause * -Sema::ActOnOpenMPMapClause(OpenMPMapClauseKind MapTypeModifier, - OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, - SourceLocation MapLoc, SourceLocation ColonLoc, - ArrayRef VarList, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc) { - SmallVector Vars; +// Check the validity of the provided variable list for the provided clause kind +// \a CKind. In the check process the valid expressions, and mappable expression +// components and variables are extracted and used to fill \a Vars, +// \a ClauseComponents, and \a ClauseBaseDeclarations. \a MapType and +// \a IsMapTypeImplicit are expected to be valid if the clause kind is 'map'. +static void checkMappableExpressionList( + Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind, + ArrayRef VarList, SmallVector &Vars, + OMPClauseMappableExprCommon::MappableExprComponentLists &ClauseComponents, + SmallVector &ClauseBaseDeclarations, + SourceLocation StartLoc, OpenMPMapClauseKind MapType = OMPC_MAP_unknown, + bool IsMapTypeImplicit = false) { + // We only expect mappable expressions in 'to' and 'map' clauses. + assert((CKind == OMPC_map || CKind == OMPC_to) && + "Unexpected clause kind with mappable expressions!"); // Keep track of the mappable components and base declarations in this clause. // Each entry in the list is going to have a list of components associated. We // record each set of the components so that we can build the clause later on. // In the end we should have the same amount of declarations and component // lists. - OMPClauseMappableExprCommon::MappableExprComponentLists ClauseComponents; - SmallVector ClauseBaseDeclarations; - ClauseComponents.reserve(VarList.size()); ClauseBaseDeclarations.reserve(VarList.size()); for (auto &RE : VarList) { - assert(RE && "Null expr in omp map"); + assert(RE && "Null expr in omp to/map clause"); if (isa(RE)) { // It will be analyzed later. Vars.push_back(RE); @@ -10228,7 +10255,8 @@ auto *SimpleExpr = RE->IgnoreParenCasts(); if (!RE->IgnoreParenImpCasts()->isLValue()) { - Diag(ELoc, diag::err_omp_expected_named_var_member_or_array_expression) + SemaRef.Diag(ELoc, + diag::err_omp_expected_named_var_member_or_array_expression) << RE->getSourceRange(); continue; } @@ -10238,7 +10266,8 @@ // Obtain the array or member expression bases if required. Also, fill the // components array with all the components identified in the process. - auto *BE = CheckMapClauseExpressionBase(*this, SimpleExpr, CurComponents); + auto *BE = + CheckMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind); if (!BE) continue; @@ -10261,84 +10290,90 @@ (void)FD; // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10] - // threadprivate variables cannot appear in a map clause. - if (VD && DSAStack->isThreadPrivate(VD)) { - auto DVar = DSAStack->getTopDSA(VD, false); - Diag(ELoc, diag::err_omp_threadprivate_in_map); - ReportOriginalDSA(*this, DSAStack, VD, DVar); + // threadprivate variables cannot appear in a map clause. + // OpenMP 4.5 [2.10.5, target update Construct] + // threadprivate variables cannot appear in a from clause. + if (VD && DSAS->isThreadPrivate(VD)) { + auto DVar = DSAS->getTopDSA(VD, false); + SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause) + << getOpenMPClauseName(CKind); + ReportOriginalDSA(SemaRef, DSAS, VD, DVar); continue; } // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9] // A list item cannot appear in both a map clause and a data-sharing // attribute clause on the same construct. - // - // TODO: Implement this check - it cannot currently be tested because of - // missing implementation of the other data sharing clauses in target - // directives. // Check conflicts with other map clause expressions. We check the conflicts // with the current construct separately from the enclosing data - // environment, because the restrictions are different. - if (CheckMapConflicts(*this, DSAStack, CurDeclaration, SimpleExpr, - /*CurrentRegionOnly=*/true, CurComponents)) + // environment, because the restrictions are different. We only have to + // check conflicts across regions for the map clauses. + if (CheckMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr, + /*CurrentRegionOnly=*/true, CurComponents, CKind)) break; - if (CheckMapConflicts(*this, DSAStack, CurDeclaration, SimpleExpr, - /*CurrentRegionOnly=*/false, CurComponents)) + if (CKind == OMPC_map && + CheckMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr, + /*CurrentRegionOnly=*/false, CurComponents, CKind)) break; + // OpenMP 4.5 [2.10.5, target update Construct] // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1] // If the type of a list item is a reference to a type T then the type will // be considered to be T for all purposes of this clause. QualType Type = CurDeclaration->getType().getNonReferenceType(); + // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4] + // A list item in a to or from clause must have a mappable type. // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9] // A list item must have a mappable type. - if (!CheckTypeMappable(VE->getExprLoc(), VE->getSourceRange(), *this, - DSAStack, Type)) - continue; - - // target enter data - // OpenMP [2.10.2, Restrictions, p. 99] - // A map-type must be specified in all map clauses and must be either - // to or alloc. - OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); - if (DKind == OMPD_target_enter_data && - !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc)) { - Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive) - << (IsMapTypeImplicit ? 1 : 0) - << getOpenMPSimpleClauseTypeName(OMPC_map, MapType) - << getOpenMPDirectiveName(DKind); + if (!CheckTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef, + DSAS, Type)) continue; - } - // target exit_data - // OpenMP [2.10.3, Restrictions, p. 102] - // A map-type must be specified in all map clauses and must be either - // from, release, or delete. - DKind = DSAStack->getCurrentDirective(); - if (DKind == OMPD_target_exit_data && - !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release || - MapType == OMPC_MAP_delete)) { - Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive) - << (IsMapTypeImplicit ? 1 : 0) - << getOpenMPSimpleClauseTypeName(OMPC_map, MapType) - << getOpenMPDirectiveName(DKind); - continue; - } + if (CKind == OMPC_map) { + // target enter data + // OpenMP [2.10.2, Restrictions, p. 99] + // A map-type must be specified in all map clauses and must be either + // to or alloc. + OpenMPDirectiveKind DKind = DSAS->getCurrentDirective(); + if (DKind == OMPD_target_enter_data && + !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc)) { + SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive) + << (IsMapTypeImplicit ? 1 : 0) + << getOpenMPSimpleClauseTypeName(OMPC_map, MapType) + << getOpenMPDirectiveName(DKind); + continue; + } - // OpenMP 4.5 [2.15.5.1, Restrictions, p.3] - // A list item cannot appear in both a map clause and a data-sharing - // attribute clause on the same construct - if (DKind == OMPD_target && VD) { - auto DVar = DSAStack->getTopDSA(VD, false); - if (isOpenMPPrivate(DVar.CKind)) { - Diag(ELoc, diag::err_omp_variable_in_map_and_dsa) - << getOpenMPClauseName(DVar.CKind) - << getOpenMPDirectiveName(DSAStack->getCurrentDirective()); - ReportOriginalDSA(*this, DSAStack, CurDeclaration, DVar); + // target exit_data + // OpenMP [2.10.3, Restrictions, p. 102] + // A map-type must be specified in all map clauses and must be either + // from, release, or delete. + DKind = DSAS->getCurrentDirective(); + if (DKind == OMPD_target_exit_data && + !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release || + MapType == OMPC_MAP_delete)) { + SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive) + << (IsMapTypeImplicit ? 1 : 0) + << getOpenMPSimpleClauseTypeName(OMPC_map, MapType) + << getOpenMPDirectiveName(DKind); continue; } + + // OpenMP 4.5 [2.15.5.1, Restrictions, p.3] + // A list item cannot appear in both a map clause and a data-sharing + // attribute clause on the same construct + if (DKind == OMPD_target && VD) { + auto DVar = DSAS->getTopDSA(VD, false); + if (isOpenMPPrivate(DVar.CKind)) { + SemaRef.Diag(ELoc, diag::err_omp_variable_in_map_and_dsa) + << getOpenMPClauseName(DVar.CKind) + << getOpenMPDirectiveName(DSAS->getCurrentDirective()); + ReportOriginalDSA(SemaRef, DSAS, CurDeclaration, DVar); + continue; + } + } } // Save the current expression. @@ -10346,7 +10381,7 @@ // Store the components in the stack so that they can be used to check // against other clauses later on. - DSAStack->addMappableExpressionComponents(CurDeclaration, CurComponents); + DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents); // Save the components and declaration to create the clause. For purposes of // the clause creation, any component list that has has base 'this' uses @@ -10356,6 +10391,21 @@ ClauseBaseDeclarations.push_back(isa(BE) ? nullptr : CurDeclaration); } +} + +OMPClause * +Sema::ActOnOpenMPMapClause(OpenMPMapClauseKind MapTypeModifier, + OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, + SourceLocation MapLoc, SourceLocation ColonLoc, + ArrayRef VarList, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc) { + SmallVector Vars; + OMPClauseMappableExprCommon::MappableExprComponentLists ClauseComponents; + SmallVector ClauseBaseDeclarations; + + checkMappableExpressionList(*this, DSAStack, OMPC_map, VarList, Vars, + ClauseComponents, ClauseBaseDeclarations, + StartLoc, MapType, IsMapTypeImplicit); // 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. @@ -10964,3 +11014,21 @@ } checkDeclInTargetContext(E->getExprLoc(), E->getSourceRange(), *this, D); } + +OMPClause *Sema::ActOnOpenMPToClause(ArrayRef VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + SmallVector Vars; + OMPClauseMappableExprCommon::MappableExprComponentLists ClauseComponents; + SmallVector ClauseBaseDeclarations; + + checkMappableExpressionList(*this, DSAStack, OMPC_to, VarList, Vars, + ClauseComponents, ClauseBaseDeclarations, + StartLoc); + if (Vars.empty()) + return nullptr; + + return OMPToClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars, + ClauseBaseDeclarations, ClauseComponents); +} Index: lib/Sema/TreeTransform.h =================================================================== --- lib/Sema/TreeTransform.h +++ lib/Sema/TreeTransform.h @@ -1751,6 +1751,17 @@ Kind, ChunkSize, StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc); } + /// \brief Build a new OpenMP 'to' clause. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPToClause(ArrayRef VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPToClause(VarList, StartLoc, LParenLoc, EndLoc); + } + /// \brief Rebuild the operand to an Objective-C \@synchronized statement. /// /// By default, performs semantic analysis to build the new statement. @@ -8038,6 +8049,20 @@ return C; } +template +OMPClause *TreeTransform::TransformOMPToClause(OMPToClause *C) { + llvm::SmallVector Vars; + Vars.reserve(C->varlist_size()); + for (auto *VE : C->varlists()) { + ExprResult EVar = getDerived().TransformExpr(cast(VE)); + if (EVar.isInvalid()) + return 0; + Vars.push_back(EVar.get()); + } + return getDerived().RebuildOMPToClause(Vars, C->getLocStart(), + C->getLParenLoc(), C->getLocEnd()); +} + //===----------------------------------------------------------------------===// // Expression transformation //===----------------------------------------------------------------------===// Index: lib/Serialization/ASTReaderStmt.cpp =================================================================== --- lib/Serialization/ASTReaderStmt.cpp +++ lib/Serialization/ASTReaderStmt.cpp @@ -1894,6 +1894,15 @@ case OMPC_defaultmap: C = new (Context) OMPDefaultmapClause(); break; + case OMPC_to: { + unsigned NumVars = Record[Idx++]; + unsigned NumDeclarations = Record[Idx++]; + unsigned NumLists = Record[Idx++]; + unsigned NumComponents = Record[Idx++]; + C = OMPToClause::CreateEmpty(Context, NumVars, NumDeclarations, NumLists, + NumComponents); + break; + } } Visit(C); C->setLocStart(Reader->ReadSourceLocation(Record, Idx)); @@ -2322,6 +2331,50 @@ C->setDefaultmapKindLoc(Reader->ReadSourceLocation(Record, Idx)); } +void OMPClauseReader::VisitOMPToClause(OMPToClause *C) { + C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); + auto NumVars = C->varlist_size(); + auto UniqueDecls = C->getUniqueDeclarationsNum(); + auto TotalLists = C->getTotalComponentListNum(); + auto TotalComponents = C->getTotalComponentsNum(); + + SmallVector Vars; + Vars.reserve(NumVars); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setVarRefs(Vars); + + SmallVector Decls; + Decls.reserve(UniqueDecls); + for (unsigned i = 0; i < UniqueDecls; ++i) + Decls.push_back( + Reader->Reader.ReadDeclAs(Reader->F, Record, Idx)); + C->setUniqueDecls(Decls); + + SmallVector ListsPerDecl; + ListsPerDecl.reserve(UniqueDecls); + for (unsigned i = 0; i < UniqueDecls; ++i) + ListsPerDecl.push_back(Record[Idx++]); + C->setDeclNumLists(ListsPerDecl); + + SmallVector ListSizes; + ListSizes.reserve(TotalLists); + for (unsigned i = 0; i < TotalLists; ++i) + ListSizes.push_back(Record[Idx++]); + C->setComponentListSizes(ListSizes); + + SmallVector Components; + Components.reserve(TotalComponents); + for (unsigned i = 0; i < TotalComponents; ++i) { + Expr *AssociatedExpr = Reader->Reader.ReadSubExpr(); + ValueDecl *AssociatedDecl = + Reader->Reader.ReadDeclAs(Reader->F, Record, Idx); + Components.push_back(OMPClauseMappableExprCommon::MappableComponent( + AssociatedExpr, AssociatedDecl)); + } + C->setComponents(Components, ListSizes); +} + //===----------------------------------------------------------------------===// // OpenMP Directives. //===----------------------------------------------------------------------===// Index: lib/Serialization/ASTWriterStmt.cpp =================================================================== --- lib/Serialization/ASTWriterStmt.cpp +++ lib/Serialization/ASTWriterStmt.cpp @@ -2090,6 +2090,26 @@ Record.AddSourceLocation(C->getDefaultmapKindLoc()); } +void OMPClauseWriter::VisitOMPToClause(OMPToClause *C) { + Record.push_back(C->varlist_size()); + Record.push_back(C->getUniqueDeclarationsNum()); + Record.push_back(C->getTotalComponentListNum()); + Record.push_back(C->getTotalComponentsNum()); + Record.AddSourceLocation(C->getLParenLoc()); + for (auto *E : C->varlists()) + Record.AddStmt(E); + for (auto *D : C->all_decls()) + Record.AddDeclRef(D); + for (auto N : C->all_num_lists()) + Record.push_back(N); + for (auto N : C->all_lists_sizes()) + Record.push_back(N); + for (auto &M : C->all_components()) { + Record.AddStmt(M.getAssociatedExpression()); + Record.AddDeclRef(M.getAssociatedDeclaration()); + } +} + //===----------------------------------------------------------------------===// // OpenMP Directives. //===----------------------------------------------------------------------===// Index: test/OpenMP/nesting_of_regions.cpp =================================================================== --- test/OpenMP/nesting_of_regions.cpp +++ test/OpenMP/nesting_of_regions.cpp @@ -133,6 +133,10 @@ for (int i = 0; i < 10; ++i) ; } +#pragma omp parallel + { +#pragma omp target update to(a) + } // SIMD DIRECTIVE #pragma omp simd @@ -293,6 +297,10 @@ for (int j = 0; j < 10; ++j) ; } +#pragma omp simd + for (int i = 0; i < 10; ++i) { +#pragma omp target update to(a) // expected-error {{OpenMP constructs may not be nested inside a simd region}} + } // FOR DIRECTIVE #pragma omp for @@ -476,6 +484,10 @@ for (int j = 0; j < 10; ++j) ; } +#pragma omp for + for (int i = 0; i < 10; ++i) { +#pragma omp target update to(a) + } // FOR SIMD DIRECTIVE #pragma omp for simd @@ -636,6 +648,11 @@ for (int j = 0; j < 10; ++j) ; } +#pragma omp for simd + for (int i = 0; i < 10; ++i) { +#pragma omp target update to(a) // expected-error {{OpenMP constructs may not be nested inside a simd region}} + bar(); + } // SECTIONS DIRECTIVE #pragma omp sections @@ -824,6 +841,10 @@ for (int i = 0; i < 10; ++i) ; } +#pragma omp sections + { +#pragma omp target update to(a) + } // SECTION DIRECTIVE #pragma omp section // expected-error {{orphaned 'omp section' directives are prohibited, it must be closely nested to a sections region}} @@ -1062,6 +1083,14 @@ for (int i = 0; i < 10; ++i) ; } +#pragma omp sections + { +#pragma omp section + { + bar(); +#pragma omp target update to(a) + } + } // SINGLE DIRECTIVE #pragma omp single @@ -1235,6 +1264,11 @@ for (int i = 0; i < 10; ++i) ; } +#pragma omp single + { +#pragma omp target update to(a) + bar(); + } // MASTER DIRECTIVE #pragma omp master @@ -1408,6 +1442,11 @@ for (int i = 0; i < 10; ++i) ; } +#pragma omp master + { +#pragma omp target update to(a) + bar(); + } // CRITICAL DIRECTIVE #pragma omp critical @@ -1595,6 +1634,11 @@ for (int i = 0; i < 10; ++i) ; } +#pragma omp critical + { +#pragma omp target update to(a) + bar(); + } // PARALLEL FOR DIRECTIVE #pragma omp parallel for @@ -1783,6 +1827,10 @@ for (int j = 0; j < 10; ++j) ; } +#pragma omp parallel for + for (int i = 0; i < 10; ++i) { +#pragma omp target update to(a) + } // PARALLEL FOR SIMD DIRECTIVE #pragma omp parallel for simd @@ -1971,6 +2019,11 @@ for (int j = 0; j < 10; ++j) ; } +#pragma omp parallel for simd + for (int i = 0; i < 10; ++i) { +#pragma omp target update to(a) // expected-error {{OpenMP constructs may not be nested inside a simd region}} + bar(); + } // PARALLEL SECTIONS DIRECTIVE #pragma omp parallel sections @@ -2148,6 +2201,10 @@ for (int i = 0; i < 10; ++i) ; } +#pragma omp parallel sections + { +#pragma omp target update to(a) + } // TASK DIRECTIVE #pragma omp task @@ -2271,6 +2328,11 @@ for (int i = 0; i < 10; ++i) ; } +#pragma omp task + { +#pragma omp target update to(a) + bar(); + } // ORDERED DIRECTIVE #pragma omp ordered @@ -2464,6 +2526,12 @@ for (int i = 0; i < 10; ++i) ; } +#pragma omp ordered + { + bar(); +#pragma omp target update to(a) + bar(); + } // ATOMIC DIRECTIVE #pragma omp atomic @@ -2678,6 +2746,13 @@ for (int i = 0; i < 10; ++i) ; } +#pragma omp atomic + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} + { +#pragma omp target update to(a) // expected-error {{OpenMP constructs may not be nested inside an atomic region}} + bar(); + } // TARGET DIRECTIVE #pragma omp target @@ -2812,6 +2887,10 @@ { #pragma omp target exit data map(from: a) // expected-error {{region cannot be nested inside 'target' region}} } +#pragma omp target + { +#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target' region}} + } // TARGET PARALLEL DIRECTIVE #pragma omp target parallel @@ -2946,6 +3025,10 @@ { #pragma omp target exit data map(from: a) // expected-error {{region cannot be nested inside 'target parallel' region}} } +#pragma omp target parallel + { +#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target parallel' region}} + } // TARGET PARALLEL FOR DIRECTIVE #pragma omp target parallel for @@ -3134,6 +3217,10 @@ for (int j = 0; j < 10; ++j) ; } +#pragma omp target parallel for + for (int i = 0; i < 10; ++i) { +#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target parallel for' region}} + } // TEAMS DIRECTIVE #pragma omp target @@ -3297,6 +3384,11 @@ #pragma omp distribute for (int j = 0; j < 10; ++j) ; +#pragma omp target +#pragma omp teams + { +#pragma omp target update to(a) // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp target update' directive into a parallel region?}} + } // TASKLOOP DIRECTIVE #pragma omp taskloop @@ -3469,6 +3561,13 @@ for (int i = 0; i < 10; ++i) ++a; } +#pragma omp taskloop + for (int i = 0; i < 10; ++i) { +#pragma omp target update to(a) + bar(); + } + + // DISTRIBUTE DIRECTIVE #pragma omp target #pragma omp teams @@ -3686,6 +3785,13 @@ #pragma omp teams // expected-error {{region cannot be closely nested inside 'distribute' region; perhaps you forget to enclose 'omp teams' directive into a target region?}} ++a; } +#pragma omp target +#pragma omp teams +#pragma omp distribute + for (int i = 0; i < 10; ++i) { +#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target' region}} + ++a; + } } void foo() { @@ -3816,6 +3922,11 @@ for (int i = 0; i < 10; ++i) ; } +#pragma omp parallel + { +#pragma omp target update to(a) + a++; + } // SIMD DIRECTIVE #pragma omp simd @@ -3969,6 +4080,11 @@ for (int j = 0; j < 10; ++j) ; } +#pragma omp simd + for (int i = 0; i < 10; ++i) { +#pragma omp target update to(a) // expected-error {{OpenMP constructs may not be nested inside a simd region}} + a++; + } // FOR DIRECTIVE #pragma omp for @@ -4142,6 +4258,11 @@ for (int j = 0; j < 10; ++j) ; } +#pragma omp for + for (int i = 0; i < 10; ++i) { +#pragma omp target update to(a) + ++a; + } // FOR SIMD DIRECTIVE #pragma omp for simd @@ -4295,6 +4416,11 @@ for (int j = 0; j < 10; ++j) ; } +#pragma omp for simd + for (int i = 0; i < 10; ++i) { +#pragma omp target update to(a) // expected-error {{OpenMP constructs may not be nested inside a simd region}} + ++a; + } // SECTIONS DIRECTIVE #pragma omp sections @@ -4458,6 +4584,10 @@ for (int i = 0; i < 10; ++i) ; } +#pragma omp sections + { +#pragma omp target update to(a) + } // SECTION DIRECTIVE #pragma omp section // expected-error {{orphaned 'omp section' directives are prohibited, it must be closely nested to a sections region}} @@ -4706,6 +4836,14 @@ for (int i = 0; i < 10; ++i) ; } +#pragma omp sections + { +#pragma omp section + { +#pragma omp target update to(a) + a++; + } + } // SINGLE DIRECTIVE #pragma omp single @@ -4869,6 +5007,11 @@ for (int i = 0; i < 10; ++i) ; } +#pragma omp single + { +#pragma omp target update to(a) + a++; + } // MASTER DIRECTIVE #pragma omp master @@ -5042,6 +5185,11 @@ for (int i = 0; i < 10; ++i) ; } +#pragma omp master + { +#pragma omp target update to(a) + ++a; + } // CRITICAL DIRECTIVE #pragma omp critical @@ -5234,6 +5382,11 @@ for (int i = 0; i < 10; ++i) ; } +#pragma omp critical + { +#pragma omp target update to(a) + a++; + } // PARALLEL FOR DIRECTIVE #pragma omp parallel for @@ -5422,6 +5575,11 @@ for (int j = 0; j < 10; ++j) ; } +#pragma omp parallel for + for (int i = 0; i < 10; ++i) { +#pragma omp target update to(a) + a++; + } // PARALLEL FOR SIMD DIRECTIVE #pragma omp parallel for simd @@ -5610,6 +5768,11 @@ for (int j = 0; j < 10; ++j) ; } +#pragma omp parallel for simd + for (int i = 0; i < 10; ++i) { +#pragma omp target update to(a) // expected-error {{OpenMP constructs may not be nested inside a simd region}} + a++; + } // PARALLEL SECTIONS DIRECTIVE #pragma omp parallel sections @@ -5783,6 +5946,10 @@ for (int i = 0; i < 10; ++i) ; } +#pragma omp parallel sections + { +#pragma omp target update to(a) + } // TASK DIRECTIVE #pragma omp task @@ -5905,6 +6072,11 @@ for (int i = 0; i < 10; ++i) ; } +#pragma omp task + { +#pragma omp target update to(a) + a++; + } // ATOMIC DIRECTIVE #pragma omp atomic @@ -6119,6 +6291,12 @@ for (int i = 0; i < 10; ++i) ; } +#pragma omp atomic + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} + { +#pragma omp target update // expected-error {{OpenMP constructs may not be nested inside an atomic region}} + } // TARGET DIRECTIVE #pragma omp target @@ -6253,6 +6431,13 @@ for (int i = 0; i < 10; ++i) ; } +#pragma omp atomic + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} + { +#pragma omp target update to(a) // expected-error {{OpenMP constructs may not be nested inside an atomic region}} + a++; + } // TARGET PARALLEL DIRECTIVE #pragma omp target parallel @@ -6387,6 +6572,11 @@ { #pragma omp target exit data map(from: a) // expected-error {{region cannot be nested inside 'target parallel' region}} } +#pragma omp target parallel + { +#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target parallel' region}} + } + // TARGET PARALLEL FOR DIRECTIVE #pragma omp target parallel for @@ -6575,6 +6765,11 @@ for (int j = 0; j < 10; ++j) ; } +#pragma omp target parallel for + for (int i = 0; i < 10; ++i) { +#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target parallel for' region}} + a++; + } // TEAMS DIRECTIVE #pragma omp target @@ -6736,6 +6931,12 @@ #pragma omp distribute for (int j = 0; j < 10; ++j) ; +#pragma omp target +#pragma omp teams + { +#pragma omp target update to(a) // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp target update' directive into a parallel region?}} + ++a; + } // TASKLOOP DIRECTIVE #pragma omp taskloop @@ -6908,6 +7109,11 @@ for (int i = 0; i < 10; ++i) ++a; } +#pragma omp taskloop + for (int i = 0; i < 10; ++i) { +#pragma omp target update to(a) + ++a; + } // DISTRIBUTE DIRECTIVE #pragma omp target @@ -7127,4 +7333,11 @@ #pragma omp target exit data map(from: a) // expected-error {{region cannot be nested inside 'target' region}} ++a; } +#pragma omp target +#pragma omp teams +#pragma omp distribute + for (int i = 0; i < 10; ++i) { +#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target' region}} + ++a; + } } Index: test/OpenMP/target_map_messages.cpp =================================================================== --- test/OpenMP/target_map_messages.cpp +++ test/OpenMP/target_map_messages.cpp @@ -40,7 +40,7 @@ #pragma omp target map(arg,a,d[:2]) // expected-error {{subscripted value is not an array or pointer}} {} - #pragma omp target map(to:ss) // expected-error {{threadprivate variables are not allowed in map clause}} + #pragma omp target map(to:ss) // expected-error {{threadprivate variables are not allowed in 'map' clause}} {} #pragma omp target map(to:b,e) @@ -239,7 +239,7 @@ {} #pragma omp target map(r.C, t.C) {} - #pragma omp target map(r.A) // expected-error {{bit fields cannot be used to specify storage in a map clause}} + #pragma omp target map(r.A) // expected-error {{bit fields cannot be used to specify storage in a 'map' clause}} {} #pragma omp target map(r.Arr) {} @@ -407,7 +407,7 @@ #pragma omp target data map(S2::S2s) #pragma omp target data map(S2::S2sc) #pragma omp target data map(e, g) -#pragma omp target data map(h) // expected-error {{threadprivate variables are not allowed in map clause}} +#pragma omp target data map(h) // expected-error {{threadprivate variables are not allowed in 'map' clause}} #pragma omp target data map(k) map(k) // expected-error 2 {{variable already marked as mapped in current construct}} expected-note 2 {{used here}} #pragma omp target map(k), map(k[:5]) // expected-error 2 {{pointer cannot be mapped along with a section derived from itself}} expected-note 2 {{used here}} foo(); @@ -476,7 +476,7 @@ #pragma omp target data map(S2::S2s) #pragma omp target data map(S2::S2sc) #pragma omp target data map(e, g) -#pragma omp target data map(h) // expected-error {{threadprivate variables are not allowed in map clause}} +#pragma omp target data map(h) // expected-error {{threadprivate variables are not allowed in 'map' clause}} #pragma omp target data map(k), map(k) // expected-error {{variable already marked as mapped in current construct}} expected-note {{used here}} #pragma omp target map(k), map(k[:5]) // expected-error {{pointer cannot be mapped along with a section derived from itself}} expected-note {{used here}} foo(); Index: test/OpenMP/target_parallel_for_map_messages.cpp =================================================================== --- test/OpenMP/target_parallel_for_map_messages.cpp +++ test/OpenMP/target_parallel_for_map_messages.cpp @@ -126,7 +126,7 @@ for (i = 0; i < argc; ++i) foo(); #pragma omp target parallel for map(e, g) for (i = 0; i < argc; ++i) foo(); -#pragma omp target parallel for map(h) // expected-error {{threadprivate variables are not allowed in map clause}} +#pragma omp target parallel for map(h) // expected-error {{threadprivate variables are not allowed in 'map' clause}} for (i = 0; i < argc; ++i) foo(); #pragma omp target parallel for map(k), map(k) // expected-error 2 {{variable already marked as mapped in current construct}} expected-note 2 {{used here}} for (i = 0; i < argc; ++i) foo(); @@ -230,7 +230,7 @@ for (i = 0; i < argc; ++i) foo(); #pragma omp target parallel for map(e, g) for (i = 0; i < argc; ++i) foo(); -#pragma omp target parallel for map(h) // expected-error {{threadprivate variables are not allowed in map clause}} +#pragma omp target parallel for map(h) // expected-error {{threadprivate variables are not allowed in 'map' clause}} for (i = 0; i < argc; ++i) foo(); #pragma omp target parallel for map(k), map(k) // expected-error {{variable already marked as mapped in current construct}} expected-note {{used here}} for (i = 0; i < argc; ++i) foo(); Index: test/OpenMP/target_parallel_map_messages.cpp =================================================================== --- test/OpenMP/target_parallel_map_messages.cpp +++ test/OpenMP/target_parallel_map_messages.cpp @@ -126,7 +126,7 @@ foo(); #pragma omp target parallel map(e, g) foo(); -#pragma omp target parallel map(h) // expected-error {{threadprivate variables are not allowed in map clause}} +#pragma omp target parallel map(h) // expected-error {{threadprivate variables are not allowed in 'map' clause}} foo(); #pragma omp target parallel map(k), map(k) // expected-error 2 {{variable already marked as mapped in current construct}} expected-note 2 {{used here}} foo(); @@ -229,7 +229,7 @@ foo(); #pragma omp target parallel map(e, g) foo(); -#pragma omp target parallel map(h) // expected-error {{threadprivate variables are not allowed in map clause}} +#pragma omp target parallel map(h) // expected-error {{threadprivate variables are not allowed in 'map' clause}} foo(); #pragma omp target parallel map(k), map(k) // expected-error {{variable already marked as mapped in current construct}} expected-note {{used here}} foo(); Index: test/OpenMP/target_update_ast_print.cpp =================================================================== --- /dev/null +++ test/OpenMP/target_update_ast_print.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER + +void foo() {} + +template +T foo(T targ, U uarg) { + static T a; + U b; + int l; +#pragma omp target update to(a) if(l>5) device(l) + return a + targ + (T)b; +} +// CHECK: static int a; +// CHECK-NEXT: float b; +// CHECK-NEXT: int l; +// CHECK-NEXT: #pragma omp target update to(a) if(l > 5) device(l) +// CHECK: static char a; +// CHECK-NEXT: float b; +// CHECK-NEXT: int l; +// CHECK-NEXT: #pragma omp target update to(a) if(l > 5) device(l) +// CHECK: static T a; +// CHECK-NEXT: U b; +// CHECK-NEXT: int l; +// CHECK-NEXT: #pragma omp target update to(a) if(l > 5) device(l) + +int main(int argc, char **argv) { + static int a; + int n; + float f; + +// CHECK: static int a; +// CHECK-NEXT: int n; +// CHECK-NEXT: float f; +#pragma omp target update to(a) if(f>0.0) device(n) + // CHECK-NEXT: #pragma omp target update to(a) if(f > 0.) device(n) + return foo(argc, f) + foo(argv[0][0], f) + a; +} + +#endif Index: test/OpenMP/target_update_device_messages.cpp =================================================================== --- test/OpenMP/target_update_device_messages.cpp +++ test/OpenMP/target_update_device_messages.cpp @@ -12,11 +12,11 @@ template int tmain(T argc, S **argv) { int i; -#pragma omp target update device // expected-error {{expected '(' after 'device'}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} -#pragma omp target update device ( // expected-error {{expected expression}} 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 device () // expected-error {{expected expression}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} -#pragma omp target update device (argc // 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 device (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(i) device // expected-error {{expected '(' after 'device'}} +#pragma omp target update to(i) device ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} +#pragma omp target update to(i) device () // expected-error {{expected expression}} +#pragma omp target update to(i) device (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} +#pragma omp target update to(i) device (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}} #pragma omp target update device (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} #pragma omp target update device (argc + argc) // expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} #pragma omp target update device (argc), device (argc+1) // expected-error {{directive '#pragma omp target update' cannot contain more than one 'device' clause}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} @@ -27,17 +27,17 @@ int main(int argc, char **argv) { int j; -#pragma omp target update device // expected-error {{expected '(' after 'device'}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(j) device // expected-error {{expected '(' after 'device'}} #pragma omp target update device ( // expected-error {{expected expression}} 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 device () // expected-error {{expected expression}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(j) device () // expected-error {{expected expression}} #pragma omp target update device (argc // 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 device (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(j) device (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}} #pragma omp target update device (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} -#pragma omp target update device (argc + argc) // expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(j) device (argc + argc) #pragma omp target update device (argc), device (argc+1) // expected-error {{directive '#pragma omp target update' cannot contain more than one 'device' clause}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} -#pragma omp target update device (S1) // expected-error {{'S1' does not refer to a value}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(j) device (S1) // expected-error {{'S1' does not refer to a value}} #pragma omp target update device (-2) // expected-error {{argument to 'device' clause must be a non-negative integer value}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} -#pragma omp target update device (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(j) device (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}} return tmain(argc, argv); } Index: test/OpenMP/target_update_if_messages.cpp =================================================================== --- test/OpenMP/target_update_if_messages.cpp +++ test/OpenMP/target_update_if_messages.cpp @@ -12,47 +12,47 @@ template // expected-note {{declared here}} int tmain(T argc, S **argv) { int n; -#pragma omp target update if // expected-error {{expected '(' after 'if'}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(n) if // expected-error {{expected '(' after 'if'}} #pragma omp target update if ( // expected-error {{expected expression}} 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 if () // expected-error {{expected expression}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(n) if () // expected-error {{expected expression}} #pragma omp target update if (argc // 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 if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(n) if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}} #pragma omp target update if (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} -#pragma omp target update if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp target update' cannot contain more than one 'if' clause}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(n) if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp target update' cannot contain more than one 'if' clause}} #pragma omp target update if (S) // expected-error {{'S' does not refer to a value}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} -#pragma omp target update if (argv[1]=2) // 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(n) if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} #pragma omp target update if (argc argc) // 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 if(argc) // expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(n) if(argc) #pragma omp target update if(target update // expected-warning {{missing ':' after directive name modifier - ignoring}} expected-error {{expected expression}} 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 if(target update : // expected-error {{expected expression}} 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(n) if(target update : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} #pragma omp target update if(target update : argc // 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 if(target update : argc) // expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(n) if(target update : argc) #pragma omp target update if(target update : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp target update'}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} -#pragma omp target update if(target update : argc) if (target update:argc) // expected-error {{directive '#pragma omp target update' cannot contain more than one 'if' clause with 'target update' name modifier}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(n) if(target update : argc) if (target update:argc) // expected-error {{directive '#pragma omp target update' cannot contain more than one 'if' clause with 'target update' name modifier}} #pragma omp target update if(target update : argc) if (argc) // expected-error {{no more 'if' clause is allowed}} expected-note {{previous clause with directive name modifier specified here}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} return 0; } int main(int argc, char **argv) { int m; -#pragma omp target update if // expected-error {{expected '(' after 'if'}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(m) if // expected-error {{expected '(' after 'if'}} #pragma omp target update if ( // expected-error {{expected expression}} 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 if () // expected-error {{expected expression}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(m) if () // expected-error {{expected expression}} #pragma omp target update if (argc // 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 if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(m) if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}} #pragma omp target update if (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} -#pragma omp target update if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp target update' cannot contain more than one 'if' clause}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(m) if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp target update' cannot contain more than one 'if' clause}} #pragma omp target update if (S1) // expected-error {{'S1' does not refer to a value}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} -#pragma omp target update if (argv[1]=2) // 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(m) if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} #pragma omp target update if (argc argc) // 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 if (1 0) // 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(m) if (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}} #pragma omp target update if(if(tmain(argc, argv) // expected-error {{expected expression}} 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 if(target update // expected-warning {{missing ':' after directive name modifier - ignoring}} expected-error {{expected expression}} 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(m) if(target update // expected-warning {{missing ':' after directive name modifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} #pragma omp target update if(target update : // expected-error {{expected expression}} 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 if(target update : argc // 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(m) if(target update : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} #pragma omp target update if(target update : argc) // expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} -#pragma omp target update if(target update : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp target update'}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(m) if(target update : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp target update'}} #pragma omp target update if(target update : argc) if (target update:argc) // expected-error {{directive '#pragma omp target update' cannot contain more than one 'if' clause with 'target update' name modifier}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} -#pragma omp target update if(target update : argc) if (argc) // expected-error {{no more 'if' clause is allowed}} expected-note {{previous clause with directive name modifier specified here}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(m) if(target update : argc) if (argc) // expected-error {{no more 'if' clause is allowed}} expected-note {{previous clause with directive name modifier specified here}} return tmain(argc, argv); } Index: test/OpenMP/target_update_messages.cpp =================================================================== --- test/OpenMP/target_update_messages.cpp +++ test/OpenMP/target_update_messages.cpp @@ -18,13 +18,13 @@ int main(int argc, char **argv) { int m; #pragma omp target update // expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} - #pragma omp target update { // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} - #pragma omp target update ( // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} - #pragma omp target update [ // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} - #pragma omp target update ] // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} - #pragma omp target update ) // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} + #pragma omp target update to(m) { // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}} + #pragma omp target update to(m) ( // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}} + #pragma omp target update to(m) [ // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}} + #pragma omp target update to(m) ] // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}} + #pragma omp target update to(m) ) // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}} - #pragma omp target update // expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} + #pragma omp target update to(m) // OK { foo(); } Index: test/OpenMP/target_update_to_messages.cpp =================================================================== --- /dev/null +++ test/OpenMP/target_update_to_messages.cpp @@ -0,0 +1,175 @@ +// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s + +void foo() { +} + +bool foobool(int argc) { + return argc; +} + +struct S1; // expected-note 2 {{declared here}} +extern S1 a; +class S2 { + mutable int a; +public: + S2():a(0) { } + S2(S2 &s2):a(s2.a) { } + static float S2s; // expected-note 4 {{mappable type cannot contain static members}} + static const float S2sc; // expected-note 4 {{mappable type cannot contain static members}} +}; +const float S2::S2sc = 0; +const S2 b; +const S2 ba[5]; +class S3 { + int a; +public: + S3():a(0) { } + S3(S3 &s3):a(s3.a) { } +}; +const S3 c; +const S3 ca[5]; +extern const int f; +class S4 { + int a; + S4(); + S4(const S4 &s4); +public: + S4(int v):a(v) { } +}; +class S5 { + int a; + S5():a(0) {} + S5(const S5 &s5):a(s5.a) { } +public: + S5(int v):a(v) { } +}; +struct S6 { + int ii; + int aa[30]; + float xx; + double *pp; +}; +struct S7 { + int i; + int a[50]; + float x; + S6 s6[5]; + double *p; + unsigned bfa : 4; +}; + +S3 h; +#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}} + +typedef int from; + +template // expected-note {{declared here}} +T tmain(T argc) { + const T d = 5; + const T da[5] = { 0 }; + S4 e(4); + S5 g(5); + T *m; + T i, t[20]; + T &j = i; + T *k = &j; + T x; + T y; + T to; + const T (&l)[5] = da; + S7 s7; + +#pragma omp target update to // expected-error {{expected '(' after 'to'}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to() // expected-error {{expected expression}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update() // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(alloc) // expected-error {{use of undeclared identifier 'alloc'}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(x) +#pragma omp target update to(t[:I]) +#pragma omp target update to(T) // expected-error {{'T' does not refer to a value}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(I) // expected-error 2 {{expected expression containing only member accesses and/or array sections based on named variables}} +#pragma omp target update to(S2::S2s) +#pragma omp target update to(S2::S2sc) +#pragma omp target update to(to) +#pragma omp target update to(y x) // expected-error {{expected ',' or ')' in 'to' clause}} +#pragma omp target update to(argc > 0 ? x : y) // expected-error 2 {{expected expression containing only member accesses and/or array sections based on named variables}} +#pragma omp target update to(S1) // expected-error {{'S1' does not refer to a value}}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} expected-error 2 {{type 'S2' is not mappable to target}} +#pragma omp target update to(ba) // expected-error 2 {{type 'S2' is not mappable to target}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(h) // expected-error {{threadprivate variables are not allowed in 'to' clause}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(k), to(k) // expected-error 2 {{variable can appear only once in OpenMP 'target update' construct}} expected-note 2 {{used here}} +#pragma omp target update to(t), to(t[:5]) // expected-error 2 {{variable can appear only once in OpenMP 'target update' construct}} expected-note 2 {{used here}} +#pragma omp target update to(da) +#pragma omp target update to(da[:4]) + +#pragma omp target update to(x, a[:2]) // expected-error {{subscripted value is not an array or pointer}} +#pragma omp target update to(x, c[:]) // expected-error {{subscripted value is not an array or pointer}} +#pragma omp target update to(x, (m+1)[2]) // expected-error 2 {{expected expression containing only member accesses and/or array sections based on named variables}} +#pragma omp target update to(s7.i, s7.a[:3]) +#pragma omp target update to(s7.s6[1].aa[0:5]) +#pragma omp target update to(x, s7.s6[:5].aa[6]) // expected-error {{OpenMP array section is not allowed here}} +#pragma omp target update to(x, s7.s6[:5].aa[:6]) // expected-error {{OpenMP array section is not allowed here}} +#pragma omp target update to(s7.p[:10]) +#pragma omp target update to(x, s7.bfa) // expected-error {{bit fields cannot be used to specify storage in a 'to' clause}} +#pragma omp target update to(x, s7.p[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} +#pragma omp target data map(to: s7.i) + { +#pragma omp target update to(s7.x) + } + return 0; +} + +int main(int argc, char **argv) { + const int d = 5; + const int da[5] = { 0 }; + S4 e(4); + S5 g(5); + int i, t[20]; + int &j = i; + int *k = &j; + int x; + int y; + int to; + const int (&l)[5] = da; + S7 s7; + int *m; + +#pragma omp target update to // expected-error {{expected '(' after 'to'}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to() // expected-error {{expected expression}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update() // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(alloc) // expected-error {{use of undeclared identifier 'alloc'}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(x) +#pragma omp target update to(t[:i]) +#pragma omp target update to(S2::S2s) +#pragma omp target update to(S2::S2sc) +#pragma omp target update to(to) +#pragma omp target update to(y x) // expected-error {{expected ',' or ')' in 'to' clause}} +#pragma omp target update to(argc > 0 ? x : y) // expected-error {{expected expression containing only member accesses and/or array sections based on named variables}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(S1) // expected-error {{'S1' does not refer to a value}}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} expected-error 2 {{type 'S2' is not mappable to target}} +#pragma omp target update to(ba) // expected-error 2 {{type 'S2' is not mappable to target}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(h) // expected-error {{threadprivate variables are not allowed in 'to' clause}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}} +#pragma omp target update to(k), to(k) // expected-error {{variable can appear only once in OpenMP 'target update' construct}} expected-note {{used here}} +#pragma omp target update to(t), to(t[:5]) // expected-error {{variable can appear only once in OpenMP 'target update' construct}} expected-note {{used here}} +#pragma omp target update to(da) +#pragma omp target update to(da[:4]) + +#pragma omp target update to(x, a[:2]) // expected-error {{subscripted value is not an array or pointer}} +#pragma omp target update to(x, c[:]) // expected-error {{subscripted value is not an array or pointer}} +#pragma omp target update to(x, (m+1)[2]) // expected-error {{expected expression containing only member accesses and/or array sections based on named variables}} +#pragma omp target update to(s7.i, s7.a[:3]) +#pragma omp target update to(s7.s6[1].aa[0:5]) +#pragma omp target update to(x, s7.s6[:5].aa[6]) // expected-error {{OpenMP array section is not allowed here}} +#pragma omp target update to(x, s7.s6[:5].aa[:6]) // expected-error {{OpenMP array section is not allowed here}} +#pragma omp target update to(s7.p[:10]) +#pragma omp target update to(x, s7.bfa) // expected-error {{bit fields cannot be used to specify storage in a 'to' clause}} +#pragma omp target update to(x, s7.p[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} +#pragma omp target data map(to: s7.i) + { +#pragma omp target update to(s7.x) + } + + 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}} +} + Index: tools/libclang/CIndex.cpp =================================================================== --- tools/libclang/CIndex.cpp +++ tools/libclang/CIndex.cpp @@ -2246,6 +2246,9 @@ } void OMPClauseEnqueue::VisitOMPDefaultmapClause( const OMPDefaultmapClause * /*C*/) {} +void OMPClauseEnqueue::VisitOMPToClause(const OMPToClause *C) { + VisitOMPClauseList(C); +} } void EnqueueVisitor::EnqueueChildren(const OMPClause *S) {