From: Alexey Bataev Date: Fri, 19 Sep 2014 08:19:49 +0000 (+0000) Subject: [OPENMP] Initial parsing/sema analysis of 'target' directive. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bd7dfd35d37f85eb22f6224e2b02c9e59358d691;p=clang [OPENMP] Initial parsing/sema analysis of 'target' directive. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@218110 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index a86171aaba..3f7f13cb06 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -2213,7 +2213,11 @@ enum CXCursorKind { */ CXCursor_OMPForSimdDirective = 250, - CXCursor_LastStmt = CXCursor_OMPForSimdDirective, + /** \brief OpenMP target directive. + */ + CXCursor_OMPTargetDirective = 251, + + CXCursor_LastStmt = CXCursor_OMPTargetDirective, /** * \brief Cursor that represents the translation unit itself. diff --git a/include/clang/AST/DataRecursiveASTVisitor.h b/include/clang/AST/DataRecursiveASTVisitor.h index 0612231e91..b06fb25525 100644 --- a/include/clang/AST/DataRecursiveASTVisitor.h +++ b/include/clang/AST/DataRecursiveASTVisitor.h @@ -2342,6 +2342,9 @@ DEF_TRAVERSE_STMT(OMPOrderedDirective, DEF_TRAVERSE_STMT(OMPAtomicDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPTargetDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + // OpenMP clauses. template bool RecursiveASTVisitor::TraverseOMPClause(OMPClause *C) { diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 19c01e0212..cf2b4156a3 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -2364,6 +2364,9 @@ DEF_TRAVERSE_STMT(OMPOrderedDirective, DEF_TRAVERSE_STMT(OMPAtomicDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPTargetDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + // OpenMP clauses. template bool RecursiveASTVisitor::TraverseOMPClause(OMPClause *C) { diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h index 54df0eaf47..cbb8735506 100644 --- a/include/clang/AST/StmtOpenMP.h +++ b/include/clang/AST/StmtOpenMP.h @@ -1215,6 +1215,63 @@ public: } }; +/// \brief This represents '#pragma omp target' directive. +/// +/// \code +/// #pragma omp target if(a) +/// \endcode +/// In this example directive '#pragma omp target' has clause 'if' with +/// condition 'a'. +/// +class OMPTargetDirective : 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 Number of clauses. + /// + OMPTargetDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPTargetDirectiveClass, OMPD_target, + StartLoc, EndLoc, NumClauses, 1) {} + + /// \brief Build an empty directive. + /// + /// \param NumClauses Number of clauses. + /// + explicit OMPTargetDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPTargetDirectiveClass, OMPD_target, + SourceLocation(), SourceLocation(), NumClauses, + 1) {} + +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 OMPTargetDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef Clauses, Stmt *AssociatedStmt); + + /// \brief Creates an empty directive with the place for \a NumClauses + /// clauses. + /// + /// \param C AST context. + /// \param NumClauses Number of clauses. + /// + static OMPTargetDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTargetDirectiveClass; + } +}; + } // end namespace clang #endif diff --git a/include/clang/Basic/OpenMPKinds.def b/include/clang/Basic/OpenMPKinds.def index cda95abc9e..2c31307119 100644 --- a/include/clang/Basic/OpenMPKinds.def +++ b/include/clang/Basic/OpenMPKinds.def @@ -51,6 +51,9 @@ #ifndef OPENMP_ATOMIC_CLAUSE # define OPENMP_ATOMIC_CLAUSE(Name) #endif +#ifndef OPENMP_TARGET_CLAUSE +# define OPENMP_TARGET_CLAUSE(Name) +#endif #ifndef OPENMP_DEFAULT_KIND # define OPENMP_DEFAULT_KIND(Name) #endif @@ -78,6 +81,7 @@ OPENMP_DIRECTIVE(taskwait) OPENMP_DIRECTIVE(flush) OPENMP_DIRECTIVE(ordered) OPENMP_DIRECTIVE(atomic) +OPENMP_DIRECTIVE(target) OPENMP_DIRECTIVE_EXT(parallel_for, "parallel for") OPENMP_DIRECTIVE_EXT(parallel_sections, "parallel sections") OPENMP_DIRECTIVE_EXT(for_simd, "for simd") @@ -226,6 +230,10 @@ OPENMP_ATOMIC_CLAUSE(update) OPENMP_ATOMIC_CLAUSE(capture) OPENMP_ATOMIC_CLAUSE(seq_cst) +// Clauses allowed for OpenMP directive 'target'. +// TODO More clauses for 'target' directive. +OPENMP_TARGET_CLAUSE(if) + #undef OPENMP_SCHEDULE_KIND #undef OPENMP_PROC_BIND_KIND #undef OPENMP_DEFAULT_KIND @@ -239,6 +247,7 @@ OPENMP_ATOMIC_CLAUSE(seq_cst) #undef OPENMP_PARALLEL_SECTIONS_CLAUSE #undef OPENMP_TASK_CLAUSE #undef OPENMP_ATOMIC_CLAUSE +#undef OPENMP_TARGET_CLAUSE #undef OPENMP_SIMD_CLAUSE #undef OPENMP_FOR_CLAUSE #undef OPENMP_FOR_SIMD_CLAUSE diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td index c967d3ff47..81c113e6bf 100644 --- a/include/clang/Basic/StmtNodes.td +++ b/include/clang/Basic/StmtNodes.td @@ -197,3 +197,4 @@ def OMPTaskwaitDirective : DStmt; def OMPFlushDirective : DStmt; def OMPOrderedDirective : DStmt; def OMPAtomicDirective : DStmt; +def OMPTargetDirective : DStmt; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index b262c45cd7..0e5ed350a7 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -7466,6 +7466,12 @@ public: Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc); + /// \brief Called on well-formed '\#pragma omp target' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPTargetDirective(ArrayRef Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index d209bcc876..0e13a910f6 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -1358,6 +1358,7 @@ namespace clang { STMT_OMP_FLUSH_DIRECTIVE, STMT_OMP_ORDERED_DIRECTIVE, STMT_OMP_ATOMIC_DIRECTIVE, + STMT_OMP_TARGET_DIRECTIVE, // ARC EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index e966ee83bb..f2efca8664 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -1788,3 +1788,29 @@ OMPAtomicDirective *OMPAtomicDirective::CreateEmpty(const ASTContext &C, return new (Mem) OMPAtomicDirective(NumClauses); } +OMPTargetDirective *OMPTargetDirective::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef Clauses, + Stmt *AssociatedStmt) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTargetDirective), + llvm::alignOf()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); + OMPTargetDirective *Dir = + new (Mem) OMPTargetDirective(StartLoc, EndLoc, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPTargetDirective *OMPTargetDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTargetDirective), + llvm::alignOf()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); + return new (Mem) OMPTargetDirective(NumClauses); +} + diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 50715e68c2..d065c62fea 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -917,6 +917,11 @@ void StmtPrinter::VisitOMPAtomicDirective(OMPAtomicDirective *Node) { PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPTargetDirective(OMPTargetDirective *Node) { + Indent() << "#pragma omp target "; + PrintOMPExecutableDirective(Node); +} + //===----------------------------------------------------------------------===// // Expr printing methods. //===----------------------------------------------------------------------===// diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 9d2d69fa28..cc61fae276 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -457,6 +457,10 @@ void StmtProfiler::VisitOMPAtomicDirective(const OMPAtomicDirective *S) { VisitOMPExecutableDirective(S); } +void StmtProfiler::VisitOMPTargetDirective(const OMPTargetDirective *S) { + VisitOMPExecutableDirective(S); +} + void StmtProfiler::VisitExpr(const Expr *S) { VisitStmt(S); } diff --git a/lib/Basic/OpenMPKinds.cpp b/lib/Basic/OpenMPKinds.cpp index b0043d5e48..7394d0bbb1 100644 --- a/lib/Basic/OpenMPKinds.cpp +++ b/lib/Basic/OpenMPKinds.cpp @@ -289,6 +289,16 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, #define OPENMP_ATOMIC_CLAUSE(Name) \ case OMPC_##Name: \ return true; +#include "clang/Basic/OpenMPKinds.def" + default: + break; + } + break; + case OMPD_target: + switch (CKind) { +#define OPENMP_TARGET_CLAUSE(Name) \ + case OMPC_##Name: \ + return true; #include "clang/Basic/OpenMPKinds.def" default: break; diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 560ce608be..7be6759df4 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -230,6 +230,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { case Stmt::OMPAtomicDirectiveClass: EmitOMPAtomicDirective(cast(*S)); break; + case Stmt::OMPTargetDirectiveClass: + EmitOMPTargetDirective(cast(*S)); + break; } } diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp index 3597dddd99..74b73a5560 100644 --- a/lib/CodeGen/CGStmtOpenMP.cpp +++ b/lib/CodeGen/CGStmtOpenMP.cpp @@ -140,3 +140,7 @@ void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &) { llvm_unreachable("CodeGen for 'omp atomic' is not supported yet."); } +void CodeGenFunction::EmitOMPTargetDirective(const OMPTargetDirective &) { + llvm_unreachable("CodeGen for 'omp target' is not supported yet."); +} + diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index eebdbf34a8..4e89725a60 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1943,6 +1943,7 @@ public: void EmitOMPFlushDirective(const OMPFlushDirective &S); void EmitOMPOrderedDirective(const OMPOrderedDirective &S); void EmitOMPAtomicDirective(const OMPAtomicDirective &S); + void EmitOMPTargetDirective(const OMPTargetDirective &S); //===--------------------------------------------------------------------===// // LValue Expression Emission diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp index dd776773f4..45f6da0d05 100644 --- a/lib/Parse/ParseOpenMP.cpp +++ b/lib/Parse/ParseOpenMP.cpp @@ -105,6 +105,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { case OMPD_parallel_for: case OMPD_parallel_sections: case OMPD_atomic: + case OMPD_target: Diag(Tok, diag::err_omp_unexpected_directive) << getOpenMPDirectiveName(DKind); break; @@ -124,7 +125,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { /// 'section' | 'single' | 'master' | 'critical' [ '(' ')' ] | /// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' | /// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' | -/// 'for simd' {clause} +/// 'for simd' | 'target' {clause} /// annot_pragma_openmp_end /// StmtResult @@ -191,7 +192,8 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { case OMPD_parallel_sections: case OMPD_task: case OMPD_ordered: - case OMPD_atomic: { + case OMPD_atomic: + case OMPD_target: { ConsumeToken(); // Parse directive name of the 'critical' directive if any. if (DKind == OMPD_critical) { diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index 5c78804239..30d873efcc 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -1132,6 +1132,14 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { Params); break; } + case OMPD_target: { + Sema::CapturedParamNameType Params[] = { + std::make_pair(StringRef(), QualType()) // __context with shared vars + }; + ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, + Params); + break; + } case OMPD_threadprivate: llvm_unreachable("OpenMP Directive is not allowed"); case OMPD_unknown: @@ -1165,6 +1173,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel | flush | * | // | parallel | ordered | + | // | parallel | atomic | * | + // | parallel | target | * | // +------------------+-----------------+------------------------------------+ // | for | parallel | * | // | for | for | + | @@ -1184,6 +1193,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | for | flush | * | // | for | ordered | * (if construct is ordered) | // | for | atomic | * | + // | for | target | * | // +------------------+-----------------+------------------------------------+ // | master | parallel | * | // | master | for | + | @@ -1203,6 +1213,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | master | flush | * | // | master | ordered | + | // | master | atomic | * | + // | master | target | * | // +------------------+-----------------+------------------------------------+ // | critical | parallel | * | // | critical | for | + | @@ -1221,6 +1232,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | critical | taskwait | * | // | critical | ordered | + | // | critical | atomic | * | + // | critical | target | * | // +------------------+-----------------+------------------------------------+ // | simd | parallel | | // | simd | for | | @@ -1240,6 +1252,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | simd | flush | | // | simd | ordered | | // | simd | atomic | | + // | simd | target | | // +------------------+-----------------+------------------------------------+ // | for simd | parallel | | // | for simd | for | | @@ -1259,6 +1272,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | for simd | flush | | // | for simd | ordered | | // | for simd | atomic | | + // | for simd | target | | // +------------------+-----------------+------------------------------------+ // | sections | parallel | * | // | sections | for | + | @@ -1278,6 +1292,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | sections | flush | * | // | sections | ordered | + | // | sections | atomic | * | + // | sections | target | * | // +------------------+-----------------+------------------------------------+ // | section | parallel | * | // | section | for | + | @@ -1297,6 +1312,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | section | flush | * | // | section | ordered | + | // | section | atomic | * | + // | section | target | * | // +------------------+-----------------+------------------------------------+ // | single | parallel | * | // | single | for | + | @@ -1316,6 +1332,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | single | flush | * | // | single | ordered | + | // | single | atomic | * | + // | single | target | * | // +------------------+-----------------+------------------------------------+ // | parallel for | parallel | * | // | parallel for | for | + | @@ -1335,6 +1352,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel for | flush | * | // | parallel for | ordered | * (if construct is ordered) | // | parallel for | atomic | * | + // | parallel for | target | * | // +------------------+-----------------+------------------------------------+ // | parallel sections| parallel | * | // | parallel sections| for | + | @@ -1354,6 +1372,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel sections| flush | * | // | parallel sections| ordered | + | // | parallel sections| atomic | * | + // | parallel sections| target | * | // +------------------+-----------------+------------------------------------+ // | task | parallel | * | // | task | for | + | @@ -1373,6 +1392,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | task | flush | * | // | task | ordered | + | // | task | atomic | * | + // | task | target | * | // +------------------+-----------------+------------------------------------+ // | ordered | parallel | * | // | ordered | for | + | @@ -1392,6 +1412,47 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | ordered | flush | * | // | ordered | ordered | + | // | ordered | atomic | * | + // | ordered | target | * | + // +------------------+-----------------+------------------------------------+ + // | atomic | parallel | | + // | atomic | for | | + // | atomic | for simd | | + // | atomic | master | | + // | atomic | critical | | + // | atomic | simd | | + // | atomic | sections | | + // | atomic | section | | + // | atomic | single | | + // | atomic | parallel for | | + // | atomic |parallel sections| | + // | atomic | task | | + // | atomic | taskyield | | + // | atomic | barrier | | + // | atomic | taskwait | | + // | atomic | flush | | + // | atomic | ordered | | + // | atomic | atomic | | + // | atomic | target | | + // +------------------+-----------------+------------------------------------+ + // | target | parallel | * | + // | target | for | * | + // | target | for simd | * | + // | target | master | * | + // | target | critical | * | + // | target | simd | * | + // | target | sections | * | + // | target | section | * | + // | target | single | * | + // | target | parallel for | * | + // | target |parallel sections| * | + // | target | task | * | + // | target | taskyield | * | + // | target | barrier | * | + // | target | taskwait | * | + // | target | flush | * | + // | target | ordered | * | + // | target | atomic | * | + // | target | target | * | // +------------------+-----------------+------------------------------------+ if (Stack->getCurScope()) { auto ParentRegion = Stack->getParentDirective(); @@ -1630,6 +1691,10 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); break; + case OMPD_target: + Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc, + EndLoc); + break; case OMPD_threadprivate: llvm_unreachable("OpenMP Directive is not allowed"); case OMPD_unknown: @@ -2512,6 +2577,17 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef Clauses, return OMPAtomicDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt); } +StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef Clauses, + Stmt *AStmt, + SourceLocation StartLoc, + SourceLocation EndLoc) { + assert(AStmt && isa(AStmt) && "Captured statement expected"); + + getCurFunction()->setHasBranchProtectedScope(); + + return OMPTargetDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt); +} + OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 92baa0ebd2..9dfa8b73e0 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -6663,6 +6663,17 @@ TreeTransform::TransformOMPAtomicDirective(OMPAtomicDirective *D) { return Res; } +template +StmtResult +TreeTransform::TransformOMPTargetDirective(OMPTargetDirective *D) { + DeclarationNameInfo DirName; + getDerived().getSema().StartOpenMPDSABlock(OMPD_target, DirName, nullptr, + D->getLocStart()); + StmtResult Res = getDerived().TransformOMPExecutableDirective(D); + getDerived().getSema().EndOpenMPDSABlock(Res.get()); + return Res; +} + //===----------------------------------------------------------------------===// // OpenMP clause transformation //===----------------------------------------------------------------------===// diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index eefdcdf04c..ff7a53e22f 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -2072,6 +2072,13 @@ void ASTStmtReader::VisitOMPAtomicDirective(OMPAtomicDirective *D) { VisitOMPExecutableDirective(D); } +void ASTStmtReader::VisitOMPTargetDirective(OMPTargetDirective *D) { + VisitStmt(D); + // The NumClauses field was read in ReadStmtFromStream. + ++Idx; + VisitOMPExecutableDirective(D); +} + //===----------------------------------------------------------------------===// // ASTReader Implementation //===----------------------------------------------------------------------===// @@ -2644,6 +2651,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { Context, Record[ASTStmtReader::NumStmtFields], Empty); break; + case STMT_OMP_TARGET_DIRECTIVE: + S = OMPTargetDirective::CreateEmpty( + Context, Record[ASTStmtReader::NumStmtFields], Empty); + break; + case EXPR_CXX_OPERATOR_CALL: S = new (Context) CXXOperatorCallExpr(Context, Empty); break; diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 9873eda75f..759f7f3ade 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -1931,6 +1931,13 @@ void ASTStmtWriter::VisitOMPAtomicDirective(OMPAtomicDirective *D) { Code = serialization::STMT_OMP_ATOMIC_DIRECTIVE; } +void ASTStmtWriter::VisitOMPTargetDirective(OMPTargetDirective *D) { + VisitStmt(D); + Record.push_back(D->getNumClauses()); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_TARGET_DIRECTIVE; +} + void ASTStmtWriter::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *D) { VisitStmt(D); VisitOMPExecutableDirective(D); diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index a80b2de70d..f85b004f08 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -816,6 +816,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::OMPFlushDirectiveClass: case Stmt::OMPOrderedDirectiveClass: case Stmt::OMPAtomicDirectiveClass: + case Stmt::OMPTargetDirectiveClass: llvm_unreachable("Stmt should not be in analyzer evaluation loop"); case Stmt::ObjCSubscriptRefExprClass: diff --git a/test/OpenMP/nesting_of_regions.cpp b/test/OpenMP/nesting_of_regions.cpp index eac2db215a..203026b2f7 100644 --- a/test/OpenMP/nesting_of_regions.cpp +++ b/test/OpenMP/nesting_of_regions.cpp @@ -86,6 +86,11 @@ void foo() { #pragma omp atomic ++a; } +#pragma omp parallel + { +#pragma omp target + ++a; + } // SIMD DIRECTIVE #pragma omp simd @@ -197,6 +202,11 @@ void foo() { #pragma omp atomic // 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 target // expected-error {{OpenMP constructs may not be nested inside a simd region}} + ++a; + } // FOR DIRECTIVE #pragma omp for @@ -331,6 +341,11 @@ void foo() { #pragma omp atomic ++a; } +#pragma omp for + for (int i = 0; i < 10; ++i) { +#pragma omp target + ++a; + } // FOR SIMD DIRECTIVE #pragma omp for simd @@ -442,6 +457,11 @@ void foo() { #pragma omp atomic // 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 target // expected-error {{OpenMP constructs may not be nested inside a simd region}} + ++a; + } // SECTIONS DIRECTIVE #pragma omp sections @@ -583,6 +603,11 @@ void foo() { #pragma omp atomic ++a; } +#pragma omp sections + { +#pragma omp target + ++a; + } // SECTION DIRECTIVE #pragma omp section // expected-error {{orphaned 'omp section' directives are prohibited, it must be closely nested to a sections region}} @@ -755,6 +780,12 @@ void foo() { #pragma omp atomic ++a; } +#pragma omp sections + { +#pragma omp section +#pragma omp target + ++a; + } // SINGLE DIRECTIVE #pragma omp single @@ -879,6 +910,11 @@ void foo() { #pragma omp atomic ++a; } +#pragma omp single + { +#pragma omp target + ++a; + } // MASTER DIRECTIVE #pragma omp master @@ -1003,6 +1039,11 @@ void foo() { #pragma omp atomic ++a; } +#pragma omp master + { +#pragma omp target + ++a; + } // CRITICAL DIRECTIVE #pragma omp critical @@ -1141,6 +1182,11 @@ void foo() { #pragma omp atomic ++a; } +#pragma omp critical + { +#pragma omp target + ++a; + } // PARALLEL FOR DIRECTIVE #pragma omp parallel for @@ -1280,6 +1326,11 @@ void foo() { #pragma omp atomic ++a; } +#pragma omp parallel for + for (int i = 0; i < 10; ++i) { +#pragma omp target + ++a; + } // PARALLEL SECTIONS DIRECTIVE #pragma omp parallel sections @@ -1410,6 +1461,11 @@ void foo() { #pragma omp atomic ++a; } +#pragma omp parallel sections + { +#pragma omp target + ++a; + } // TASK DIRECTIVE #pragma omp task @@ -1488,6 +1544,11 @@ void foo() { #pragma omp atomic ++a; } +#pragma omp task + { +#pragma omp target + ++a; + } // ORDERED DIRECTIVE #pragma omp ordered @@ -1602,38 +1663,43 @@ void foo() { #pragma omp atomic ++a; } +#pragma omp ordered + { +#pragma omp target + ++a; + } // ATOMIC DIRECTIVE #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp for // expected-error {{OpenMP constructs may not be nested inside an atomic region}} for (int i = 0; i < 10; ++i) ; } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp simd // expected-error {{OpenMP constructs may not be nested inside an atomic region}} for (int i = 0; i < 10; ++i) ; } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp for simd // expected-error {{OpenMP constructs may not be nested inside an atomic region}} for (int i = 0; i < 10; ++i) ; } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp parallel // expected-error {{OpenMP constructs may not be nested inside an atomic region}} for (int i = 0; i < 10; ++i) ; } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp sections // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -1641,7 +1707,7 @@ void foo() { } } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp section // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -1649,7 +1715,7 @@ void foo() { } } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp single // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -1657,7 +1723,7 @@ void foo() { } } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp master // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -1665,7 +1731,7 @@ void foo() { } } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp critical // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -1673,14 +1739,14 @@ void foo() { } } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp parallel for // expected-error {{OpenMP constructs may not be nested inside an atomic region}} for (int i = 0; i < 10; ++i) ; } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp parallel sections // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -1688,7 +1754,7 @@ void foo() { } } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp task // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -1696,41 +1762,137 @@ void foo() { } } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp taskyield // expected-error {{OpenMP constructs may not be nested inside an atomic region}} bar(); } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp barrier // expected-error {{OpenMP constructs may not be nested inside an atomic region}} bar(); } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside an atomic region}} bar(); } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp flush // expected-error {{OpenMP constructs may not be nested inside an atomic region}} bar(); } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp ordered // expected-error {{OpenMP constructs may not be nested inside an atomic region}} bar(); } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp atomic // expected-error {{OpenMP constructs may not be nested inside an atomic region}} ++a; } +#pragma omp atomic + // expected-error@+1 {{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}} + { +#pragma omp target // expected-error {{OpenMP constructs may not be nested inside an atomic region}} + ++a; + } + +// TARGET DIRECTIVE +#pragma omp target +#pragma omp parallel + bar(); +#pragma omp target +#pragma omp for + for (int i = 0; i < 10; ++i) + ; +#pragma omp target +#pragma omp simd + for (int i = 0; i < 10; ++i) + ; +#pragma omp target +#pragma omp for simd + for (int i = 0; i < 10; ++i) + ; +#pragma omp target +#pragma omp sections + { + bar(); + } +#pragma omp target +#pragma omp section // expected-error {{'omp section' directive must be closely nested to a sections region, not a target region}} + { + bar(); + } +#pragma omp target +#pragma omp single + bar(); + +#pragma omp target +#pragma omp master + { + bar(); + } +#pragma omp target +#pragma omp critical + { + bar(); + } +#pragma omp target +#pragma omp parallel for + for (int i = 0; i < 10; ++i) + ; +#pragma omp target +#pragma omp parallel sections + { + bar(); + } +#pragma omp target +#pragma omp task + { + bar(); + } +#pragma omp target + { +#pragma omp taskyield + bar(); + } +#pragma omp target + { +#pragma omp barrier + bar(); + } +#pragma omp target + { +#pragma omp taskwait + bar(); + } +#pragma omp target + { +#pragma omp flush + bar(); + } +#pragma omp target + { +#pragma omp ordered // expected-error {{region cannot be closely nested inside 'target' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}} + bar(); + } +#pragma omp target + { +#pragma omp atomic + ++a; + } +#pragma omp target + { +#pragma omp target + ++a; + } } void foo() { @@ -1816,6 +1978,11 @@ void foo() { #pragma omp atomic ++a; } +#pragma omp parallel + { +#pragma omp target + ++a; + } // SIMD DIRECTIVE #pragma omp simd @@ -1920,6 +2087,11 @@ void foo() { #pragma omp atomic // 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 target // expected-error {{OpenMP constructs may not be nested inside a simd region}} + ++a; + } // FOR DIRECTIVE #pragma omp for @@ -2044,6 +2216,11 @@ void foo() { #pragma omp atomic ++a; } +#pragma omp for + for (int i = 0; i < 10; ++i) { +#pragma omp target + ++a; + } // FOR SIMD DIRECTIVE #pragma omp for simd @@ -2148,6 +2325,11 @@ void foo() { #pragma omp atomic // 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 target // expected-error {{OpenMP constructs may not be nested inside a simd region}} + ++a; + } // SECTIONS DIRECTIVE #pragma omp sections @@ -2264,6 +2446,11 @@ void foo() { #pragma omp atomic ++a; } +#pragma omp sections + { +#pragma omp target + ++a; + } // SECTION DIRECTIVE #pragma omp section // expected-error {{orphaned 'omp section' directives are prohibited, it must be closely nested to a sections region}} @@ -2438,6 +2625,14 @@ void foo() { ++a; } } +#pragma omp sections + { +#pragma omp section + { +#pragma omp target + ++a; + } + } // SINGLE DIRECTIVE #pragma omp single @@ -2552,6 +2747,11 @@ void foo() { #pragma omp atomic ++a; } +#pragma omp single + { +#pragma omp target + ++a; + } // MASTER DIRECTIVE #pragma omp master @@ -2676,6 +2876,11 @@ void foo() { #pragma omp atomic ++a; } +#pragma omp master + { +#pragma omp target + ++a; + } // CRITICAL DIRECTIVE #pragma omp critical @@ -2819,6 +3024,11 @@ void foo() { #pragma omp atomic ++a; } +#pragma omp critical + { +#pragma omp target + ++a; + } // PARALLEL FOR DIRECTIVE #pragma omp parallel for @@ -2958,6 +3168,11 @@ void foo() { #pragma omp atomic ++a; } +#pragma omp parallel for + for (int i = 0; i < 10; ++i) { +#pragma omp target + ++a; + } // PARALLEL SECTIONS DIRECTIVE #pragma omp parallel sections @@ -3084,6 +3299,11 @@ void foo() { #pragma omp atomic ++a; } +#pragma omp parallel sections + { +#pragma omp target + ++a; + } // TASK DIRECTIVE #pragma omp task @@ -3161,38 +3381,43 @@ void foo() { #pragma omp atomic ++a; } +#pragma omp task + { +#pragma omp target + ++a; + } // ATOMIC DIRECTIVE #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp for // expected-error {{OpenMP constructs may not be nested inside an atomic region}} for (int i = 0; i < 10; ++i) ; } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp simd // expected-error {{OpenMP constructs may not be nested inside an atomic region}} for (int i = 0; i < 10; ++i) ; } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp for simd // expected-error {{OpenMP constructs may not be nested inside an atomic region}} for (int i = 0; i < 10; ++i) ; } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp parallel // expected-error {{OpenMP constructs may not be nested inside an atomic region}} for (int i = 0; i < 10; ++i) ; } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp sections // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -3200,7 +3425,7 @@ void foo() { } } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp section // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -3208,7 +3433,7 @@ void foo() { } } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp single // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -3216,7 +3441,7 @@ void foo() { } } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp master // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -3224,7 +3449,7 @@ void foo() { } } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp critical // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -3232,14 +3457,14 @@ void foo() { } } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp parallel for // expected-error {{OpenMP constructs may not be nested inside an atomic region}} for (int i = 0; i < 10; ++i) ; } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp parallel sections // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -3247,7 +3472,7 @@ void foo() { } } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp task // expected-error {{OpenMP constructs may not be nested inside an atomic region}} { @@ -3255,41 +3480,137 @@ void foo() { } } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp taskyield // expected-error {{OpenMP constructs may not be nested inside an atomic region}} bar(); } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp barrier // expected-error {{OpenMP constructs may not be nested inside an atomic region}} bar(); } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside an atomic region}} bar(); } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp flush // expected-error {{OpenMP constructs may not be nested inside an atomic region}} bar(); } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp ordered // expected-error {{OpenMP constructs may not be nested inside an atomic region}} bar(); } #pragma omp atomic -// expected-error@+1 {{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-error@+1 {{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}} { #pragma omp atomic // expected-error {{OpenMP constructs may not be nested inside an atomic region}} ++a; } +#pragma omp atomic + // expected-error@+1 {{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}} + { +#pragma omp target // expected-error {{OpenMP constructs may not be nested inside an atomic region}} + ++a; + } + +// TARGET DIRECTIVE +#pragma omp target +#pragma omp parallel + bar(); +#pragma omp target +#pragma omp for + for (int i = 0; i < 10; ++i) + ; +#pragma omp target +#pragma omp simd + for (int i = 0; i < 10; ++i) + ; +#pragma omp target +#pragma omp for simd + for (int i = 0; i < 10; ++i) + ; +#pragma omp target +#pragma omp sections + { + bar(); + } +#pragma omp target +#pragma omp section // expected-error {{'omp section' directive must be closely nested to a sections region, not a target region}} + { + bar(); + } +#pragma omp target +#pragma omp single + bar(); + +#pragma omp target +#pragma omp master + { + bar(); + } +#pragma omp target +#pragma omp critical + { + bar(); + } +#pragma omp target +#pragma omp parallel for + for (int i = 0; i < 10; ++i) + ; +#pragma omp target +#pragma omp parallel sections + { + bar(); + } +#pragma omp target +#pragma omp task + { + bar(); + } +#pragma omp target + { +#pragma omp taskyield + bar(); + } +#pragma omp target + { +#pragma omp barrier + bar(); + } +#pragma omp target + { +#pragma omp taskwait + bar(); + } +#pragma omp target + { +#pragma omp flush + bar(); + } +#pragma omp target + { +#pragma omp ordered // expected-error {{region cannot be closely nested inside 'target' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}} + bar(); + } +#pragma omp target + { +#pragma omp atomic + ++a; + } +#pragma omp target + { +#pragma omp target + ++a; + } return foo(); } diff --git a/test/OpenMP/target_ast_print.cpp b/test/OpenMP/target_ast_print.cpp new file mode 100644 index 0000000000..c57c04955f --- /dev/null +++ b/test/OpenMP/target_ast_print.cpp @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp=libiomp5 -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 tmain(T argc, T *argv) { +#pragma omp target + foo(); +#pragma omp target if (argc > 0) + foo(); +#pragma omp target if (C) + foo(); + return 0; +} + +// CHECK: template int tmain(int argc, int *argv) { +// CHECK-NEXT: #pragma omp target +// CHECK-NEXT: foo(); +// CHECK-NEXT: #pragma omp target if(argc > 0) +// CHECK-NEXT: foo() +// CHECK-NEXT: #pragma omp target if(5) +// CHECK-NEXT: foo() +// CHECK: template char tmain(char argc, char *argv) { +// CHECK-NEXT: #pragma omp target +// CHECK-NEXT: foo(); +// CHECK-NEXT: #pragma omp target if(argc > 0) +// CHECK-NEXT: foo() +// CHECK-NEXT: #pragma omp target if(1) +// CHECK-NEXT: foo() +// CHECK: template T tmain(T argc, T *argv) { +// CHECK-NEXT: #pragma omp target +// CHECK-NEXT: foo(); +// CHECK-NEXT: #pragma omp target if(argc > 0) +// CHECK-NEXT: foo() +// CHECK-NEXT: #pragma omp target if(C) +// CHECK-NEXT: foo() + +// CHECK-LABEL: int main(int argc, char **argv) { +int main (int argc, char **argv) { +#pragma omp target +// CHECK-NEXT: #pragma omp target + foo(); +// CHECK-NEXT: foo(); +#pragma omp target if (argc > 0) +// CHECK-NEXT: #pragma omp target if(argc > 0) + foo(); +// CHECK-NEXT: foo(); + return tmain(argc, &argc) + tmain(argv[0][0], argv[0]); +} + +#endif diff --git a/test/OpenMP/target_if_messages.cpp b/test/OpenMP/target_if_messages.cpp new file mode 100644 index 0000000000..50a9ed2a20 --- /dev/null +++ b/test/OpenMP/target_if_messages.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -verify -fopenmp=libiomp5 %s + +void foo() { +} + +bool foobool(int argc) { + return argc; +} + +struct S1; // expected-note {{declared here}} + +template // expected-note {{declared here}} +int tmain(T argc, S **argv) { + #pragma omp target if // expected-error {{expected '(' after 'if'}} + #pragma omp target if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + #pragma omp target if () // expected-error {{expected expression}} + #pragma omp target if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + #pragma omp target if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target' are ignored}} + #pragma omp target if (argc > 0 ? argv[1] : argv[2]) + #pragma omp target if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp target' cannot contain more than one 'if' clause}} + #pragma omp target if (S) // expected-error {{'S' does not refer to a value}} + #pragma omp target if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} + #pragma omp target if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}} + #pragma omp target if(argc) + foo(); + + return 0; +} + +int main(int argc, char **argv) { + #pragma omp target if // expected-error {{expected '(' after 'if'}} + #pragma omp target if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + #pragma omp target if () // expected-error {{expected expression}} + #pragma omp target if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + #pragma omp target if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target' are ignored}} + #pragma omp target if (argc > 0 ? argv[1] : argv[2]) + #pragma omp target if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp target' cannot contain more than one 'if' clause}} + #pragma omp target if (S1) // expected-error {{'S1' does not refer to a value}} + #pragma omp target if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} + #pragma omp target if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}} + #pragma omp target if (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}} + #pragma omp target if(if(tmain(argc, argv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + foo(); + + return tmain(argc, argv); +} diff --git a/test/OpenMP/target_messages.cpp b/test/OpenMP/target_messages.cpp new file mode 100644 index 0000000000..fb492281e2 --- /dev/null +++ b/test/OpenMP/target_messages.cpp @@ -0,0 +1,64 @@ +// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -std=c++11 -o - %s + +void foo() { +} + +#pragma omp target // expected-error {{unexpected OpenMP directive '#pragma omp target'}} + +int main(int argc, char **argv) { + #pragma omp target { // expected-warning {{extra tokens at the end of '#pragma omp target' are ignored}} + foo(); + #pragma omp target ( // expected-warning {{extra tokens at the end of '#pragma omp target' are ignored}} + foo(); + #pragma omp target [ // expected-warning {{extra tokens at the end of '#pragma omp target' are ignored}} + foo(); + #pragma omp target ] // expected-warning {{extra tokens at the end of '#pragma omp target' are ignored}} + foo(); + #pragma omp target ) // expected-warning {{extra tokens at the end of '#pragma omp target' are ignored}} + foo(); + #pragma omp target } // expected-warning {{extra tokens at the end of '#pragma omp target' are ignored}} + foo(); + #pragma omp target + // expected-warning@+1 {{extra tokens at the end of '#pragma omp target' are ignored}} + #pragma omp target unknown() + foo(); + L1: + foo(); + #pragma omp target + ; + #pragma omp target + { + goto L1; // expected-error {{use of undeclared label 'L1'}} + argc++; + } + + for (int i = 0; i < 10; ++i) { + switch(argc) { + case (0): + #pragma omp target + { + foo(); + break; // expected-error {{'break' statement not in loop or switch statement}} + continue; // expected-error {{'continue' statement not in loop statement}} + } + default: + break; + } + } + + goto L2; // expected-error {{use of undeclared label 'L2'}} + #pragma omp target + L2: + foo(); + #pragma omp target + { + return 1; // expected-error {{cannot return from OpenMP region}} + } + + [[]] // expected-error {{an attribute list cannot appear here}} + #pragma omp target + for (int n = 0; n < 100; ++n) {} + + return 0; +} + diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 1c97845462..6d241170ca 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -1879,6 +1879,7 @@ public: void VisitOMPFlushDirective(const OMPFlushDirective *D); void VisitOMPOrderedDirective(const OMPOrderedDirective *D); void VisitOMPAtomicDirective(const OMPAtomicDirective *D); + void VisitOMPTargetDirective(const OMPTargetDirective *D); private: void AddDeclarationNameInfo(const Stmt *S); @@ -2407,6 +2408,10 @@ void EnqueueVisitor::VisitOMPAtomicDirective(const OMPAtomicDirective *D) { VisitOMPExecutableDirective(D); } +void EnqueueVisitor::VisitOMPTargetDirective(const OMPTargetDirective *D) { + VisitOMPExecutableDirective(D); +} + void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, const Stmt *S) { EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU,RegionOfInterest)).Visit(S); } @@ -4172,6 +4177,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return cxstring::createRef("OMPOrderedDirective"); case CXCursor_OMPAtomicDirective: return cxstring::createRef("OMPAtomicDirective"); + case CXCursor_OMPTargetDirective: + return cxstring::createRef("OMPTargetDirective"); } llvm_unreachable("Unhandled CXCursorKind"); diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp index 96e8f993f6..d83e71a99a 100644 --- a/tools/libclang/CXCursor.cpp +++ b/tools/libclang/CXCursor.cpp @@ -572,6 +572,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent, case Stmt::OMPAtomicDirectiveClass: K = CXCursor_OMPAtomicDirective; break; + case Stmt::OMPTargetDirectiveClass: + K = CXCursor_OMPTargetDirective; + break; } CXCursor C = { K, 0, { Parent, S, TU } };