Index: include/clang/AST/OpenMPClause.h =================================================================== --- include/clang/AST/OpenMPClause.h +++ include/clang/AST/OpenMPClause.h @@ -4010,6 +4010,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 @@ -7934,8 +7934,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< @@ -8076,6 +8076,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< @@ -8213,8 +8215,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 @@ -8418,6 +8418,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; } @@ -625,3 +627,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 @@ -3134,6 +3134,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 @@ -6521,10 +6521,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(); @@ -6798,6 +6799,7 @@ case OMPC_defaultmap: case OMPC_unknown: case OMPC_uniform: + case OMPC_to: llvm_unreachable("Clause is not allowed."); } return Res; @@ -7084,6 +7086,7 @@ case OMPC_defaultmap: case OMPC_unknown: case OMPC_uniform: + case OMPC_to: llvm_unreachable("Clause is not allowed."); } return Res; @@ -7235,6 +7238,7 @@ case OMPC_hint: case OMPC_unknown: case OMPC_uniform: + case OMPC_to: llvm_unreachable("Clause is not allowed."); } return Res; @@ -7419,6 +7423,7 @@ case OMPC_defaultmap: case OMPC_unknown: case OMPC_uniform: + case OMPC_to: llvm_unreachable("Clause is not allowed."); } return Res; @@ -7532,6 +7537,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: @@ -9874,13 +9882,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(); @@ -9966,8 +9975,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; } @@ -10089,7 +10098,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(); @@ -10164,7 +10174,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; @@ -10219,7 +10235,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; @@ -10264,32 +10286,51 @@ 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; +namespace { +// Utility struct that gathers all the related lists associated with a mappable +// expression. +struct MappableVarListInfo final { + // The list of expressions. + ArrayRef VarList; + // The list of processed expressions. + SmallVector ProcessedVarList; + // The mappble components for each expression. + OMPClauseMappableExprCommon::MappableExprComponentLists VarComponents; + // The base declaration of the variable. + SmallVector VarBaseDeclarations; + + MappableVarListInfo(ArrayRef VarList) : VarList(VarList) { + // We have a list of components and base declarations for each entry in the + // variable list. + VarComponents.reserve(VarList.size()); + VarBaseDeclarations.reserve(VarList.size()); + } +}; +} + +// 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, MappableVarListInfo &MVLI, + 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"); - if (isa(RE)) { - // It will be analyzed later. - Vars.push_back(RE); - continue; - } + for (auto &RE : MVLI.VarList) { + assert(RE && "Null expr in omp to/map clause"); SourceLocation ELoc = RE->getExprLoc(); auto *VE = RE->IgnoreParenLValueCasts(); @@ -10299,14 +10340,15 @@ VE->containsUnexpandedParameterPack()) { // We can only analyze this information once the missing information is // resolved. - Vars.push_back(RE); + MVLI.ProcessedVarList.push_back(RE); continue; } 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; } @@ -10316,7 +10358,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; @@ -10339,107 +10382,125 @@ (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)) + if (!CheckTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef, + DSAS, 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); - 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. + 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. - Vars.push_back(RE); + MVLI.ProcessedVarList.push_back(RE); // 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 // null as base declaration. - ClauseComponents.resize(ClauseComponents.size() + 1); - ClauseComponents.back().append(CurComponents.begin(), CurComponents.end()); - ClauseBaseDeclarations.push_back(isa(BE) ? nullptr - : CurDeclaration); + MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1); + MVLI.VarComponents.back().append(CurComponents.begin(), + CurComponents.end()); + MVLI.VarBaseDeclarations.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) { + MappableVarListInfo MVLI(VarList); + checkMappableExpressionList(*this, DSAStack, OMPC_map, MVLI, 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. - return OMPMapClause::Create( - Context, StartLoc, LParenLoc, EndLoc, Vars, ClauseBaseDeclarations, - ClauseComponents, MapTypeModifier, MapType, IsMapTypeImplicit, MapLoc); + return OMPMapClause::Create(Context, StartLoc, LParenLoc, EndLoc, + MVLI.ProcessedVarList, MVLI.VarBaseDeclarations, + MVLI.VarComponents, MapTypeModifier, MapType, + IsMapTypeImplicit, MapLoc); } QualType Sema::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, @@ -11042,3 +11103,17 @@ } checkDeclInTargetContext(E->getExprLoc(), E->getSourceRange(), *this, D); } + +OMPClause *Sema::ActOnOpenMPToClause(ArrayRef VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + MappableVarListInfo MVLI(VarList); + checkMappableExpressionList(*this, DSAStack, OMPC_to, MVLI, StartLoc); + if (MVLI.ProcessedVarList.empty()) + return nullptr; + + return OMPToClause::Create(Context, StartLoc, LParenLoc, EndLoc, + MVLI.ProcessedVarList, MVLI.VarBaseDeclarations, + MVLI.VarComponents); +} 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)); @@ -2323,6 +2332,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 @@ -2091,6 +2091,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 @@ -135,7 +135,7 @@ } #pragma omp parallel { -#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(a) } // SIMD DIRECTIVE @@ -299,7 +299,7 @@ } #pragma omp simd for (int i = 0; i < 10; ++i) { -#pragma omp target update // expected-error {{OpenMP constructs may not be nested inside a simd region}} +#pragma omp target update to(a) // expected-error {{OpenMP constructs may not be nested inside a simd region}} } // FOR DIRECTIVE @@ -486,7 +486,7 @@ } #pragma omp for for (int i = 0; i < 10; ++i) { -#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(a) } // FOR SIMD DIRECTIVE @@ -650,7 +650,7 @@ } #pragma omp for simd for (int i = 0; i < 10; ++i) { -#pragma omp target update // expected-error {{OpenMP constructs may not be nested inside a simd region}} +#pragma omp target update to(a) // expected-error {{OpenMP constructs may not be nested inside a simd region}} bar(); } @@ -843,7 +843,7 @@ } #pragma omp sections { -#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(a) } // SECTION DIRECTIVE @@ -1088,7 +1088,7 @@ #pragma omp section { bar(); -#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(a) } } @@ -1266,7 +1266,7 @@ } #pragma omp single { -#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(a) bar(); } @@ -1444,7 +1444,7 @@ } #pragma omp master { -#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(a) bar(); } @@ -1636,7 +1636,7 @@ } #pragma omp critical { -#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(a) bar(); } @@ -1829,7 +1829,7 @@ } #pragma omp parallel for for (int i = 0; i < 10; ++i) { -#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(a) } // PARALLEL FOR SIMD DIRECTIVE @@ -2021,7 +2021,7 @@ } #pragma omp parallel for simd for (int i = 0; i < 10; ++i) { -#pragma omp target update // expected-error {{OpenMP constructs may not be nested inside a simd region}} +#pragma omp target update to(a) // expected-error {{OpenMP constructs may not be nested inside a simd region}} bar(); } @@ -2203,7 +2203,7 @@ } #pragma omp parallel sections { -#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(a) } // TASK DIRECTIVE @@ -2330,7 +2330,7 @@ } #pragma omp task { -#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(a) bar(); } @@ -2529,7 +2529,7 @@ #pragma omp ordered { bar(); -#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(a) bar(); } @@ -2750,7 +2750,7 @@ // 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}} +#pragma omp target update to(a) // expected-error {{OpenMP constructs may not be nested inside an atomic region}} bar(); } @@ -2889,7 +2889,7 @@ } #pragma omp target { -#pragma omp target update // expected-error {{region cannot be nested inside 'target' region}} +#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target' region}} } // TARGET PARALLEL DIRECTIVE @@ -3027,7 +3027,7 @@ } #pragma omp target parallel { -#pragma omp target update // expected-error {{region cannot be nested inside 'target parallel' region}} +#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target parallel' region}} } // TARGET PARALLEL FOR DIRECTIVE @@ -3219,7 +3219,7 @@ } #pragma omp target parallel for for (int i = 0; i < 10; ++i) { -#pragma omp target update // expected-error {{region cannot be nested inside 'target parallel for' region}} +#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target parallel for' region}} } // TEAMS DIRECTIVE @@ -3387,7 +3387,7 @@ #pragma omp target #pragma omp teams { -#pragma omp target update // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp target update' directive into a parallel region?}} +#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 @@ -3563,7 +3563,7 @@ } #pragma omp taskloop for (int i = 0; i < 10; ++i) { -#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(a) bar(); } @@ -3789,7 +3789,7 @@ #pragma omp teams #pragma omp distribute for (int i = 0; i < 10; ++i) { -#pragma omp target update // expected-error {{region cannot be nested inside 'target' region}} +#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target' region}} ++a; } } @@ -3924,7 +3924,7 @@ } #pragma omp parallel { -#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(a) a++; } @@ -4082,7 +4082,7 @@ } #pragma omp simd for (int i = 0; i < 10; ++i) { -#pragma omp target update // expected-error {{OpenMP constructs may not be nested inside a simd region}} +#pragma omp target update to(a) // expected-error {{OpenMP constructs may not be nested inside a simd region}} a++; } @@ -4260,7 +4260,7 @@ } #pragma omp for for (int i = 0; i < 10; ++i) { -#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(a) ++a; } @@ -4418,7 +4418,7 @@ } #pragma omp for simd for (int i = 0; i < 10; ++i) { -#pragma omp target update // expected-error {{OpenMP constructs may not be nested inside a simd region}} +#pragma omp target update to(a) // expected-error {{OpenMP constructs may not be nested inside a simd region}} ++a; } @@ -4586,7 +4586,7 @@ } #pragma omp sections { -#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(a) } // SECTION DIRECTIVE @@ -4840,7 +4840,7 @@ { #pragma omp section { -#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(a) a++; } } @@ -5009,7 +5009,7 @@ } #pragma omp single { -#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(a) a++; } @@ -5187,7 +5187,7 @@ } #pragma omp master { -#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(a) ++a; } @@ -5384,7 +5384,7 @@ } #pragma omp critical { -#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(a) a++; } @@ -5577,7 +5577,7 @@ } #pragma omp parallel for for (int i = 0; i < 10; ++i) { -#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(a) a++; } @@ -5770,7 +5770,7 @@ } #pragma omp parallel for simd for (int i = 0; i < 10; ++i) { -#pragma omp target update // expected-error {{OpenMP constructs may not be nested inside a simd region}} +#pragma omp target update to(a) // expected-error {{OpenMP constructs may not be nested inside a simd region}} a++; } @@ -5948,7 +5948,7 @@ } #pragma omp parallel sections { -#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(a) } // TASK DIRECTIVE @@ -6074,7 +6074,7 @@ } #pragma omp task { -#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(a) a++; } @@ -6435,7 +6435,7 @@ // 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}} +#pragma omp target update to(a) // expected-error {{OpenMP constructs may not be nested inside an atomic region}} a++; } @@ -6574,7 +6574,7 @@ } #pragma omp target parallel { -#pragma omp target update // expected-error {{region cannot be nested inside 'target parallel' region}} +#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target parallel' region}} } @@ -6767,7 +6767,7 @@ } #pragma omp target parallel for for (int i = 0; i < 10; ++i) { -#pragma omp target update // expected-error {{region cannot be nested inside 'target parallel for' region}} +#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target parallel for' region}} a++; } @@ -6934,7 +6934,7 @@ #pragma omp target #pragma omp teams { -#pragma omp target update // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp target update' directive into a parallel region?}} +#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; } @@ -7111,7 +7111,7 @@ } #pragma omp taskloop for (int i = 0; i < 10; ++i) { -#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(a) ++a; } @@ -7337,7 +7337,7 @@ #pragma omp teams #pragma omp distribute for (int i = 0; i < 10; ++i) { -#pragma omp target update // expected-error {{region cannot be nested inside 'target' region}} +#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) {