Index: include/clang-c/Index.h =================================================================== --- include/clang-c/Index.h +++ include/clang-c/Index.h @@ -2278,7 +2278,11 @@ */ CXCursor_OMPTargetEnterDataDirective = 261, - CXCursor_LastStmt = CXCursor_OMPTargetEnterDataDirective, + /** \brief OpenMP target exit data directive. + */ + CXCursor_OMPTargetExitDataDirective = 262, + + CXCursor_LastStmt = CXCursor_OMPTargetExitDataDirective, /** * \brief Cursor that represents the translation unit itself. Index: include/clang/AST/RecursiveASTVisitor.h =================================================================== --- include/clang/AST/RecursiveASTVisitor.h +++ include/clang/AST/RecursiveASTVisitor.h @@ -2436,6 +2436,9 @@ DEF_TRAVERSE_STMT(OMPTargetEnterDataDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPTargetExitDataDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPTeamsDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) Index: include/clang/AST/StmtOpenMP.h =================================================================== --- include/clang/AST/StmtOpenMP.h +++ include/clang/AST/StmtOpenMP.h @@ -2098,6 +2098,64 @@ } }; +/// \brief This represents '#pragma omp target exit data' directive. +/// +/// \code +/// #pragma omp target exit data device(0) if(a) map(b[:]) +/// \endcode +/// In this example directive '#pragma omp target exit data' has clauses +/// 'device' with the value '0', 'if' with condition 'a' and 'map' with array +/// section 'b[:]'. +/// +class OMPTargetExitDataDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param NumClauses The number of clauses. + /// + OMPTargetExitDataDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPTargetExitDataDirectiveClass, + OMPD_target_exit_data, StartLoc, EndLoc, + NumClauses, /*NumChildren=*/0) {} + + /// \brief Build an empty directive. + /// + /// \param NumClauses Number of clauses. + /// + explicit OMPTargetExitDataDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPTargetExitDataDirectiveClass, + OMPD_target_exit_data, SourceLocation(), + SourceLocation(), NumClauses, + /*NumChildren=*/0) {} +public: + /// \brief Creates directive with a list of \a Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// + static OMPTargetExitDataDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef Clauses); + + /// \brief Creates an empty directive with the place for \a N clauses. + /// + /// \param C AST context. + /// \param N The number of clauses. + /// + static OMPTargetExitDataDirective *CreateEmpty(const ASTContext &C, + unsigned N, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTargetExitDataDirectiveClass; + } +}; + /// \brief This represents '#pragma omp teams' directive. /// /// \code Index: include/clang/Basic/OpenMPKinds.def =================================================================== --- include/clang/Basic/OpenMPKinds.def +++ include/clang/Basic/OpenMPKinds.def @@ -63,6 +63,9 @@ #ifndef OPENMP_TARGET_ENTER_DATA_CLAUSE #define OPENMP_TARGET_ENTER_DATA_CLAUSE(Name) #endif +#ifndef OPENMP_TARGET_EXIT_DATA_CLAUSE +#define OPENMP_TARGET_EXIT_DATA_CLAUSE(Name) +#endif #ifndef OPENMP_TEAMS_CLAUSE # define OPENMP_TEAMS_CLAUSE(Name) #endif @@ -129,6 +132,7 @@ OPENMP_DIRECTIVE(cancel) OPENMP_DIRECTIVE_EXT(target_data, "target data") OPENMP_DIRECTIVE_EXT(target_enter_data, "target enter data") +OPENMP_DIRECTIVE_EXT(target_exit_data, "target exit data") OPENMP_DIRECTIVE_EXT(parallel_for, "parallel for") OPENMP_DIRECTIVE_EXT(parallel_for_simd, "parallel for simd") OPENMP_DIRECTIVE_EXT(parallel_sections, "parallel sections") @@ -359,6 +363,12 @@ OPENMP_TARGET_ENTER_DATA_CLAUSE(device) OPENMP_TARGET_ENTER_DATA_CLAUSE(map) +// Clauses allowed for OpenMP directive 'target exit data'. +// TODO More clauses for 'target exit data' directive. +OPENMP_TARGET_EXIT_DATA_CLAUSE(if) +OPENMP_TARGET_EXIT_DATA_CLAUSE(device) +OPENMP_TARGET_EXIT_DATA_CLAUSE(map) + // Clauses allowed for OpenMP directive 'teams'. // TODO More clauses for 'teams' directive. OPENMP_TEAMS_CLAUSE(default) @@ -454,6 +464,7 @@ #undef OPENMP_TARGET_CLAUSE #undef OPENMP_TARGET_DATA_CLAUSE #undef OPENMP_TARGET_ENTER_DATA_CLAUSE +#undef OPENMP_TARGET_EXIT_DATA_CLAUSE #undef OPENMP_TEAMS_CLAUSE #undef OPENMP_SIMD_CLAUSE #undef OPENMP_FOR_CLAUSE Index: include/clang/Basic/StmtNodes.td =================================================================== --- include/clang/Basic/StmtNodes.td +++ include/clang/Basic/StmtNodes.td @@ -217,6 +217,7 @@ def OMPTargetDirective : DStmt; def OMPTargetDataDirective : DStmt; def OMPTargetEnterDataDirective : DStmt; +def OMPTargetExitDataDirective : DStmt; def OMPTeamsDirective : DStmt; def OMPCancellationPointDirective : DStmt; def OMPCancelDirective : DStmt; Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -7946,6 +7946,11 @@ StmtResult ActOnOpenMPTargetEnterDataDirective(ArrayRef Clauses, SourceLocation StartLoc, SourceLocation EndLoc); + /// \brief Called on well-formed '\#pragma omp target exit data' after + /// parsing of the associated statement. + StmtResult ActOnOpenMPTargetExitDataDirective(ArrayRef Clauses, + SourceLocation StartLoc, + SourceLocation EndLoc); /// \brief Called on well-formed '\#pragma omp teams' after parsing of the /// associated statement. StmtResult ActOnOpenMPTeamsDirective(ArrayRef Clauses, Index: include/clang/Serialization/ASTBitCodes.h =================================================================== --- include/clang/Serialization/ASTBitCodes.h +++ include/clang/Serialization/ASTBitCodes.h @@ -1446,6 +1446,7 @@ STMT_OMP_TARGET_DIRECTIVE, STMT_OMP_TARGET_DATA_DIRECTIVE, STMT_OMP_TARGET_ENTER_DATA_DIRECTIVE, + STMT_OMP_TARGET_EXIT_DATA_DIRECTIVE, STMT_OMP_TEAMS_DIRECTIVE, STMT_OMP_TASKGROUP_DIRECTIVE, STMT_OMP_CANCELLATION_POINT_DIRECTIVE, Index: lib/AST/StmtOpenMP.cpp =================================================================== --- lib/AST/StmtOpenMP.cpp +++ lib/AST/StmtOpenMP.cpp @@ -740,6 +740,28 @@ return new (Mem) OMPTargetEnterDataDirective(N); } +OMPTargetExitDataDirective *OMPTargetExitDataDirective::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef Clauses) { + void *Mem = + C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPTargetExitDataDirective), + llvm::alignOf()) + + sizeof(OMPClause *) * Clauses.size()); + OMPTargetExitDataDirective *Dir = + new (Mem) OMPTargetExitDataDirective(StartLoc, EndLoc, Clauses.size()); + Dir->setClauses(Clauses); + return Dir; +} + +OMPTargetExitDataDirective *OMPTargetExitDataDirective::CreateEmpty( + const ASTContext &C, unsigned N, EmptyShell) { + void *Mem = + C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPTargetExitDataDirective), + llvm::alignOf()) + + sizeof(OMPClause *) * N); + return new (Mem) OMPTargetExitDataDirective(N); +} + OMPTeamsDirective *OMPTeamsDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Index: lib/AST/StmtPrinter.cpp =================================================================== --- lib/AST/StmtPrinter.cpp +++ lib/AST/StmtPrinter.cpp @@ -1057,6 +1057,12 @@ PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPTargetExitDataDirective( + OMPTargetExitDataDirective *Node) { + Indent() << "#pragma omp target exit data "; + PrintOMPExecutableDirective(Node); +} + void StmtPrinter::VisitOMPTeamsDirective(OMPTeamsDirective *Node) { Indent() << "#pragma omp teams "; PrintOMPExecutableDirective(Node); Index: lib/AST/StmtProfile.cpp =================================================================== --- lib/AST/StmtProfile.cpp +++ lib/AST/StmtProfile.cpp @@ -589,6 +589,11 @@ VisitOMPExecutableDirective(S); } +void StmtProfiler::VisitOMPTargetExitDataDirective( + const OMPTargetExitDataDirective *S) { + VisitOMPExecutableDirective(S); +} + void StmtProfiler::VisitOMPTeamsDirective(const OMPTeamsDirective *S) { VisitOMPExecutableDirective(S); } Index: lib/Basic/OpenMPKinds.cpp =================================================================== --- lib/Basic/OpenMPKinds.cpp +++ lib/Basic/OpenMPKinds.cpp @@ -408,6 +408,16 @@ break; } break; + case OMPD_target_exit_data: + switch (CKind) { +#define OPENMP_TARGET_EXIT_DATA_CLAUSE(Name) \ + case OMPC_##Name: \ + return true; +#include "clang/Basic/OpenMPKinds.def" + default: + break; + } + break; case OMPD_teams: switch (CKind) { #define OPENMP_TEAMS_CLAUSE(Name) \ Index: lib/CodeGen/CGStmt.cpp =================================================================== --- lib/CodeGen/CGStmt.cpp +++ lib/CodeGen/CGStmt.cpp @@ -259,6 +259,9 @@ case Stmt::OMPTargetEnterDataDirectiveClass: EmitOMPTargetEnterDataDirective(cast(*S)); break; + case Stmt::OMPTargetExitDataDirectiveClass: + EmitOMPTargetExitDataDirective(cast(*S)); + break; case Stmt::OMPTaskLoopDirectiveClass: EmitOMPTaskLoopDirective(cast(*S)); break; Index: lib/CodeGen/CGStmtOpenMP.cpp =================================================================== --- lib/CodeGen/CGStmtOpenMP.cpp +++ lib/CodeGen/CGStmtOpenMP.cpp @@ -2665,6 +2665,11 @@ // TODO: codegen for target enter data. } +void CodeGenFunction::EmitOMPTargetExitDataDirective( + const OMPTargetExitDataDirective &S) { + // TODO: codegen for target exit data. +} + void CodeGenFunction::EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S) { // emit the code inside the construct for now auto CS = cast(S.getAssociatedStmt()); Index: lib/CodeGen/CodeGenFunction.h =================================================================== --- lib/CodeGen/CodeGenFunction.h +++ lib/CodeGen/CodeGenFunction.h @@ -2336,6 +2336,7 @@ void EmitOMPTargetDirective(const OMPTargetDirective &S); void EmitOMPTargetDataDirective(const OMPTargetDataDirective &S); void EmitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective &S); + void EmitOMPTargetExitDataDirective(const OMPTargetExitDataDirective &S); void EmitOMPTeamsDirective(const OMPTeamsDirective &S); void EmitOMPCancellationPointDirective(const OMPCancellationPointDirective &S); Index: lib/Parse/ParseOpenMP.cpp =================================================================== --- lib/Parse/ParseOpenMP.cpp +++ lib/Parse/ParseOpenMP.cpp @@ -38,6 +38,8 @@ OMPD_unknown /*target enter/exit*/}, {OMPD_unknown /*target enter*/, OMPD_unknown /*data*/, OMPD_target_enter_data}, + {OMPD_unknown /*target exit*/, OMPD_unknown /*data*/, + OMPD_target_exit_data}, {OMPD_for, OMPD_simd, OMPD_for_simd}, {OMPD_parallel, OMPD_for, OMPD_parallel_for}, {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd}, @@ -56,7 +58,9 @@ ((i == 0) && !P.getPreprocessor().getSpelling(Tok).compare("cancellation")) || ((i == 3) && - !P.getPreprocessor().getSpelling(Tok).compare("enter")); + !P.getPreprocessor().getSpelling(Tok).compare("enter")) || + ((i == 4) && + !P.getPreprocessor().getSpelling(Tok).compare("exit")); } else { TokenMatched = DKind == F[i][0] && DKind != OMPD_unknown; } @@ -73,10 +77,11 @@ TokenMatched = ((i == 0) && !P.getPreprocessor().getSpelling(Tok).compare("point")) || - ((i == 1 || i == 3) && + ((i == 1 || i == 3 || i == 4) && !P.getPreprocessor().getSpelling(Tok).compare("data")) || ((i == 2) && - !P.getPreprocessor().getSpelling(Tok).compare("enter")); + (!P.getPreprocessor().getSpelling(Tok).compare("enter") || + !P.getPreprocessor().getSpelling(Tok).compare("exit"))); } else { TokenMatched = SDKind == F[i][1] && SDKind != OMPD_unknown; } @@ -148,6 +153,7 @@ case OMPD_cancel: case OMPD_target_data: case OMPD_target_enter_data: + case OMPD_target_exit_data: case OMPD_taskloop: case OMPD_taskloop_simd: case OMPD_distribute: @@ -172,7 +178,8 @@ /// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' | /// 'for simd' | 'parallel for simd' | 'target' | 'target data' | /// 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' {clause} | -/// 'distribute' | 'target enter data' | annot_pragma_openmp_end +/// 'distribute' | 'target enter data' | 'target exit data' +/// annot_pragma_openmp_end /// StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { @@ -223,6 +230,7 @@ case OMPD_cancellation_point: case OMPD_cancel: case OMPD_target_enter_data: + case OMPD_target_exit_data: if (!StandAloneAllowed) { Diag(Tok, diag::err_omp_immediate_directive) << getOpenMPDirectiveName(DKind) << 0; Index: lib/Sema/SemaOpenMP.cpp =================================================================== --- lib/Sema/SemaOpenMP.cpp +++ lib/Sema/SemaOpenMP.cpp @@ -1611,6 +1611,7 @@ case OMPD_cancel: case OMPD_flush: case OMPD_target_enter_data: + case OMPD_target_exit_data: llvm_unreachable("OpenMP Directive is not allowed"); case OMPD_unknown: llvm_unreachable("Unknown OpenMP directive"); @@ -1727,6 +1728,8 @@ // | parallel | target | * | // | parallel | target enter | * | // | | data | | + // | parallel | target exit | * | + // | | data | | // | parallel | teams | + | // | parallel | cancellation | | // | | point | ! | @@ -1758,6 +1761,8 @@ // | for | target | * | // | for | target enter | * | // | | data | | + // | for | target exit | * | + // | | data | | // | for | teams | + | // | for | cancellation | | // | | point | ! | @@ -1789,6 +1794,8 @@ // | master | target | * | // | master | target enter | * | // | | data | | + // | master | target exit | * | + // | | data | | // | master | teams | + | // | master | cancellation | | // | | point | | @@ -1819,6 +1826,8 @@ // | critical | target | * | // | critical | target enter | * | // | | data | | + // | critical | target exit | * | + // | | data | | // | critical | teams | + | // | critical | cancellation | | // | | point | | @@ -1850,6 +1859,8 @@ // | simd | target | | // | simd | target enter | | // | | data | | + // | simd | target exit | | + // | | data | | // | simd | teams | | // | simd | cancellation | | // | | point | | @@ -1881,6 +1892,8 @@ // | for simd | target | | // | for simd | target enter | | // | | data | | + // | for simd | target exit | | + // | | data | | // | for simd | teams | | // | for simd | cancellation | | // | | point | | @@ -1912,6 +1925,8 @@ // | parallel for simd| target | | // | parallel for simd| target enter | | // | | data | | + // | parallel for simd| target exit | | + // | | data | | // | parallel for simd| teams | | // | parallel for simd| cancellation | | // | | point | | @@ -1943,6 +1958,8 @@ // | sections | target | * | // | sections | target enter | * | // | | data | | + // | sections | target exit | * | + // | | data | | // | sections | teams | + | // | sections | cancellation | | // | | point | ! | @@ -1974,6 +1991,8 @@ // | section | target | * | // | section | target enter | * | // | | data | | + // | section | target exit | * | + // | | data | | // | section | teams | + | // | section | cancellation | | // | | point | ! | @@ -2005,6 +2024,8 @@ // | single | target | * | // | single | target enter | * | // | | data | | + // | single | target exit | * | + // | | data | | // | single | teams | + | // | single | cancellation | | // | | point | | @@ -2036,6 +2057,8 @@ // | parallel for | target | * | // | parallel for | target enter | * | // | | data | | + // | parallel for | target exit | * | + // | | data | | // | parallel for | teams | + | // | parallel for | cancellation | | // | | point | ! | @@ -2067,6 +2090,8 @@ // | parallel sections| target | * | // | parallel sections| target enter | * | // | | data | | + // | parallel sections| target exit | * | + // | | data | | // | parallel sections| teams | + | // | parallel sections| cancellation | | // | | point | ! | @@ -2098,6 +2123,8 @@ // | task | target | * | // | task | target enter | * | // | | data | | + // | task | target exit | * | + // | | data | | // | task | teams | + | // | task | cancellation | | // | | point | ! | @@ -2129,6 +2156,8 @@ // | ordered | target | * | // | ordered | target enter | * | // | | data | | + // | ordered | target exit | * | + // | | data | | // | ordered | teams | + | // | ordered | cancellation | | // | | point | | @@ -2160,6 +2189,8 @@ // | atomic | target | | // | atomic | target enter | | // | | data | | + // | atomic | target exit | | + // | | data | | // | atomic | teams | | // | atomic | cancellation | | // | | point | | @@ -2191,6 +2222,8 @@ // | target | target | * | // | target | target enter | * | // | | data | | + // | target | target exit | * | + // | | data | | // | target | teams | * | // | target | cancellation | | // | | point | | @@ -2222,6 +2255,8 @@ // | teams | target | + | // | teams | target enter | + | // | | data | | + // | teams | target exit | + | + // | | data | | // | teams | teams | + | // | teams | cancellation | | // | | point | | @@ -2253,6 +2288,8 @@ // | taskloop | target | * | // | taskloop | target enter | * | // | | data | | + // | taskloop | target exit | * | + // | | data | | // | taskloop | teams | + | // | taskloop | cancellation | | // | | point | | @@ -2283,6 +2320,8 @@ // | taskloop simd | target | | // | taskloop simd | target enter | | // | | data | | + // | taskloop simd | target exit | | + // | | data | | // | taskloop simd | teams | | // | taskloop simd | cancellation | | // | | point | | @@ -2314,6 +2353,8 @@ // | distribute | target | | // | distribute | target enter | | // | | data | | + // | distribute | target exit | | + // | | data | | // | distribute | teams | | // | distribute | cancellation | + | // | | point | | @@ -2743,6 +2784,11 @@ EndLoc); AllowedNameModifiers.push_back(OMPD_target_enter_data); break; + case OMPD_target_exit_data: + Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc, + EndLoc); + AllowedNameModifiers.push_back(OMPD_target_exit_data); + break; case OMPD_taskloop: Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); @@ -5520,6 +5566,20 @@ return OMPTargetEnterDataDirective::Create(Context, StartLoc, EndLoc, Clauses); } +StmtResult Sema::ActOnOpenMPTargetExitDataDirective( + ArrayRef Clauses, SourceLocation StartLoc, + SourceLocation EndLoc) { + // OpenMP [2.10.3, Restrictions, p. 102] + // At least one map clause must appear on the directive. + if (!HasMapClause(Clauses)) { + Diag(StartLoc, diag::err_omp_no_map_for_directive) << + getOpenMPDirectiveName(OMPD_target_exit_data); + return StmtError(); + } + + return OMPTargetExitDataDirective::Create(Context, StartLoc, EndLoc, Clauses); +} + StmtResult Sema::ActOnOpenMPTeamsDirective(ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { @@ -8528,6 +8588,23 @@ // further spurious messages } + // 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) << + // TODO: Need to determine if map type is implicitly determined + 0 << + getOpenMPSimpleClauseTypeName(OMPC_map, MapType) << + getOpenMPDirectiveName(DKind); + // Proceed to add the variable in a map clause anyway, to prevent + // further spurious messages + } + Vars.push_back(RE); MI.RefExpr = RE; DSAStack->addMapInfoForVar(VD, MI); Index: lib/Sema/TreeTransform.h =================================================================== --- lib/Sema/TreeTransform.h +++ lib/Sema/TreeTransform.h @@ -7389,6 +7389,17 @@ } template +StmtResult TreeTransform::TransformOMPTargetExitDataDirective( + OMPTargetExitDataDirective *D) { + DeclarationNameInfo DirName; + getDerived().getSema().StartOpenMPDSABlock(OMPD_target_exit_data, DirName, + nullptr, D->getLocStart()); + StmtResult Res = getDerived().TransformOMPExecutableDirective(D); + getDerived().getSema().EndOpenMPDSABlock(Res.get()); + return Res; +} + +template StmtResult TreeTransform::TransformOMPTeamsDirective(OMPTeamsDirective *D) { DeclarationNameInfo DirName; Index: lib/Serialization/ASTReaderStmt.cpp =================================================================== --- lib/Serialization/ASTReaderStmt.cpp +++ lib/Serialization/ASTReaderStmt.cpp @@ -2449,6 +2449,13 @@ VisitOMPExecutableDirective(D); } +void ASTStmtReader::VisitOMPTargetExitDataDirective( + OMPTargetExitDataDirective *D) { + VisitStmt(D); + ++Idx; + VisitOMPExecutableDirective(D); +} + void ASTStmtReader::VisitOMPTeamsDirective(OMPTeamsDirective *D) { VisitStmt(D); // The NumClauses field was read in ReadStmtFromStream. @@ -3097,6 +3104,11 @@ Context, Record[ASTStmtReader::NumStmtFields], Empty); break; + case STMT_OMP_TARGET_EXIT_DATA_DIRECTIVE: + S = OMPTargetExitDataDirective::CreateEmpty( + Context, Record[ASTStmtReader::NumStmtFields], Empty); + break; + case STMT_OMP_TEAMS_DIRECTIVE: S = OMPTeamsDirective::CreateEmpty( Context, Record[ASTStmtReader::NumStmtFields], Empty); Index: lib/Serialization/ASTWriterStmt.cpp =================================================================== --- lib/Serialization/ASTWriterStmt.cpp +++ lib/Serialization/ASTWriterStmt.cpp @@ -2213,6 +2213,14 @@ Code = serialization::STMT_OMP_TARGET_ENTER_DATA_DIRECTIVE; } +void ASTStmtWriter::VisitOMPTargetExitDataDirective( + OMPTargetExitDataDirective *D) { + VisitStmt(D); + Record.push_back(D->getNumClauses()); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_TARGET_EXIT_DATA_DIRECTIVE; +} + void ASTStmtWriter::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *D) { VisitStmt(D); VisitOMPExecutableDirective(D); Index: lib/StaticAnalyzer/Core/ExprEngine.cpp =================================================================== --- lib/StaticAnalyzer/Core/ExprEngine.cpp +++ lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -831,6 +831,7 @@ case Stmt::OMPTargetDirectiveClass: case Stmt::OMPTargetDataDirectiveClass: case Stmt::OMPTargetEnterDataDirectiveClass: + case Stmt::OMPTargetExitDataDirectiveClass: case Stmt::OMPTeamsDirectiveClass: case Stmt::OMPCancellationPointDirectiveClass: case Stmt::OMPCancelDirectiveClass: Index: test/OpenMP/nesting_of_regions.cpp =================================================================== --- test/OpenMP/nesting_of_regions.cpp +++ test/OpenMP/nesting_of_regions.cpp @@ -102,6 +102,11 @@ } #pragma omp parallel { +#pragma omp target exit data map(from: a) + ++a; + } +#pragma omp parallel + { #pragma omp teams // expected-error {{region cannot be closely nested inside 'parallel' region; perhaps you forget to enclose 'omp teams' directive into a target region?}} ++a; } @@ -246,6 +251,11 @@ } #pragma omp simd for (int i = 0; i < 10; ++i) { +#pragma omp target exit data map(from: a) // expected-error {{OpenMP constructs may not be nested inside a simd region}} + ++a; + } +#pragma omp simd + for (int i = 0; i < 10; ++i) { #pragma omp teams // expected-error {{OpenMP constructs may not be nested inside a simd region}} ++a; } @@ -413,6 +423,11 @@ } #pragma omp for for (int i = 0; i < 10; ++i) { +#pragma omp target exit data map(from: a) + ++a; + } +#pragma omp for + for (int i = 0; i < 10; ++i) { #pragma omp teams // expected-error {{region cannot be closely nested inside 'for' region; perhaps you forget to enclose 'omp teams' directive into a target region?}} ++a; } @@ -557,6 +572,11 @@ } #pragma omp for simd for (int i = 0; i < 10; ++i) { +#pragma omp target exit data map(from: a) // expected-error {{OpenMP constructs may not be nested inside a simd region}} + ++a; + } +#pragma omp for simd + for (int i = 0; i < 10; ++i) { #pragma omp teams // expected-error {{OpenMP constructs may not be nested inside a simd region}} ++a; } @@ -730,6 +750,10 @@ } #pragma omp sections { +#pragma omp target exit data map(from: a) + } +#pragma omp sections + { #pragma omp teams // expected-error {{region cannot be closely nested inside 'sections' region; perhaps you forget to enclose 'omp teams' directive into a target region?}} ++a; } @@ -943,6 +967,14 @@ #pragma omp sections { #pragma omp section + { +#pragma omp target exit data map(from: a) + ++a; + } + } +#pragma omp sections + { +#pragma omp section #pragma omp teams // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp teams' directive into a target region?}} ++a; } @@ -1102,6 +1134,11 @@ } #pragma omp single { +#pragma omp target exit data map(from: a) + ++a; + } +#pragma omp single + { #pragma omp teams // expected-error {{region cannot be closely nested inside 'single' region; perhaps you forget to enclose 'omp teams' directive into a target region?}} ++a; } @@ -1259,6 +1296,11 @@ } #pragma omp master { +#pragma omp target exit data map(from: a) + ++a; + } +#pragma omp master + { #pragma omp teams // expected-error {{region cannot be closely nested inside 'master' region; perhaps you forget to enclose 'omp teams' directive into a target region?}} ++a; } @@ -1430,6 +1472,11 @@ } #pragma omp critical { +#pragma omp target exit data map(from: a) + ++a; + } +#pragma omp critical + { #pragma omp teams // expected-error {{region cannot be closely nested inside 'critical' region; perhaps you forget to enclose 'omp teams' directive into a target region?}} ++a; } @@ -1602,6 +1649,11 @@ } #pragma omp parallel for for (int i = 0; i < 10; ++i) { +#pragma omp target exit data map(from: a) + ++a; + } +#pragma omp parallel for + for (int i = 0; i < 10; ++i) { #pragma omp teams // expected-error {{region cannot be closely nested inside 'parallel for' region; perhaps you forget to enclose 'omp teams' directive into a target region?}} ++a; } @@ -1774,6 +1826,11 @@ } #pragma omp parallel for simd for (int i = 0; i < 10; ++i) { +#pragma omp target exit data map(from: a) // expected-error {{OpenMP constructs may not be nested inside a simd region}} + ++a; + } +#pragma omp parallel for simd + for (int i = 0; i < 10; ++i) { #pragma omp teams // expected-error {{OpenMP constructs may not be nested inside a simd region}} ++a; } @@ -1936,6 +1993,10 @@ } #pragma omp parallel sections { +#pragma omp target exit data map(from: a) + } +#pragma omp parallel sections + { #pragma omp teams // expected-error {{region cannot be closely nested inside 'parallel sections' region; perhaps you forget to enclose 'omp teams' directive into a target region?}} ++a; } @@ -2045,6 +2106,11 @@ } #pragma omp task { +#pragma omp target exit data map(from: a) + ++a; + } +#pragma omp task + { #pragma omp teams // expected-error {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp teams' directive into a target region?}} ++a; } @@ -2212,6 +2278,11 @@ } #pragma omp ordered { +#pragma omp target exit data map(from: a) + ++a; + } +#pragma omp ordered + { #pragma omp teams // expected-error {{region cannot be closely nested inside 'ordered' region; perhaps you forget to enclose 'omp teams' directive into a target region?}} ++a; } @@ -2400,6 +2471,13 @@ // 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 exit data map(from: a) // expected-error {{OpenMP constructs may not be nested inside an atomic region}} + ++a; + } +#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 teams // expected-error {{OpenMP constructs may not be nested inside an atomic region}} ++a; } @@ -2540,6 +2618,10 @@ { #pragma omp target enter data map(to: a) } +#pragma omp target + { +#pragma omp target exit data map(from: a) + } // TEAMS DIRECTIVE #pragma omp target @@ -2663,6 +2745,12 @@ #pragma omp target #pragma omp teams { +#pragma omp target exit data map(from: a) // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp target exit data' directive into a parallel region?}} + ++a; + } +#pragma omp target +#pragma omp teams + { #pragma omp teams // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp teams' directive into a target region?}} ++a; } @@ -2833,6 +2921,11 @@ } #pragma omp taskloop for (int i = 0; i < 10; ++i) { +#pragma omp target exit data map(from: a) + ++a; + } +#pragma omp taskloop + for (int i = 0; i < 10; ++i) { #pragma omp teams // expected-error {{region cannot be closely nested inside 'taskloop' region; perhaps you forget to enclose 'omp teams' directive into a target region?}} ++a; } @@ -3034,6 +3127,13 @@ #pragma omp teams #pragma omp distribute for (int i = 0; i < 10; ++i) { +#pragma omp target exit data map(from: a) + ++a; + } +#pragma omp target +#pragma omp teams +#pragma omp distribute + for (int i = 0; i < 10; ++i) { #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; } @@ -3138,6 +3238,11 @@ } #pragma omp parallel { +#pragma omp target exit data map(from: a) + ++a; + } +#pragma omp parallel + { #pragma omp teams // expected-error {{region cannot be closely nested inside 'parallel' region; perhaps you forget to enclose 'omp teams' directive into a target region?}} ++a; } @@ -3275,6 +3380,11 @@ } #pragma omp simd for (int i = 0; i < 10; ++i) { +#pragma omp target exit data map(from: a) // expected-error {{OpenMP constructs may not be nested inside a simd region}} + ++a; + } +#pragma omp simd + for (int i = 0; i < 10; ++i) { #pragma omp teams // expected-error {{OpenMP constructs may not be nested inside a simd region}} ++a; } @@ -3432,6 +3542,11 @@ } #pragma omp for for (int i = 0; i < 10; ++i) { +#pragma omp target exit data map(from: a) + ++a; + } +#pragma omp for + for (int i = 0; i < 10; ++i) { #pragma omp teams // expected-error {{region cannot be closely nested inside 'for' region; perhaps you forget to enclose 'omp teams' directive into a target region?}} ++a; } @@ -3569,6 +3684,11 @@ } #pragma omp for simd for (int i = 0; i < 10; ++i) { +#pragma omp target exit data map(from: a) // expected-error {{OpenMP constructs may not be nested inside a simd region}} + ++a; + } +#pragma omp for simd + for (int i = 0; i < 10; ++i) { #pragma omp teams // expected-error {{OpenMP constructs may not be nested inside a simd region}} ++a; } @@ -3717,6 +3837,10 @@ } #pragma omp sections { +#pragma omp target exit data map(from: a) + } +#pragma omp sections + { #pragma omp teams // expected-error {{region cannot be closely nested inside 'sections' region; perhaps you forget to enclose 'omp teams' directive into a target region?}} ++a; } @@ -3935,6 +4059,14 @@ { #pragma omp section { +#pragma omp target exit data map(from: a) + ++a; + } + } +#pragma omp sections + { +#pragma omp section + { #pragma omp teams // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp teams' directive into a target region?}} ++a; } @@ -4087,6 +4219,11 @@ } #pragma omp single { +#pragma omp target exit data map(from: a) + ++a; + } +#pragma omp single + { #pragma omp teams // expected-error {{region cannot be closely nested inside 'single' region; perhaps you forget to enclose 'omp teams' directive into a target region?}} ++a; } @@ -4244,6 +4381,11 @@ } #pragma omp master { +#pragma omp target exit data map(from: a) + ++a; + } +#pragma omp master + { #pragma omp teams // expected-error {{region cannot be closely nested inside 'master' region; perhaps you forget to enclose 'omp teams' directive into a target region?}} ++a; } @@ -4420,6 +4562,11 @@ } #pragma omp critical { +#pragma omp target exit data map(from: a) + ++a; + } +#pragma omp critical + { #pragma omp teams // expected-error {{region cannot be closely nested inside 'critical' region; perhaps you forget to enclose 'omp teams' directive into a target region?}} ++a; } @@ -4592,6 +4739,11 @@ } #pragma omp parallel for for (int i = 0; i < 10; ++i) { +#pragma omp target exit data map(from: a) + ++a; + } +#pragma omp parallel for + for (int i = 0; i < 10; ++i) { #pragma omp teams // expected-error {{region cannot be closely nested inside 'parallel for' region; perhaps you forget to enclose 'omp teams' directive into a target region?}} ++a; } @@ -4764,6 +4916,11 @@ } #pragma omp parallel for simd for (int i = 0; i < 10; ++i) { +#pragma omp target exit data map(from: a) // expected-error {{OpenMP constructs may not be nested inside a simd region}} + ++a; + } +#pragma omp parallel for simd + for (int i = 0; i < 10; ++i) { #pragma omp teams // expected-error {{OpenMP constructs may not be nested inside a simd region}} ++a; } @@ -4922,6 +5079,10 @@ } #pragma omp parallel sections { +#pragma omp target exit data map(from: a) + } +#pragma omp parallel sections + { #pragma omp teams // expected-error {{region cannot be closely nested inside 'parallel sections' region; perhaps you forget to enclose 'omp teams' directive into a target region?}} ++a; } @@ -5030,6 +5191,11 @@ } #pragma omp task { +#pragma omp target exit data map(from: a) + ++a; + } +#pragma omp task + { #pragma omp teams // expected-error {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp teams' directive into a target region?}} ++a; } @@ -5218,6 +5384,13 @@ // 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 exit data map(from: a) // expected-error {{OpenMP constructs may not be nested inside an atomic region}} + ++a; + } +#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 teams // expected-error {{OpenMP constructs may not be nested inside an atomic region}} ++a; } @@ -5337,6 +5510,10 @@ } #pragma omp target { +#pragma omp target exit data map(from: a) + } +#pragma omp target + { #pragma omp teams ++a; } @@ -5480,6 +5657,11 @@ #pragma omp target #pragma omp teams { +#pragma omp target exit data map(from: a) // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp target exit data' directive into a parallel region?}} + } +#pragma omp target +#pragma omp teams + { #pragma omp teams // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp teams' directive into a target region?}} ++a; } @@ -5650,6 +5832,11 @@ } #pragma omp taskloop for (int i = 0; i < 10; ++i) { +#pragma omp target exit data map(from: a) + ++a; + } +#pragma omp taskloop + for (int i = 0; i < 10; ++i) { #pragma omp teams // expected-error {{region cannot be closely nested inside 'taskloop' region; perhaps you forget to enclose 'omp teams' directive into a target region?}} ++a; } @@ -5856,4 +6043,11 @@ #pragma omp target enter data map(to: a) ++a; } +#pragma omp target +#pragma omp teams +#pragma omp distribute + for (int i = 0; i < 10; ++i) { +#pragma omp target exit data map(from: a) + ++a; + } } Index: test/OpenMP/target_exit_data_ast_print.cpp =================================================================== --- /dev/null +++ test/OpenMP/target_exit_data_ast_print.cpp @@ -0,0 +1,100 @@ +// 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 + +template +T tmain(T argc, T *argv) { + T i, j, b, c, d, e, x[20]; + + i = argc; +#pragma omp target exit data map(from: i) + +#pragma omp target exit data map(from: i) if (target exit data: j > 0) + +#pragma omp target exit data map(from: i) if (b) + +#pragma omp target exit data map(from: c) + +#pragma omp target exit data map(from: c) if(b>e) + +#pragma omp target exit data map(release: x[0:10], c) + +#pragma omp target exit data map(from: c) map(release: d) + +#pragma omp target exit data map(always,release: e) + + return 0; +} + +// CHECK: template int tmain(int argc, int *argv) { +// CHECK-NEXT: int i, j, b, c, d, e, x[20]; +// CHECK-NEXT: i = argc; +// CHECK-NEXT: #pragma omp target exit data map(from: i) +// CHECK-NEXT: #pragma omp target exit data map(from: i) if(target exit data: j > 0) +// CHECK-NEXT: #pragma omp target exit data map(from: i) if(b) +// CHECK-NEXT: #pragma omp target exit data map(from: c) +// CHECK-NEXT: #pragma omp target exit data map(from: c) if(b > e) +// CHECK-NEXT: #pragma omp target exit data map(release: x[0:10],c) +// CHECK-NEXT: #pragma omp target exit data map(from: c) map(release: d) +// CHECK-NEXT: #pragma omp target exit data map(always,release: e) +// CHECK: template char tmain(char argc, char *argv) { +// CHECK-NEXT: char i, j, b, c, d, e, x[20]; +// CHECK-NEXT: i = argc; +// CHECK-NEXT: #pragma omp target exit data map(from: i) +// CHECK-NEXT: #pragma omp target exit data map(from: i) if(target exit data: j > 0) +// CHECK-NEXT: #pragma omp target exit data map(from: i) if(b) +// CHECK-NEXT: #pragma omp target exit data map(from: c) +// CHECK-NEXT: #pragma omp target exit data map(from: c) if(b > e) +// CHECK-NEXT: #pragma omp target exit data map(release: x[0:10],c) +// CHECK-NEXT: #pragma omp target exit data map(from: c) map(release: d) +// CHECK-NEXT: #pragma omp target exit data map(always,release: e) +// CHECK: template T tmain(T argc, T *argv) { +// CHECK-NEXT: T i, j, b, c, d, e, x[20]; +// CHECK-NEXT: i = argc; +// CHECK-NEXT: #pragma omp target exit data map(from: i) +// CHECK-NEXT: #pragma omp target exit data map(from: i) if(target exit data: j > 0) +// CHECK-NEXT: #pragma omp target exit data map(from: i) if(b) +// CHECK-NEXT: #pragma omp target exit data map(from: c) +// CHECK-NEXT: #pragma omp target exit data map(from: c) if(b > e) +// CHECK-NEXT: #pragma omp target exit data map(release: x[0:10],c) +// CHECK-NEXT: #pragma omp target exit data map(from: c) map(release: d) +// CHECK-NEXT: #pragma omp target exit data map(always,release: e) + +int main (int argc, char **argv) { + int b = argc, c, d, e, f, g, x[20]; + static int a; +// CHECK: static int a; + +#pragma omp target exit data map(from: a) +// CHECK: #pragma omp target exit data map(from: a) + a=2; +// CHECK-NEXT: a = 2; +#pragma omp target exit data map(from: a) if (target exit data: b) +// CHECK: #pragma omp target exit data map(from: a) if(target exit data: b) + +#pragma omp target exit data map(from: a) if (b > g) +// CHECK: #pragma omp target exit data map(from: a) if(b > g) + +#pragma omp target exit data map(from: c) +// CHECK-NEXT: #pragma omp target exit data map(from: c) + +#pragma omp target exit data map(release: c) if(b>g) +// CHECK-NEXT: #pragma omp target exit data map(release: c) if(b > g) + +#pragma omp target exit data map(from: x[0:10], c) +// CHECK-NEXT: #pragma omp target exit data map(from: x[0:10],c) + +#pragma omp target exit data map(from: c) map(release: d) +// CHECK-NEXT: #pragma omp target exit data map(from: c) map(release: d) + +#pragma omp target exit data map(always,release: e) +// CHECK-NEXT: #pragma omp target exit data map(always,release: e) + + return tmain(argc, &argc) + tmain(argv[0][0], argv[0]); +} + +#endif Index: test/OpenMP/target_exit_data_device_messages.cpp =================================================================== --- /dev/null +++ test/OpenMP/target_exit_data_device_messages.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s + +void foo() { +} + +bool foobool(int argc) { + return argc; +} + +struct S1; // expected-note {{declared here}} + +int main(int argc, char **argv) { + int i; + #pragma omp target exit data map(from: i) device // expected-error {{expected '(' after 'device'}} + #pragma omp target exit data map(from: i) device ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + #pragma omp target exit data map(from: i) device () // expected-error {{expected expression}} + #pragma omp target exit data map(from: i) device (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + #pragma omp target exit data map(from: i) device (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target exit data' are ignored}} +#pragma omp target exit data map(from: i) device (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} + #pragma omp target exit data map(from: i) device (argc + argc) + #pragma omp target exit data map(from: i) device (argc), device (argc+1) // expected-error {{directive '#pragma omp target exit data' cannot contain more than one 'device' clause}} + #pragma omp target exit data map(from: i) device (S1) // expected-error {{'S1' does not refer to a value}} + #pragma omp target exit data map(from: i) device (-2) // expected-error {{argument to 'device' clause must be a non-negative integer value}} + #pragma omp target exit data map(from: i) device (-10u) + #pragma omp target exit data map(from: i) device (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}} + foo(); + + return 0; +} Index: test/OpenMP/target_exit_data_if_messages.cpp =================================================================== --- /dev/null +++ test/OpenMP/target_exit_data_if_messages.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s + +void foo() { +} + +bool foobool(int argc) { + return argc; +} + +struct S1; // expected-note {{declared here}} + +int main(int argc, char **argv) { + int i; + #pragma omp target exit data map(from: i) if // expected-error {{expected '(' after 'if'}} + #pragma omp target exit data map(from: i) if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + #pragma omp target exit data map(from: i) if () // expected-error {{expected expression}} + #pragma omp target exit data map(from: i) if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + #pragma omp target exit data map(from: i) if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target exit data' are ignored}} + #pragma omp target exit data map(from: i) if (argc > 0 ? argv[1] : argv[2]) + #pragma omp target exit data map(from: i) if (argc + argc) + #pragma omp target exit data map(from: i) if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp target exit data' cannot contain more than one 'if' clause}} + #pragma omp target exit data map(from: i) if (S1) // expected-error {{'S1' does not refer to a value}} + #pragma omp target exit data map(from: i) if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} + #pragma omp target exit data map(from: i) if(target data : true) // expected-error {{directive name modifier 'target data' is not allowed for '#pragma omp target exit data'}} + #pragma omp target exit data map(from: i) if(target exit data : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + #pragma omp target exit data map(from: i) if(target exit data : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + #pragma omp target exit data map(from: i) if(target exit data : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + #pragma omp target exit data map(from: i) if(target exit data : argc) + #pragma omp target exit data map(from: i) if(target exit data : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp target exit data'}} + #pragma omp target exit data map(from: i) if(target exit data : argc) if (target exit data:argc) // expected-error {{directive '#pragma omp target exit data' cannot contain more than one 'if' clause with 'target exit data' name modifier}} + #pragma omp target exit data map(from: i) if(target exit data : argc) if (argc) // expected-error {{no more 'if' clause is allowed}} expected-note {{previous clause with directive name modifier specified here}} + foo(); + + return 0; +} Index: test/OpenMP/target_exit_data_map_messages.c =================================================================== --- /dev/null +++ test/OpenMP/target_exit_data_map_messages.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s + +int main(int argc, char **argv) { + + int r; + #pragma omp target exit data // expected-error {{expected at least one map clause for '#pragma omp target exit data'}} + + #pragma omp target exit data map(tofrom: r) // expected-error {{map type 'tofrom' is not allowed for '#pragma omp target exit data'}} + + #pragma omp target exit data map(always, from: r) + #pragma omp target exit data map(delete: r) + #pragma omp target exit data map(release: r) + #pragma omp target exit data map(always, alloc: r) // expected-error {{map type 'alloc' is not allowed for '#pragma omp target exit data'}} + #pragma omp target exit data map(to: r) // expected-error {{map type 'to' is not allowed for '#pragma omp target exit data'}} + + return 0; +} Index: tools/libclang/CIndex.cpp =================================================================== --- tools/libclang/CIndex.cpp +++ tools/libclang/CIndex.cpp @@ -1954,6 +1954,7 @@ void VisitOMPTargetDirective(const OMPTargetDirective *D); void VisitOMPTargetDataDirective(const OMPTargetDataDirective *D); void VisitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective *D); + void VisitOMPTargetExitDataDirective(const OMPTargetExitDataDirective *D); void VisitOMPTeamsDirective(const OMPTeamsDirective *D); void VisitOMPTaskLoopDirective(const OMPTaskLoopDirective *D); void VisitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective *D); @@ -2634,6 +2635,11 @@ VisitOMPExecutableDirective(D); } +void EnqueueVisitor::VisitOMPTargetExitDataDirective( + const OMPTargetExitDataDirective *D) { + VisitOMPExecutableDirective(D); +} + void EnqueueVisitor::VisitOMPTeamsDirective(const OMPTeamsDirective *D) { VisitOMPExecutableDirective(D); } @@ -4518,6 +4524,8 @@ return cxstring::createRef("OMPTargetDataDirective"); case CXCursor_OMPTargetEnterDataDirective: return cxstring::createRef("OMPTargetEnterDataDirective"); + case CXCursor_OMPTargetExitDataDirective: + return cxstring::createRef("OMPTargetExitDataDirective"); case CXCursor_OMPTeamsDirective: return cxstring::createRef("OMPTeamsDirective"); case CXCursor_OMPCancellationPointDirective: Index: tools/libclang/CXCursor.cpp =================================================================== --- tools/libclang/CXCursor.cpp +++ tools/libclang/CXCursor.cpp @@ -603,6 +603,9 @@ case Stmt::OMPTargetEnterDataDirectiveClass: K = CXCursor_OMPTargetEnterDataDirective; break; + case Stmt::OMPTargetExitDataDirectiveClass: + K = CXCursor_OMPTargetExitDataDirective; + break; case Stmt::OMPTeamsDirectiveClass: K = CXCursor_OMPTeamsDirective; break;