]> granicus.if.org Git - clang/commitdiff
[OPENMP] Initial parsing/sema analysis of 'target' directive.
authorAlexey Bataev <a.bataev@hotmail.com>
Fri, 19 Sep 2014 08:19:49 +0000 (08:19 +0000)
committerAlexey Bataev <a.bataev@hotmail.com>
Fri, 19 Sep 2014 08:19:49 +0000 (08:19 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@218110 91177308-0d34-0410-b5e6-96231b3b80d8

27 files changed:
include/clang-c/Index.h
include/clang/AST/DataRecursiveASTVisitor.h
include/clang/AST/RecursiveASTVisitor.h
include/clang/AST/StmtOpenMP.h
include/clang/Basic/OpenMPKinds.def
include/clang/Basic/StmtNodes.td
include/clang/Sema/Sema.h
include/clang/Serialization/ASTBitCodes.h
lib/AST/Stmt.cpp
lib/AST/StmtPrinter.cpp
lib/AST/StmtProfile.cpp
lib/Basic/OpenMPKinds.cpp
lib/CodeGen/CGStmt.cpp
lib/CodeGen/CGStmtOpenMP.cpp
lib/CodeGen/CodeGenFunction.h
lib/Parse/ParseOpenMP.cpp
lib/Sema/SemaOpenMP.cpp
lib/Sema/TreeTransform.h
lib/Serialization/ASTReaderStmt.cpp
lib/Serialization/ASTWriterStmt.cpp
lib/StaticAnalyzer/Core/ExprEngine.cpp
test/OpenMP/nesting_of_regions.cpp
test/OpenMP/target_ast_print.cpp [new file with mode: 0644]
test/OpenMP/target_if_messages.cpp [new file with mode: 0644]
test/OpenMP/target_messages.cpp [new file with mode: 0644]
tools/libclang/CIndex.cpp
tools/libclang/CXCursor.cpp

index a86171aaba96fa336951cfded733e3b24d65c3d3..3f7f13cb069c2e230ebe24df1d119b4d8cae6a4f 100644 (file)
@@ -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.
index 0612231e915362354b5a73da42a140f8fafb0b94..b06fb255252974bc09761af6be1e2dedc70fb3a4 100644 (file)
@@ -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 <typename Derived>
 bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
index 19c01e0212ff32d06f7661e139011416a7881946..cf2b4156a33e24bdf9b5c2b78a86c77c33e698fe 100644 (file)
@@ -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 <typename Derived>
 bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
index 54df0eaf4715acbf4a5a59b1904e0842039687c8..cbb87355062985c7d0058cbc0203a2484ae5e1d6 100644 (file)
@@ -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<OMPClause *> 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
index cda95abc9e3950a24c12b5a21c5ca6ef9edd38e9..2c31307119b9ac6ee5f626ecfbc945e0bd6b420d 100644 (file)
@@ -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
index c967d3ff47e2f607163cd61a4bed7e76facde39e..81c113e6bf4d17164a838d40dc7c14b04d89c0d2 100644 (file)
@@ -197,3 +197,4 @@ def OMPTaskwaitDirective : DStmt<OMPExecutableDirective>;
 def OMPFlushDirective : DStmt<OMPExecutableDirective>;
 def OMPOrderedDirective : DStmt<OMPExecutableDirective>;
 def OMPAtomicDirective : DStmt<OMPExecutableDirective>;
+def OMPTargetDirective : DStmt<OMPExecutableDirective>;
index b262c45cd7cdedd0ec1235305c28ba2a2c1551a2..0e5ed350a77784bde913f9dcca9a8ca0380671ce 100644 (file)
@@ -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<OMPClause *> Clauses,
+                                        Stmt *AStmt, SourceLocation StartLoc,
+                                        SourceLocation EndLoc);
+
   OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
                                          Expr *Expr,
                                          SourceLocation StartLoc,
index d209bcc8769c54c7764858e8321e867973c034d9..0e13a910f6538b2d74dd6e2b1414b8ee1c1ceca4 100644 (file)
@@ -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
index e966ee83bbd7c9b479c1bf53cab8e9999034b86f..f2efca866444b351f340a16b277635a6e65c37a7 100644 (file)
@@ -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<OMPClause *> Clauses,
+                                               Stmt *AssociatedStmt) {
+  unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTargetDirective),
+                                           llvm::alignOf<OMPClause *>());
+  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<OMPClause *>());
+  void *Mem =
+      C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
+  return new (Mem) OMPTargetDirective(NumClauses);
+}
+
index 50715e68c267c7097af0868d4898106ca7de7a77..d065c62feab27647ced1a8e1581a203a369a53fa 100644 (file)
@@ -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.
 //===----------------------------------------------------------------------===//
index 9d2d69fa2825b8b03133e467f645b04b8ee5e956..cc61fae276f654e3c6689507dac97f8ea24d201a 100644 (file)
@@ -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);
 }
index b0043d5e486a975cf557948085052d8fd2e81024..7394d0bbb18e720ab5f0ce21ad4fe3bce17f3224 100644 (file)
@@ -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;
index 560ce608beeae7646aca123d4e5b1b316a8913d7..7be6759df42c0a42095d9604fda1ee8781fc5f28 100644 (file)
@@ -230,6 +230,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
   case Stmt::OMPAtomicDirectiveClass:
     EmitOMPAtomicDirective(cast<OMPAtomicDirective>(*S));
     break;
+  case Stmt::OMPTargetDirectiveClass:
+    EmitOMPTargetDirective(cast<OMPTargetDirective>(*S));
+    break;
   }
 }
 
index 3597dddd99a286ca9bdc9f29e5420995312626a1..74b73a55603575a82d5c14fc348940e55bc345f4 100644 (file)
@@ -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.");
+}
+
index eebdbf34a8eefb3cae8dbc8bab64ba67b53eaeea..4e89725a6001abcaa9234ad02a022064d75cc180 100644 (file)
@@ -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
index dd776773f42052d48b40a34b2887c996419f20e0..45f6da0d0591f776e4ba44aea2fa69e5cbae539e 100644 (file)
@@ -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' [ '(' <name> ')' ] |
 ///         '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) {
index 5c78804239e80ba97272b973d90fb8377e633bca..30d873efcc6823c89bdc2d88bd50957ed13f7fe8 100644 (file)
@@ -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<OMPClause *> Clauses,
   return OMPAtomicDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
 }
 
+StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
+                                            Stmt *AStmt,
+                                            SourceLocation StartLoc,
+                                            SourceLocation EndLoc) {
+  assert(AStmt && isa<CapturedStmt>(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,
index 92baa0ebd227b8f2cf779f9b86cad43cd6c20a53..9dfa8b73e0dd2fb1d8c3fe79ca9afb63d343df15 100644 (file)
@@ -6663,6 +6663,17 @@ TreeTransform<Derived>::TransformOMPAtomicDirective(OMPAtomicDirective *D) {
   return Res;
 }
 
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::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
 //===----------------------------------------------------------------------===//
index eefdcdf04c43e9234194341074d78966f015e3e0..ff7a53e22f8fc8fa3dd108296ca26b9e0623fb5d 100644 (file)
@@ -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;
index 9873eda75f5925bf2d19714af524e057d195a18d..759f7f3ade72c428fb645cfdbe5882a37510b2c3 100644 (file)
@@ -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);
index a80b2de70d561123797f28387f796d54ddc2ba69..f85b004f087ed0705bc5ba0f331aca34631d80f2 100644 (file)
@@ -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:
index eac2db215a2f42f20724365fab52b24e4779b52b..203026b2f758b45012c2d8509a17f95a33276797 100644 (file)
@@ -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<int>();
 }
 
diff --git a/test/OpenMP/target_ast_print.cpp b/test/OpenMP/target_ast_print.cpp
new file mode 100644 (file)
index 0000000..c57c049
--- /dev/null
@@ -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 <typename T, int C>
+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 <typename T = int, int C = 5> 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 <typename T = char, int C = 1> 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 <typename T, int C> 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<int, 5>(argc, &argc) + tmain<char, 1>(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 (file)
index 0000000..50a9ed2
--- /dev/null
@@ -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 <class T, class S> // 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 (file)
index 0000000..fb49228
--- /dev/null
@@ -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;
+}
+
index 1c97845462e887740cf80746c816b5cf077e31c8..6d241170ca82fa31378730d3abc8c9a4fe98b68d 100644 (file)
@@ -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");
index 96e8f993f66b620d59e8be114a1f33b247a46354..d83e71a99ac8bfb5c4c57751ce076aba5d276445 100644 (file)
@@ -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 } };