r212804 - [OPENMP] Parsing and sema analysis for 'omp task' directive.

Alexey Bataev a.bataev at hotmail.com
Fri Jul 11 04:25:18 PDT 2014


Author: abataev
Date: Fri Jul 11 06:25:16 2014
New Revision: 212804

URL: http://llvm.org/viewvc/llvm-project?rev=212804&view=rev
Log:
[OPENMP] Parsing and sema analysis for 'omp task' directive.

Added:
    cfe/trunk/test/OpenMP/task_ast_print.cpp   (with props)
    cfe/trunk/test/OpenMP/task_default_messages.cpp   (with props)
    cfe/trunk/test/OpenMP/task_firstprivate_messages.cpp   (with props)
    cfe/trunk/test/OpenMP/task_if_messages.cpp   (with props)
    cfe/trunk/test/OpenMP/task_messages.cpp   (with props)
    cfe/trunk/test/OpenMP/task_private_messages.cpp   (with props)
    cfe/trunk/test/OpenMP/task_shared_messages.cpp   (with props)
Modified:
    cfe/trunk/include/clang-c/Index.h
    cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
    cfe/trunk/include/clang/AST/StmtOpenMP.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Basic/OpenMPKinds.def
    cfe/trunk/include/clang/Basic/StmtNodes.td
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/include/clang/Serialization/ASTBitCodes.h
    cfe/trunk/lib/AST/Stmt.cpp
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/lib/AST/StmtProfile.cpp
    cfe/trunk/lib/Basic/OpenMPKinds.cpp
    cfe/trunk/lib/CodeGen/CGStmt.cpp
    cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/lib/Parse/ParseOpenMP.cpp
    cfe/trunk/lib/Sema/SemaOpenMP.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
    cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
    cfe/trunk/test/OpenMP/nesting_of_regions.cpp
    cfe/trunk/test/OpenMP/parallel_sections_private_messages.cpp
    cfe/trunk/tools/libclang/CIndex.cpp
    cfe/trunk/tools/libclang/CXCursor.cpp

Modified: cfe/trunk/include/clang-c/Index.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=212804&r1=212803&r2=212804&view=diff
==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Fri Jul 11 06:25:16 2014
@@ -2163,9 +2163,13 @@ enum CXCursorKind {
    */
   CXCursor_OMPParallelSectionsDirective  = 239,
 
+  /** \brief OpenMP task directive.
+   */
+  CXCursor_OMPTaskDirective              = 240,
+
   /** \brief Windows Structured Exception Handling's leave statement.
    */
-  CXCursor_SEHLeaveStmt                  = 240,
+  CXCursor_SEHLeaveStmt                  = 241,
 
   CXCursor_LastStmt                      = CXCursor_SEHLeaveStmt,
 

Modified: cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h?rev=212804&r1=212803&r2=212804&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h Fri Jul 11 06:25:16 2014
@@ -2303,6 +2303,9 @@ DEF_TRAVERSE_STMT(OMPParallelForDirectiv
 DEF_TRAVERSE_STMT(OMPParallelSectionsDirective,
                   { TRY_TO(TraverseOMPExecutableDirective(S)); })
 
+DEF_TRAVERSE_STMT(OMPTaskDirective,
+                  { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
 // OpenMP clauses.
 template <typename Derived>
 bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {

Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=212804&r1=212803&r2=212804&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Fri Jul 11 06:25:16 2014
@@ -2325,6 +2325,9 @@ DEF_TRAVERSE_STMT(OMPParallelForDirectiv
 DEF_TRAVERSE_STMT(OMPParallelSectionsDirective,
                   { TRY_TO(TraverseOMPExecutableDirective(S)); })
 
+DEF_TRAVERSE_STMT(OMPTaskDirective,
+                  { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
 // OpenMP clauses.
 template <typename Derived>
 bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {

Modified: cfe/trunk/include/clang/AST/StmtOpenMP.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtOpenMP.h?rev=212804&r1=212803&r2=212804&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/StmtOpenMP.h (original)
+++ cfe/trunk/include/clang/AST/StmtOpenMP.h Fri Jul 11 06:25:16 2014
@@ -658,6 +658,64 @@ public:
   }
 };
 
+/// \brief This represents '#pragma omp task' directive.
+///
+/// \code
+/// #pragma omp task private(a,b) final(d)
+/// \endcode
+/// In this example directive '#pragma omp task' has clauses 'private' with the
+/// variables 'a' and 'b' and 'final' with condition 'd'.
+///
+class OMPTaskDirective : 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.
+  ///
+  OMPTaskDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+                   unsigned NumClauses)
+      : OMPExecutableDirective(this, OMPTaskDirectiveClass, OMPD_task, StartLoc,
+                               EndLoc, NumClauses, 1) {}
+
+  /// \brief Build an empty directive.
+  ///
+  /// \param NumClauses Number of clauses.
+  ///
+  explicit OMPTaskDirective(unsigned NumClauses)
+      : OMPExecutableDirective(this, OMPTaskDirectiveClass, OMPD_task,
+                               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 OMPTaskDirective *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 OMPTaskDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
+                                       EmptyShell);
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == OMPTaskDirectiveClass;
+  }
+};
+
 } // end namespace clang
 
 #endif

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=212804&r1=212803&r2=212804&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Jul 11 06:25:16 2014
@@ -7017,8 +7017,12 @@ def err_omp_expected_var_name : Error<
   "expected variable name">;
 def err_omp_required_method : Error<
   "%0 variable must have an accessible, unambiguous %select{default constructor|copy constructor|copy assignment operator|'%2'|destructor}1">;
+def err_omp_task_predetermined_firstprivate_required_method : Error<
+  "predetermined as a firstprivate in a task construct variable must have an accessible, unambiguous %select{copy constructor|destructor}0">;
 def err_omp_clause_ref_type_arg : Error<
   "arguments of OpenMP clause '%0' cannot be of reference type %1">;
+def err_omp_task_predetermined_firstprivate_ref_type_arg : Error<
+  "predetermined as a firstprivate in a task construct variable cannot be of reference type %0">;
 def err_omp_threadprivate_incomplete_type : Error<
   "threadprivate variable with incomplete type %0">;
 def err_omp_no_dsa_for_variable : Error<
@@ -7035,6 +7039,7 @@ def note_omp_predetermined_dsa : Note<
   "loop iteration variable is predetermined as lastprivate|"
   "constant variable is predetermined as shared|"
   "global variable is predetermined as shared|"
+  "non-shared variable in a task construct is predetermined as firstprivate|"
   "variable with automatic storage duration is predetermined as private}0"
   "%select{|; perhaps you forget to enclose 'omp %2' directive into a parallel or another task region?}1">;
 def note_omp_implicit_dsa : Note<
@@ -7137,6 +7142,8 @@ def err_omp_sections_substmt_not_section
   "statement in 'omp sections' directive must be enclosed into a section region">;
 def err_omp_parallel_sections_substmt_not_section : Error<
   "statement in 'omp parallel sections' directive must be enclosed into a section region">;
+def err_omp_parallel_reduction_in_task_firstprivate : Error<
+  "argument of a reduction clause of a %0 construct must not appear in a firstprivate clause on a task construct">;
 } // end of OpenMP category
 
 let CategoryName = "Related Result Type Issue" in {

Modified: cfe/trunk/include/clang/Basic/OpenMPKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/OpenMPKinds.def?rev=212804&r1=212803&r2=212804&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/OpenMPKinds.def (original)
+++ cfe/trunk/include/clang/Basic/OpenMPKinds.def Fri Jul 11 06:25:16 2014
@@ -42,6 +42,9 @@
 #ifndef OPENMP_PARALLEL_SECTIONS_CLAUSE
 #  define OPENMP_PARALLEL_SECTIONS_CLAUSE(Name)
 #endif
+#ifndef OPENMP_TASK_CLAUSE
+#  define OPENMP_TASK_CLAUSE(Name)
+#endif
 #ifndef OPENMP_DEFAULT_KIND
 #  define OPENMP_DEFAULT_KIND(Name)
 #endif
@@ -170,6 +173,13 @@ OPENMP_PARALLEL_SECTIONS_CLAUSE(reductio
 OPENMP_PARALLEL_SECTIONS_CLAUSE(copyin)
 OPENMP_PARALLEL_SECTIONS_CLAUSE(lastprivate)
 
+// TODO more clauses allowed for OpenMP directive 'task'.
+OPENMP_TASK_CLAUSE(if)
+OPENMP_TASK_CLAUSE(default)
+OPENMP_TASK_CLAUSE(private)
+OPENMP_TASK_CLAUSE(firstprivate)
+OPENMP_TASK_CLAUSE(shared)
+
 #undef OPENMP_SCHEDULE_KIND
 #undef OPENMP_PROC_BIND_KIND
 #undef OPENMP_DEFAULT_KIND
@@ -181,6 +191,7 @@ OPENMP_PARALLEL_SECTIONS_CLAUSE(lastpriv
 #undef OPENMP_PARALLEL_CLAUSE
 #undef OPENMP_PARALLEL_FOR_CLAUSE
 #undef OPENMP_PARALLEL_SECTIONS_CLAUSE
+#undef OPENMP_TASK_CLAUSE
 #undef OPENMP_SIMD_CLAUSE
 #undef OPENMP_FOR_CLAUSE
 

Modified: cfe/trunk/include/clang/Basic/StmtNodes.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/StmtNodes.td?rev=212804&r1=212803&r2=212804&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/StmtNodes.td (original)
+++ cfe/trunk/include/clang/Basic/StmtNodes.td Fri Jul 11 06:25:16 2014
@@ -186,3 +186,4 @@ def OMPSectionDirective : DStmt<OMPExecu
 def OMPSingleDirective : DStmt<OMPExecutableDirective>;
 def OMPParallelForDirective : DStmt<OMPExecutableDirective>;
 def OMPParallelSectionsDirective : DStmt<OMPExecutableDirective>;
+def OMPTaskDirective : DStmt<OMPExecutableDirective>;

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=212804&r1=212803&r2=212804&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Jul 11 06:25:16 2014
@@ -7356,6 +7356,11 @@ public:
                                                   Stmt *AStmt,
                                                   SourceLocation StartLoc,
                                                   SourceLocation EndLoc);
+  /// \brief Called on well-formed '\#pragma omp task' after parsing of the
+  /// associated statement.
+  StmtResult ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
+                                      Stmt *AStmt, SourceLocation StartLoc,
+                                      SourceLocation EndLoc);
 
   OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
                                          Expr *Expr,

Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=212804&r1=212803&r2=212804&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Fri Jul 11 06:25:16 2014
@@ -1348,6 +1348,7 @@ namespace clang {
       STMT_OMP_SINGLE_DIRECTIVE,
       STMT_OMP_PARALLEL_FOR_DIRECTIVE,
       STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE,
+      STMT_OMP_TASK_DIRECTIVE,
 
       // ARC
       EXPR_OBJC_BRIDGED_CAST,     // ObjCBridgedCastExpr

Modified: cfe/trunk/lib/AST/Stmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Stmt.cpp?rev=212804&r1=212803&r2=212804&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Stmt.cpp (original)
+++ cfe/trunk/lib/AST/Stmt.cpp Fri Jul 11 06:25:16 2014
@@ -1528,3 +1528,29 @@ OMPParallelSectionsDirective::CreateEmpt
   return new (Mem) OMPParallelSectionsDirective(NumClauses);
 }
 
+OMPTaskDirective *OMPTaskDirective::Create(const ASTContext &C,
+                                           SourceLocation StartLoc,
+                                           SourceLocation EndLoc,
+                                           ArrayRef<OMPClause *> Clauses,
+                                           Stmt *AssociatedStmt) {
+  unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskDirective),
+                                           llvm::alignOf<OMPClause *>());
+  void *Mem =
+      C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
+  OMPTaskDirective *Dir =
+      new (Mem) OMPTaskDirective(StartLoc, EndLoc, Clauses.size());
+  Dir->setClauses(Clauses);
+  Dir->setAssociatedStmt(AssociatedStmt);
+  return Dir;
+}
+
+OMPTaskDirective *OMPTaskDirective::CreateEmpty(const ASTContext &C,
+                                                unsigned NumClauses,
+                                                EmptyShell) {
+  unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskDirective),
+                                           llvm::alignOf<OMPClause *>());
+  void *Mem =
+      C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
+  return new (Mem) OMPTaskDirective(NumClauses);
+}
+

Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=212804&r1=212803&r2=212804&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Fri Jul 11 06:25:16 2014
@@ -826,6 +826,11 @@ void StmtPrinter::VisitOMPParallelSectio
   PrintOMPExecutableDirective(Node);
 }
 
+void StmtPrinter::VisitOMPTaskDirective(OMPTaskDirective *Node) {
+  Indent() << "#pragma omp task ";
+  PrintOMPExecutableDirective(Node);
+}
+
 //===----------------------------------------------------------------------===//
 //  Expr printing methods.
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/AST/StmtProfile.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=212804&r1=212803&r2=212804&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtProfile.cpp (original)
+++ cfe/trunk/lib/AST/StmtProfile.cpp Fri Jul 11 06:25:16 2014
@@ -390,6 +390,10 @@ void StmtProfiler::VisitOMPParallelSecti
   VisitOMPExecutableDirective(S);
 }
 
+void StmtProfiler::VisitOMPTaskDirective(const OMPTaskDirective *S) {
+  VisitOMPExecutableDirective(S);
+}
+
 void StmtProfiler::VisitExpr(const Expr *S) {
   VisitStmt(S);
 }

Modified: cfe/trunk/lib/Basic/OpenMPKinds.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/OpenMPKinds.cpp?rev=212804&r1=212803&r2=212804&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/OpenMPKinds.cpp (original)
+++ cfe/trunk/lib/Basic/OpenMPKinds.cpp Fri Jul 11 06:25:16 2014
@@ -237,9 +237,18 @@ bool clang::isAllowedClauseForDirective(
       break;
     }
     break;
+  case OMPD_task:
+    switch (CKind) {
+#define OPENMP_TASK_CLAUSE(Name)                                               \
+  case OMPC_##Name:                                                            \
+    return true;
+#include "clang/Basic/OpenMPKinds.def"
+    default:
+      break;
+    }
+    break;
   case OMPD_unknown:
   case OMPD_threadprivate:
-  case OMPD_task:
   case OMPD_section:
     break;
   }

Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=212804&r1=212803&r2=212804&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmt.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmt.cpp Fri Jul 11 06:25:16 2014
@@ -200,6 +200,9 @@ void CodeGenFunction::EmitStmt(const Stm
   case Stmt::OMPParallelSectionsDirectiveClass:
     EmitOMPParallelSectionsDirective(cast<OMPParallelSectionsDirective>(*S));
     break;
+  case Stmt::OMPTaskDirectiveClass:
+    EmitOMPTaskDirective(cast<OMPTaskDirective>(*S));
+    break;
   }
 }
 

Modified: cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp?rev=212804&r1=212803&r2=212804&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp Fri Jul 11 06:25:16 2014
@@ -100,3 +100,7 @@ void CodeGenFunction::EmitOMPParallelSec
   llvm_unreachable("CodeGen for 'omp parallel sections' is not supported yet.");
 }
 
+void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &) {
+  llvm_unreachable("CodeGen for 'omp task' is not supported yet.");
+}
+

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=212804&r1=212803&r2=212804&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Fri Jul 11 06:25:16 2014
@@ -1918,6 +1918,7 @@ public:
   void EmitOMPSingleDirective(const OMPSingleDirective &S);
   void EmitOMPParallelForDirective(const OMPParallelForDirective &S);
   void EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &S);
+  void EmitOMPTaskDirective(const OMPTaskDirective &S);
 
   //===--------------------------------------------------------------------===//
   //                         LValue Expression Emission

Modified: cfe/trunk/lib/Parse/ParseOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseOpenMP.cpp?rev=212804&r1=212803&r2=212804&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseOpenMP.cpp (original)
+++ cfe/trunk/lib/Parse/ParseOpenMP.cpp Fri Jul 11 06:25:16 2014
@@ -105,8 +105,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpen
 ///
 ///       executable-directive:
 ///         annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
-///         'section' | 'single' | 'parallel for' | 'parallel sections' {clause}
-///         annot_pragma_openmp_end
+///         'section' | 'single' | 'parallel for' | 'parallel sections' | 'task'
+///         {clause} annot_pragma_openmp_end
 ///
 StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() {
   assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
@@ -147,7 +147,8 @@ StmtResult Parser::ParseOpenMPDeclarativ
   case OMPD_single:
   case OMPD_section:
   case OMPD_parallel_for:
-  case OMPD_parallel_sections: {
+  case OMPD_parallel_sections:
+  case OMPD_task: {
     ConsumeToken();
 
     if (isOpenMPLoopDirective(DKind))
@@ -209,11 +210,6 @@ StmtResult Parser::ParseOpenMPDeclarativ
     Diag(Tok, diag::err_omp_unknown_directive);
     SkipUntil(tok::annot_pragma_openmp_end);
     break;
-  case OMPD_task:
-    Diag(Tok, diag::err_omp_unexpected_directive)
-        << getOpenMPDirectiveName(DKind);
-    SkipUntil(tok::annot_pragma_openmp_end);
-    break;
   }
   return Directive;
 }

Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=212804&r1=212803&r2=212804&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Fri Jul 11 06:25:16 2014
@@ -139,21 +139,22 @@ public:
 
   /// \brief Returns data sharing attributes from top of the stack for the
   /// specified declaration.
-  DSAVarData getTopDSA(VarDecl *D);
+  DSAVarData getTopDSA(VarDecl *D, bool FromParent);
   /// \brief Returns data-sharing attributes for the specified declaration.
-  DSAVarData getImplicitDSA(VarDecl *D);
+  DSAVarData getImplicitDSA(VarDecl *D, bool FromParent);
   /// \brief Checks if the specified variables has data-sharing attributes which
   /// match specified \a CPred predicate in any directive which matches \a DPred
   /// predicate.
   template <class ClausesPredicate, class DirectivesPredicate>
   DSAVarData hasDSA(VarDecl *D, ClausesPredicate CPred,
-                    DirectivesPredicate DPred);
+                    DirectivesPredicate DPred, bool FromParent);
   /// \brief Checks if the specified variables has data-sharing attributes which
   /// match specified \a CPred predicate in any innermost directive which
   /// matches \a DPred predicate.
   template <class ClausesPredicate, class DirectivesPredicate>
   DSAVarData hasInnermostDSA(VarDecl *D, ClausesPredicate CPred,
-                             DirectivesPredicate DPred);
+                             DirectivesPredicate DPred,
+                             bool FromParent);
 
   /// \brief Returns currently analyzed directive.
   OpenMPDirectiveKind getCurrentDirective() const {
@@ -186,7 +187,7 @@ public:
 
   /// \brief Checks if the specified variable is a threadprivate.
   bool isThreadPrivate(VarDecl *D) {
-    DSAVarData DVar = getTopDSA(D);
+    DSAVarData DVar = getTopDSA(D, false);
     return isOpenMPThreadPrivate(DVar.CKind);
   }
 
@@ -194,6 +195,10 @@ public:
   Scope *getCurScope() { return Stack.back().CurScope; }
   SourceLocation getConstructLoc() { return Stack.back().ConstructLoc; }
 };
+bool isParallelOrTaskRegion(OpenMPDirectiveKind DKind) {
+  return isOpenMPParallelDirective(DKind) || DKind == OMPD_task ||
+         DKind == OMPD_unknown;
+}
 } // namespace
 
 DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter,
@@ -234,6 +239,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDS
   if (Iter->SharingMap.count(D)) {
     DVar.RefExpr = Iter->SharingMap[D].RefExpr;
     DVar.CKind = Iter->SharingMap[D].Attributes;
+    DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
     return DVar;
   }
 
@@ -282,7 +288,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDS
           DVar.CKind = OMPC_firstprivate;
           return DVar;
         }
-        if (isOpenMPParallelDirective(I->Directive))
+        if (isParallelOrTaskRegion(I->Directive))
           break;
       }
       DVar.DKind = OMPD_task;
@@ -328,7 +334,7 @@ bool DSAStackTy::isOpenMPLocal(VarDecl *
   if (Stack.size() > 2) {
     reverse_iterator I = Iter, E = std::prev(Stack.rend());
     Scope *TopScope = nullptr;
-    while (I != E && !isOpenMPParallelDirective(I->Directive)) {
+    while (I != E && !isParallelOrTaskRegion(I->Directive)) {
       ++I;
     }
     if (I == E)
@@ -343,7 +349,7 @@ bool DSAStackTy::isOpenMPLocal(VarDecl *
   return false;
 }
 
-DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D) {
+DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) {
   DSAVarData DVar;
 
   // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
@@ -363,9 +369,15 @@ DSAStackTy::DSAVarData DSAStackTy::getTo
   // in a Construct, C/C++, predetermined, p.1]
   // Variables with automatic storage duration that are declared in a scope
   // inside the construct are private.
-  OpenMPDirectiveKind Kind = getCurrentDirective();
-  if (!isOpenMPParallelDirective(Kind)) {
-    if (isOpenMPLocal(D, std::next(Stack.rbegin())) && D->isLocalVarDecl() &&
+  OpenMPDirectiveKind Kind =
+      FromParent ? getParentDirective() : getCurrentDirective();
+  auto StartI = std::next(Stack.rbegin());
+  auto EndI = std::prev(Stack.rend());
+  if (FromParent && StartI != EndI) {
+    StartI = std::next(StartI);
+  }
+  if (!isParallelOrTaskRegion(Kind)) {
+    if (isOpenMPLocal(D, StartI) && D->isLocalVarDecl() &&
         (D->getStorageClass() == SC_Auto || D->getStorageClass() == SC_None)) {
       DVar.CKind = OMPC_private;
       return DVar;
@@ -378,8 +390,8 @@ DSAStackTy::DSAVarData DSAStackTy::getTo
   if (D->isStaticDataMember()) {
     // Variables with const-qualified type having no mutable member may be
     // listed in a firstprivate clause, even if they are static data members.
-    DSAVarData DVarTemp =
-        hasDSA(D, MatchesAnyClause(OMPC_firstprivate), MatchesAlways());
+    DSAVarData DVarTemp = hasDSA(D, MatchesAnyClause(OMPC_firstprivate),
+                                 MatchesAlways(), FromParent);
     if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr)
       return DVar;
 
@@ -403,8 +415,8 @@ DSAStackTy::DSAVarData DSAStackTy::getTo
       !(SemaRef.getLangOpts().CPlusPlus && RD && RD->hasMutableFields())) {
     // Variables with const-qualified type having no mutable member may be
     // listed in a firstprivate clause, even if they are static data members.
-    DSAVarData DVarTemp =
-        hasDSA(D, MatchesAnyClause(OMPC_firstprivate), MatchesAlways());
+    DSAVarData DVarTemp = hasDSA(D, MatchesAnyClause(OMPC_firstprivate),
+                                 MatchesAlways(), FromParent);
     if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr)
       return DVar;
 
@@ -423,25 +435,36 @@ DSAStackTy::DSAVarData DSAStackTy::getTo
 
   // Explicitly specified attributes and local variables with predetermined
   // attributes.
-  if (Stack.back().SharingMap.count(D)) {
-    DVar.RefExpr = Stack.back().SharingMap[D].RefExpr;
-    DVar.CKind = Stack.back().SharingMap[D].Attributes;
+  auto I = std::prev(StartI);
+  if (I->SharingMap.count(D)) {
+    DVar.RefExpr = I->SharingMap[D].RefExpr;
+    DVar.CKind = I->SharingMap[D].Attributes;
+    DVar.ImplicitDSALoc = I->DefaultAttrLoc;
   }
 
   return DVar;
 }
 
-DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(VarDecl *D) {
-  return getDSA(std::next(Stack.rbegin()), D);
+DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(VarDecl *D, bool FromParent) {
+  auto StartI = Stack.rbegin();
+  auto EndI = std::prev(Stack.rend());
+  if (FromParent && StartI != EndI) {
+    StartI = std::next(StartI);
+  }
+  return getDSA(StartI, D);
 }
 
 template <class ClausesPredicate, class DirectivesPredicate>
 DSAStackTy::DSAVarData DSAStackTy::hasDSA(VarDecl *D, ClausesPredicate CPred,
-                                          DirectivesPredicate DPred) {
-  for (StackTy::reverse_iterator I = std::next(Stack.rbegin()),
-                                 E = std::prev(Stack.rend());
-       I != E; ++I) {
-    if (!DPred(I->Directive))
+                                          DirectivesPredicate DPred,
+                                          bool FromParent) {
+  auto StartI = std::next(Stack.rbegin());
+  auto EndI = std::prev(Stack.rend());
+  if (FromParent && StartI != EndI) {
+    StartI = std::next(StartI);
+  }
+  for (auto I = StartI, EE = EndI; I != EE; ++I) {
+    if (!DPred(I->Directive) && !isParallelOrTaskRegion(I->Directive))
       continue;
     DSAVarData DVar = getDSA(I, D);
     if (CPred(DVar.CKind))
@@ -451,12 +474,17 @@ DSAStackTy::DSAVarData DSAStackTy::hasDS
 }
 
 template <class ClausesPredicate, class DirectivesPredicate>
-DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(VarDecl *D,
-                                                   ClausesPredicate CPred,
-                                                   DirectivesPredicate DPred) {
-  for (auto I = Stack.rbegin(), EE = std::prev(Stack.rend()); I != EE; ++I) {
+DSAStackTy::DSAVarData
+DSAStackTy::hasInnermostDSA(VarDecl *D, ClausesPredicate CPred,
+                            DirectivesPredicate DPred, bool FromParent) {
+  auto StartI = std::next(Stack.rbegin());
+  auto EndI = std::prev(Stack.rend());
+  if (FromParent && StartI != EndI) {
+    StartI = std::next(StartI);
+  }
+  for (auto I = StartI, EE = EndI; I != EE; ++I) {
     if (!DPred(I->Directive))
-      continue;
+      break;
     DSAVarData DVar = getDSA(I, D);
     if (CPred(DVar.CKind))
       return DVar;
@@ -493,7 +521,7 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDi
           if (VarRef->isValueDependent() || VarRef->isTypeDependent())
             continue;
           auto VD = cast<VarDecl>(cast<DeclRefExpr>(VarRef)->getDecl());
-          auto DVar = DSAStack->getTopDSA(VD);
+          auto DVar = DSAStack->getTopDSA(VD, false);
           if (DVar.CKind == OMPC_lastprivate) {
             SourceLocation ELoc = VarRef->getExprLoc();
             auto Type = VarRef->getType();
@@ -795,10 +823,12 @@ static void ReportOriginalDSA(Sema &Sema
     PDSA_LoopIterVarLastprivate,
     PDSA_ConstVarShared,
     PDSA_GlobalVarShared,
+    PDSA_TaskVarFirstprivate,
     PDSA_LocalVarPrivate,
     PDSA_Implicit
   } Reason = PDSA_Implicit;
   bool ReportHint = false;
+  auto ReportLoc = VD->getLocation();
   if (IsLoopIterVar) {
     if (DVar.CKind == OMPC_private)
       Reason = PDSA_LoopIterVarPrivate;
@@ -806,6 +836,9 @@ static void ReportOriginalDSA(Sema &Sema
       Reason = PDSA_LoopIterVarLastprivate;
     else
       Reason = PDSA_LoopIterVarLinear;
+  } else if (DVar.DKind == OMPD_task && DVar.CKind == OMPC_firstprivate) {
+    Reason = PDSA_TaskVarFirstprivate;
+    ReportLoc = DVar.ImplicitDSALoc;
   } else if (VD->isStaticLocal())
     Reason = PDSA_StaticLocalVarShared;
   else if (VD->isStaticDataMember())
@@ -819,7 +852,7 @@ static void ReportOriginalDSA(Sema &Sema
     Reason = PDSA_LocalVarPrivate;
   }
   if (Reason != PDSA_Implicit) {
-    SemaRef.Diag(VD->getLocation(), diag::note_omp_predetermined_dsa)
+    SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
         << Reason << ReportHint
         << getOpenMPDirectiveName(Stack->getCurrentDirective());
   } else if (DVar.ImplicitDSALoc.isValid()) {
@@ -839,27 +872,23 @@ class DSAAttrChecker : public StmtVisito
 
 public:
   void VisitDeclRefExpr(DeclRefExpr *E) {
-    if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) {
+    if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
       // Skip internally declared variables.
       if (VD->isLocalVarDecl() && !CS->capturesVariable(VD))
         return;
 
-      SourceLocation ELoc = E->getExprLoc();
+      auto DVar = Stack->getTopDSA(VD, false);
+      // Check if the variable has explicit DSA set and stop analysis if it so.
+      if (DVar.RefExpr) return;
 
-      OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
-      DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD);
-      if (DVar.CKind != OMPC_unknown) {
-        if (DKind == OMPD_task && DVar.CKind != OMPC_shared &&
-            !Stack->isThreadPrivate(VD) && !DVar.RefExpr)
-          ImplicitFirstprivate.push_back(DVar.RefExpr);
-        return;
-      }
+      auto ELoc = E->getExprLoc();
+      auto DKind = Stack->getCurrentDirective();
       // The default(none) clause requires that each variable that is referenced
       // in the construct, and does not have a predetermined data-sharing
       // attribute, must have its data-sharing attribute explicitly determined
       // by being listed in a data-sharing attribute clause.
       if (DVar.CKind == OMPC_unknown && Stack->getDefaultDSA() == DSA_none &&
-          (isOpenMPParallelDirective(DKind) || DKind == OMPD_task) &&
+          isParallelOrTaskRegion(DKind) &&
           VarsWithInheritedDSA.count(VD) == 0) {
         VarsWithInheritedDSA[VD] = E;
         return;
@@ -870,7 +899,11 @@ public:
       //  enclosing worksharing or parallel construct may not be accessed in an
       //  explicit task.
       DVar = Stack->hasInnermostDSA(VD, MatchesAnyClause(OMPC_reduction),
-                                    MatchesAlways());
+                                    [](OpenMPDirectiveKind K) -> bool {
+                                      return isOpenMPParallelDirective(K) ||
+                                             isOpenMPWorksharingDirective(K);
+                                    },
+                                    false);
       if (DKind == OMPD_task && DVar.CKind == OMPC_reduction) {
         ErrorFound = true;
         SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
@@ -879,24 +912,27 @@ public:
       }
 
       // Define implicit data-sharing attributes for task.
-      DVar = Stack->getImplicitDSA(VD);
+      DVar = Stack->getImplicitDSA(VD, false);
       if (DKind == OMPD_task && DVar.CKind != OMPC_shared)
-        ImplicitFirstprivate.push_back(DVar.RefExpr);
+        ImplicitFirstprivate.push_back(E);
     }
   }
   void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
-    for (auto C : S->clauses())
-      if (C)
-        for (StmtRange R = C->children(); R; ++R)
-          if (Stmt *Child = *R)
-            Visit(Child);
+    for (auto *C : S->clauses()) {
+      // Skip analysis of arguments of implicitly defined firstprivate clause
+      // for task directives.
+      if (C && (!isa<OMPFirstprivateClause>(C) || C->getLocStart().isValid()))
+        for (auto *CC : C->children()) {
+          if (CC)
+            Visit(CC);
+        }
+    }
   }
   void VisitStmt(Stmt *S) {
-    for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I != E;
-         ++I)
-      if (Stmt *Child = *I)
-        if (!isa<OMPExecutableDirective>(Child))
-          Visit(Child);
+    for (auto *C : S->children()) {
+      if (C && !isa<OMPExecutableDirective>(C))
+        Visit(C);
+    }
   }
 
   bool isErrorFound() { return ErrorFound; }
@@ -984,8 +1020,15 @@ void Sema::ActOnOpenMPRegionStart(OpenMP
                              Params);
     break;
   }
+  case OMPD_task: {
+    Sema::CapturedParamNameType Params[] = {
+        std::make_pair(StringRef(), QualType()) // __context with shared vars
+    };
+    ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+                             Params);
+    break;
+  }
   case OMPD_threadprivate:
-  case OMPD_task:
     llvm_unreachable("OpenMP Directive is not allowed");
   case OMPD_unknown:
     llvm_unreachable("Unknown OpenMP directive");
@@ -1007,6 +1050,7 @@ bool CheckNestingOfRegions(Sema &SemaRef
   // | parallel         | single          | *                                  |
   // | parallel         | parallel for    | *                                  |
   // | parallel         |parallel sections| *                                  |
+  // | parallel         | task            | *                                  |
   // +------------------+-----------------+------------------------------------+
   // | for              | parallel        | *                                  |
   // | for              | for             | +                                  |
@@ -1016,6 +1060,7 @@ bool CheckNestingOfRegions(Sema &SemaRef
   // | for              | single          | +                                  |
   // | for              | parallel for    | *                                  |
   // | for              |parallel sections| *                                  |
+  // | for              | task            | *                                  |
   // +------------------+-----------------+------------------------------------+
   // | simd             | parallel        |                                    |
   // | simd             | for             |                                    |
@@ -1025,6 +1070,7 @@ bool CheckNestingOfRegions(Sema &SemaRef
   // | simd             | single          |                                    |
   // | simd             | parallel for    |                                    |
   // | simd             |parallel sections|                                    |
+  // | simd             | task            |                                    |
   // +------------------+-----------------+------------------------------------+
   // | sections         | parallel        | *                                  |
   // | sections         | for             | +                                  |
@@ -1034,6 +1080,7 @@ bool CheckNestingOfRegions(Sema &SemaRef
   // | sections         | single          | +                                  |
   // | sections         | parallel for    | *                                  |
   // | sections         |parallel sections| *                                  |
+  // | sections         | task            | *                                  |
   // +------------------+-----------------+------------------------------------+
   // | section          | parallel        | *                                  |
   // | section          | for             | +                                  |
@@ -1043,6 +1090,7 @@ bool CheckNestingOfRegions(Sema &SemaRef
   // | section          | single          | +                                  |
   // | section          | parallel for    | *                                  |
   // | section          |parallel sections| *                                  |
+  // | section          | task            | *                                  |
   // +------------------+-----------------+------------------------------------+
   // | single           | parallel        | *                                  |
   // | single           | for             | +                                  |
@@ -1052,6 +1100,7 @@ bool CheckNestingOfRegions(Sema &SemaRef
   // | single           | single          | +                                  |
   // | single           | parallel for    | *                                  |
   // | single           |parallel sections| *                                  |
+  // | single           | task            | *                                  |
   // +------------------+-----------------+------------------------------------+
   // | parallel for     | parallel        | *                                  |
   // | parallel for     | for             | +                                  |
@@ -1061,6 +1110,7 @@ bool CheckNestingOfRegions(Sema &SemaRef
   // | parallel for     | single          | +                                  |
   // | parallel for     | parallel for    | *                                  |
   // | parallel for     |parallel sections| *                                  |
+  // | parallel for     | task            | *                                  |
   // +------------------+-----------------+------------------------------------+
   // | parallel sections| parallel        | *                                  |
   // | parallel sections| for             | +                                  |
@@ -1070,6 +1120,17 @@ bool CheckNestingOfRegions(Sema &SemaRef
   // | parallel sections| single          | +                                  |
   // | parallel sections| parallel for    | *                                  |
   // | parallel sections|parallel sections| *                                  |
+  // | parallel sections| task            | *                                  |
+  // +------------------+-----------------+------------------------------------+
+  // | task             | parallel        | *                                  |
+  // | task             | for             | +                                  |
+  // | task             | simd            | *                                  |
+  // | task             | sections        | +                                  |
+  // | task             | section         | +                                  | 
+  // | task             | single          | +                                  |
+  // | task             | parallel for    | *                                  |
+  // | task             |parallel sections| *                                  |
+  // | task             | task            | *                                  |
   // +------------------+-----------------+------------------------------------+
   if (Stack->getCurScope()) {
     auto ParentRegion = Stack->getParentDirective();
@@ -1103,8 +1164,9 @@ bool CheckNestingOfRegions(Sema &SemaRef
       // A worksharing region may not be closely nested inside a worksharing,
       // explicit task, critical, ordered, atomic, or master region.
       // TODO
-      NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) &&
-                          !isOpenMPSimdDirective(ParentRegion);
+      NestingProhibited = (isOpenMPWorksharingDirective(ParentRegion) &&
+                           !isOpenMPSimdDirective(ParentRegion)) ||
+                          ParentRegion == OMPD_task;
       ShouldBeInParallelRegion = true;
     }
     if (NestingProhibited) {
@@ -1184,8 +1246,11 @@ StmtResult Sema::ActOnOpenMPExecutableDi
     Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
                                                StartLoc, EndLoc);
     break;
-  case OMPD_threadprivate:
   case OMPD_task:
+    Res =
+        ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
+    break;
+  case OMPD_threadprivate:
     llvm_unreachable("OpenMP Directive is not allowed");
   case OMPD_unknown:
     llvm_unreachable("Unknown OpenMP directive");
@@ -1651,7 +1716,7 @@ static bool CheckOpenMPIterationSpace(
   // constant-linear-step that is the increment of the associated for-loop.
   // The loop iteration variable(s) in the associated for-loop(s) of a for or
   // parallel for construct may be listed in a private or lastprivate clause.
-  DSAStackTy::DSAVarData DVar = DSA.getTopDSA(Var);
+  DSAStackTy::DSAVarData DVar = DSA.getTopDSA(Var, false);
   auto PredeterminedCKind =
       isOpenMPSimdDirective(DKind)
           ? ((NestedLoopCount == 1) ? OMPC_linear : OMPC_lastprivate)
@@ -1898,6 +1963,23 @@ Sema::ActOnOpenMPParallelSectionsDirecti
                                               Clauses, AStmt);
 }
 
+StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
+                                          Stmt *AStmt, SourceLocation StartLoc,
+                                          SourceLocation EndLoc) {
+  assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+  CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+  // 1.2.2 OpenMP Language Terminology
+  // Structured block - An executable statement with a single entry at the
+  // top and a single exit at the bottom.
+  // The point of exit cannot be a branch out of the structured block.
+  // longjmp() and throw() must not violate the entry/exit criteria.
+  CS->getCapturedDecl()->setNothrow();
+
+  getCurFunction()->setHasBranchProtectedScope();
+
+  return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
+}
+
 OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
                                              SourceLocation StartLoc,
                                              SourceLocation LParenLoc,
@@ -2494,7 +2576,7 @@ OMPClause *Sema::ActOnOpenMPPrivateClaus
     //  listed below. For these exceptions only, listing a predetermined
     //  variable in a data-sharing attribute clause is allowed and overrides
     //  the variable's predetermined data-sharing attributes.
-    DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
+    DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false);
     if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
       Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
                                           << getOpenMPClauseName(OMPC_private);
@@ -2517,6 +2599,10 @@ OMPClause *Sema::ActOnOpenMPFirstprivate
                                                SourceLocation LParenLoc,
                                                SourceLocation EndLoc) {
   SmallVector<Expr *, 8> Vars;
+  bool IsImplicitClause =
+      StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
+  auto ImplicitClauseLoc = DSAStack->getConstructLoc();
+
   for (auto &RefExpr : VarList) {
     assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
     if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
@@ -2525,7 +2611,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivate
       continue;
     }
 
-    SourceLocation ELoc = RefExpr->getExprLoc();
+    SourceLocation ELoc = IsImplicitClause ? ImplicitClauseLoc
+                                           : RefExpr->getExprLoc();
     // OpenMP [2.1, C/C++]
     //  A list item is a variable name.
     // OpenMP  [2.9.3.3, Restrictions, p.1]
@@ -2554,8 +2641,15 @@ OMPClause *Sema::ActOnOpenMPFirstprivate
       continue;
     }
     if (Type->isReferenceType()) {
-      Diag(ELoc, diag::err_omp_clause_ref_type_arg)
-          << getOpenMPClauseName(OMPC_firstprivate) << Type;
+      if (IsImplicitClause) {
+        Diag(ImplicitClauseLoc,
+             diag::err_omp_task_predetermined_firstprivate_ref_type_arg)
+            << Type;
+        Diag(RefExpr->getExprLoc(), diag::note_used_here);
+      } else {
+        Diag(ELoc, diag::err_omp_clause_ref_type_arg)
+            << getOpenMPClauseName(OMPC_firstprivate) << Type;
+      }
       bool IsDecl =
           VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
       Diag(VD->getLocation(),
@@ -2583,8 +2677,15 @@ OMPClause *Sema::ActOnOpenMPFirstprivate
                                  InitializedEntity::InitializeTemporary(Type),
                                  CD->getAccess(), PD) == AR_inaccessible ||
           CD->isDeleted()) {
-        Diag(ELoc, diag::err_omp_required_method)
-            << getOpenMPClauseName(OMPC_firstprivate) << 1;
+        if (IsImplicitClause) {
+          Diag(ImplicitClauseLoc,
+               diag::err_omp_task_predetermined_firstprivate_required_method)
+              << 0;
+          Diag(RefExpr->getExprLoc(), diag::note_used_here);
+        } else {
+          Diag(ELoc, diag::err_omp_required_method)
+              << getOpenMPClauseName(OMPC_firstprivate) << 1;
+        }
         bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
                       VarDecl::DeclarationOnly;
         Diag(VD->getLocation(),
@@ -2600,8 +2701,15 @@ OMPClause *Sema::ActOnOpenMPFirstprivate
       if (DD) {
         if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible ||
             DD->isDeleted()) {
-          Diag(ELoc, diag::err_omp_required_method)
-              << getOpenMPClauseName(OMPC_firstprivate) << 4;
+          if (IsImplicitClause) {
+            Diag(ImplicitClauseLoc,
+                 diag::err_omp_task_predetermined_firstprivate_required_method)
+                << 1;
+            Diag(RefExpr->getExprLoc(), diag::note_used_here);
+          } else {
+            Diag(ELoc, diag::err_omp_required_method)
+                << getOpenMPClauseName(OMPC_firstprivate) << 4;
+          }
           bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
                         VarDecl::DeclarationOnly;
           Diag(VD->getLocation(),
@@ -2615,10 +2723,9 @@ OMPClause *Sema::ActOnOpenMPFirstprivate
       }
     }
 
-    // If StartLoc and EndLoc are invalid - this is an implicit firstprivate
-    // variable and it was checked already.
-    if (StartLoc.isValid() && EndLoc.isValid()) {
-      DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
+    // If an implicit firstprivate variable found it was checked already.
+    if (!IsImplicitClause) {
+      DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false);
       Type = Type.getNonReferenceType().getCanonicalType();
       bool IsConstant = Type.isConstant(Context);
       Type = Context.getBaseElementType(Type);
@@ -2663,8 +2770,10 @@ OMPClause *Sema::ActOnOpenMPFirstprivate
       //  to any of the parallel regions arising from the parallel construct.
       if (isOpenMPWorksharingDirective(CurrDir) &&
           !isOpenMPParallelDirective(CurrDir)) {
-        DVar = DSAStack->getImplicitDSA(VD);
-        if (DVar.CKind != OMPC_shared) {
+        DVar = DSAStack->getImplicitDSA(VD, true);
+        if (DVar.CKind != OMPC_shared &&
+            (isOpenMPParallelDirective(DVar.DKind) ||
+             DVar.DKind == OMPD_unknown)) {
           Diag(ELoc, diag::err_omp_required_access)
               << getOpenMPClauseName(OMPC_firstprivate)
               << getOpenMPClauseName(OMPC_shared);
@@ -2678,13 +2787,28 @@ OMPClause *Sema::ActOnOpenMPFirstprivate
       //  construct if any of the worksharing or task regions arising from the
       //  worksharing or task construct ever bind to any of the parallel regions
       //  arising from the parallel construct.
-      // TODO
       // OpenMP [2.9.3.4, Restrictions, p.4]
       //  A list item that appears in a reduction clause in worksharing
       //  construct must not appear in a firstprivate clause in a task construct
       //  encountered during execution of any of the worksharing regions arising
       //  from the worksharing construct.
-      // TODO
+      if (CurrDir == OMPD_task) {
+        DVar =
+            DSAStack->hasInnermostDSA(VD, MatchesAnyClause(OMPC_reduction),
+                                      [](OpenMPDirectiveKind K) -> bool {
+                                        return isOpenMPParallelDirective(K) ||
+                                               isOpenMPWorksharingDirective(K);
+                                      },
+                                      false);
+        if (DVar.CKind == OMPC_reduction &&
+            (isOpenMPParallelDirective(DVar.DKind) ||
+             isOpenMPWorksharingDirective(DVar.DKind))) {
+          Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
+              << getOpenMPDirectiveName(DVar.DKind);
+          ReportOriginalDSA(*this, DSAStack, VD, DVar);
+          continue;
+        }
+      }
     }
 
     DSAStack->addDSA(VD, DE, OMPC_firstprivate);
@@ -2755,7 +2879,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateC
     //  Variables with the predetermined data-sharing attributes may not be
     //  listed in data-sharing attributes clauses, except for the cases
     //  listed below.
-    DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
+    DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false);
     if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
         DVar.CKind != OMPC_firstprivate &&
         (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
@@ -2775,7 +2899,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateC
     // regions.
     if (isOpenMPWorksharingDirective(CurrDir) &&
         !isOpenMPParallelDirective(CurrDir)) {
-      DVar = DSAStack->getImplicitDSA(VD);
+      DVar = DSAStack->getImplicitDSA(VD, true);
       if (DVar.CKind != OMPC_shared) {
         Diag(ELoc, diag::err_omp_required_access)
             << getOpenMPClauseName(OMPC_lastprivate)
@@ -2895,7 +3019,7 @@ OMPClause *Sema::ActOnOpenMPSharedClause
     //  listed below. For these exceptions only, listing a predetermined
     //  variable in a data-sharing attribute clause is allowed and overrides
     //  the variable's predetermined data-sharing attributes.
-    DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
+    DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false);
     if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
         DVar.RefExpr) {
       Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
@@ -2921,13 +3045,13 @@ class DSARefChecker : public StmtVisitor
 public:
   bool VisitDeclRefExpr(DeclRefExpr *E) {
     if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) {
-      DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD);
+      DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, false);
       if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
         return false;
       if (DVar.CKind != OMPC_unknown)
         return true;
       DSAStackTy::DSAVarData DVarPrivate =
-          Stack->hasDSA(VD, isOpenMPPrivate, MatchesAlways());
+          Stack->hasDSA(VD, isOpenMPPrivate, MatchesAlways(), false);
       if (DVarPrivate.CKind != OMPC_unknown)
         return true;
       return false;
@@ -3145,7 +3269,7 @@ OMPClause *Sema::ActOnOpenMPReductionCla
     //  Any number of reduction clauses can be specified on the directive,
     //  but a list item can appear only once in the reduction clauses for that
     //  directive.
-    DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
+    DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false);
     if (DVar.CKind == OMPC_reduction) {
       Diag(ELoc, diag::err_omp_once_referenced)
           << getOpenMPClauseName(OMPC_reduction);
@@ -3167,7 +3291,7 @@ OMPClause *Sema::ActOnOpenMPReductionCla
     OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
     if (isOpenMPWorksharingDirective(CurrDir) &&
         !isOpenMPParallelDirective(CurrDir)) {
-      DVar = DSAStack->getImplicitDSA(VD);
+      DVar = DSAStack->getImplicitDSA(VD, true);
       if (DVar.CKind != OMPC_shared) {
         Diag(ELoc, diag::err_omp_required_access)
             << getOpenMPClauseName(OMPC_reduction)
@@ -3275,7 +3399,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause
     //  A list-item cannot appear in more than one linear clause.
     //  A list-item that appears in a linear clause cannot appear in any
     //  other data-sharing attribute clause.
-    DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
+    DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false);
     if (DVar.RefExpr) {
       Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
                                           << getOpenMPClauseName(OMPC_linear);
@@ -3558,7 +3682,7 @@ OMPClause *Sema::ActOnOpenMPCopyprivateC
     //  A list item that appears in a copyprivate clause may not appear in a
     //  private or firstprivate clause on the single construct.
     if (!DSAStack->isThreadPrivate(VD)) {
-      auto DVar = DSAStack->getTopDSA(VD);
+      auto DVar = DSAStack->getTopDSA(VD, false);
       if (DVar.CKind != OMPC_copyprivate && DVar.CKind != OMPC_unknown &&
           !(DVar.CKind == OMPC_private && !DVar.RefExpr)) {
         Diag(ELoc, diag::err_omp_wrong_dsa)
@@ -3572,7 +3696,7 @@ OMPClause *Sema::ActOnOpenMPCopyprivateC
       //  All list items that appear in a copyprivate clause must be either
       //  threadprivate or private in the enclosing context.
       if (DVar.CKind == OMPC_unknown) {
-        DVar = DSAStack->getImplicitDSA(VD);
+        DVar = DSAStack->getImplicitDSA(VD, false);
         if (DVar.CKind == OMPC_shared) {
           Diag(ELoc, diag::err_omp_required_access)
               << getOpenMPClauseName(OMPC_copyprivate)

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=212804&r1=212803&r2=212804&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Fri Jul 11 06:25:16 2014
@@ -6512,6 +6512,17 @@ StmtResult TreeTransform<Derived>::Trans
   return Res;
 }
 
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPTaskDirective(OMPTaskDirective *D) {
+  DeclarationNameInfo DirName;
+  getDerived().getSema().StartOpenMPDSABlock(OMPD_task, DirName, nullptr,
+                                             D->getLocStart());
+  StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+  getDerived().getSema().EndOpenMPDSABlock(Res.get());
+  return Res;
+}
+
 //===----------------------------------------------------------------------===//
 // OpenMP clause transformation
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=212804&r1=212803&r2=212804&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Fri Jul 11 06:25:16 2014
@@ -1958,6 +1958,13 @@ void ASTStmtReader::VisitOMPParallelSect
   VisitOMPExecutableDirective(D);
 }
 
+void ASTStmtReader::VisitOMPTaskDirective(OMPTaskDirective *D) {
+  VisitStmt(D);
+  // The NumClauses field was read in ReadStmtFromStream.
+  ++Idx;
+  VisitOMPExecutableDirective(D);
+}
+
 //===----------------------------------------------------------------------===//
 // ASTReader Implementation
 //===----------------------------------------------------------------------===//
@@ -2483,6 +2490,11 @@ Stmt *ASTReader::ReadStmtFromStream(Modu
           Context, Record[ASTStmtReader::NumStmtFields], Empty);
       break;
 
+    case STMT_OMP_TASK_DIRECTIVE:
+      S = OMPTaskDirective::CreateEmpty(
+          Context, Record[ASTStmtReader::NumStmtFields], Empty);
+      break;
+
     case EXPR_CXX_OPERATOR_CALL:
       S = new (Context) CXXOperatorCallExpr(Context, Empty);
       break;

Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=212804&r1=212803&r2=212804&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Fri Jul 11 06:25:16 2014
@@ -1867,6 +1867,13 @@ void ASTStmtWriter::VisitOMPParallelSect
   Code = serialization::STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE;
 }
 
+void ASTStmtWriter::VisitOMPTaskDirective(OMPTaskDirective *D) {
+  VisitStmt(D);
+  Record.push_back(D->getNumClauses());
+  VisitOMPExecutableDirective(D);
+  Code = serialization::STMT_OMP_TASK_DIRECTIVE;
+}
+
 //===----------------------------------------------------------------------===//
 // ASTWriter Implementation
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=212804&r1=212803&r2=212804&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Fri Jul 11 06:25:16 2014
@@ -739,6 +739,7 @@ void ExprEngine::Visit(const Stmt *S, Ex
     case Stmt::OMPSingleDirectiveClass:
     case Stmt::OMPParallelForDirectiveClass:
     case Stmt::OMPParallelSectionsDirectiveClass:
+    case Stmt::OMPTaskDirectiveClass:
       llvm_unreachable("Stmt should not be in analyzer evaluation loop");
 
     case Stmt::ObjCSubscriptRefExprClass:

Modified: cfe/trunk/test/OpenMP/nesting_of_regions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/nesting_of_regions.cpp?rev=212804&r1=212803&r2=212804&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/nesting_of_regions.cpp (original)
+++ cfe/trunk/test/OpenMP/nesting_of_regions.cpp Fri Jul 11 06:25:16 2014
@@ -35,6 +35,11 @@ void foo() {
   {
     bar();
   }
+#pragma omp parallel
+#pragma omp task
+  {
+    bar();
+  }
 
 // SIMD DIRECTIVE
 #pragma omp simd
@@ -89,6 +94,13 @@ void foo() {
       bar();
     }
   }
+#pragma omp simd
+  for (int i = 0; i < 10; ++i) {
+#pragma omp task // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+    {
+      bar();
+    }
+  }
 
 // FOR DIRECTIVE
 #pragma omp for
@@ -160,6 +172,13 @@ void foo() {
       bar();
     }
   }
+#pragma omp for
+  for (int i = 0; i < 10; ++i) {
+#pragma omp task
+    {
+      bar();
+    }
+  }
 
 // SECTIONS DIRECTIVE
 #pragma omp sections
@@ -232,12 +251,123 @@ void foo() {
       bar();
     }
   }
+#pragma omp sections
+  {
+#pragma omp task
+    {
+      bar();
+    }
+  }
 
 // SECTION DIRECTIVE
 #pragma omp section // expected-error {{orphaned 'omp section' directives are prohibited, it must be closely nested to a sections region}}
   {
     bar();
   }
+#pragma omp sections
+  {
+#pragma omp section
+    {
+#pragma omp for // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}}
+      for (int i = 0; i < 10; ++i)
+        ;
+    }
+  }
+#pragma omp sections
+  {
+#pragma omp section
+    {
+#pragma omp simd
+      for (int i = 0; i < 10; ++i)
+        ;
+    }
+  }
+#pragma omp sections
+  {
+#pragma omp section
+    {
+#pragma omp parallel
+      for (int i = 0; i < 10; ++i)
+        ;
+    }
+  }
+#pragma omp sections
+  {
+#pragma omp section
+    {
+#pragma omp sections // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp sections' directive into a parallel region?}}
+      {
+        bar();
+      }
+    }
+  }
+#pragma omp sections
+  {
+#pragma omp section
+    {
+#pragma omp section // expected-error {{'omp section' directive must be closely nested to a sections region, not a section region}}
+      {
+        bar();
+      }
+    }
+  }
+#pragma omp sections
+  {
+#pragma omp section
+    {
+#pragma omp single // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}}
+      bar();
+    }
+  }
+#pragma omp sections
+  {
+#pragma omp section
+    {
+#pragma omp parallel
+      {
+#pragma omp single // OK
+        {
+          bar();
+        }
+#pragma omp for // OK
+        for (int i = 0; i < 10; ++i)
+          ;
+#pragma omp sections // OK
+        {
+          bar();
+        }
+      }
+    }
+  }
+#pragma omp sections
+  {
+#pragma omp section
+    {
+#pragma omp parallel for
+      for (int i = 0; i < 10; ++i)
+        ;
+    }
+  }
+#pragma omp sections
+  {
+#pragma omp section
+    {
+#pragma omp parallel sections
+      {
+        bar();
+      }
+    }
+  }
+#pragma omp sections
+  {
+#pragma omp section
+    {
+#pragma omp task
+      {
+        bar();
+      }
+    }
+  }
 
 // SINGLE DIRECTIVE
 #pragma omp single
@@ -302,6 +432,13 @@ void foo() {
       bar();
     }
   }
+#pragma omp single
+  {
+#pragma omp task
+    {
+      bar();
+    }
+  }
 
 // PARALLEL FOR DIRECTIVE
 #pragma omp parallel for
@@ -373,6 +510,13 @@ void foo() {
       bar();
     }
   }
+#pragma omp parallel for
+  for (int i = 0; i < 10; ++i) {
+#pragma omp task
+    {
+      bar();
+    }
+  }
 
 // PARALLEL SECTIONS DIRECTIVE
 #pragma omp parallel sections
@@ -445,6 +589,50 @@ void foo() {
       bar();
     }
   }
+#pragma omp parallel sections
+  {
+#pragma omp task
+    {
+      bar();
+    }
+  }
+
+// TASK DIRECTIVE
+#pragma omp task
+#pragma omp for // expected-error {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}}
+  for (int i = 0; i < 10; ++i)
+    ;
+#pragma omp task
+#pragma omp simd
+  for (int i = 0; i < 10; ++i)
+    ;
+#pragma omp task
+#pragma omp sections // expected-error {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp sections' directive into a parallel region?}}
+  {
+    bar();
+  }
+#pragma omp task
+#pragma omp section // expected-error {{'omp section' directive must be closely nested to a sections region, not a task region}}
+  {
+    bar();
+  }
+#pragma omp task
+#pragma omp single // expected-error {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}}
+  bar();
+#pragma omp task
+#pragma omp parallel for
+  for (int i = 0; i < 10; ++i)
+    ;
+#pragma omp task
+#pragma omp parallel sections
+  {
+    bar();
+  }
+#pragma omp task
+#pragma omp task
+  {
+    bar();
+  }
 }
 
 void foo() {
@@ -484,6 +672,11 @@ void foo() {
   {
     bar();
   }
+#pragma omp parallel
+#pragma omp task
+  {
+    bar();
+  }
 
 // SIMD DIRECTIVE
 #pragma omp simd
@@ -536,6 +729,13 @@ void foo() {
       bar();
     }
   }
+#pragma omp simd
+  for (int i = 0; i < 10; ++i) {
+#pragma omp task // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+    {
+      bar();
+    }
+  }
 
 // FOR DIRECTIVE
 #pragma omp for
@@ -605,6 +805,13 @@ void foo() {
       bar();
     }
   }
+#pragma omp for
+  for (int i = 0; i < 10; ++i) {
+#pragma omp task
+    {
+      bar();
+    }
+  }
 
 // SECTIONS DIRECTIVE
 #pragma omp sections
@@ -674,12 +881,123 @@ void foo() {
       bar();
     }
   }
+#pragma omp sections
+  {
+#pragma omp task
+    {
+      bar();
+    }
+  }
 
 // SECTION DIRECTIVE
 #pragma omp section // expected-error {{orphaned 'omp section' directives are prohibited, it must be closely nested to a sections region}}
   {
     bar();
   }
+#pragma omp sections
+  {
+#pragma omp section
+    {
+#pragma omp for // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}}
+      for (int i = 0; i < 10; ++i)
+        ;
+    }
+  }
+#pragma omp sections
+  {
+#pragma omp section
+    {
+#pragma omp simd
+      for (int i = 0; i < 10; ++i)
+        ;
+    }
+  }
+#pragma omp sections
+  {
+#pragma omp section
+    {
+#pragma omp parallel
+      for (int i = 0; i < 10; ++i)
+        ;
+    }
+  }
+#pragma omp sections
+  {
+#pragma omp section
+    {
+#pragma omp sections // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp sections' directive into a parallel region?}}
+      {
+        bar();
+      }
+    }
+  }
+#pragma omp sections
+  {
+#pragma omp section
+    {
+#pragma omp section // expected-error {{'omp section' directive must be closely nested to a sections region, not a section region}}
+      {
+        bar();
+      }
+    }
+  }
+#pragma omp sections
+  {
+#pragma omp section
+    {
+#pragma omp single // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}}
+      bar();
+    }
+  }
+#pragma omp sections
+  {
+#pragma omp section
+    {
+#pragma omp parallel
+      {
+#pragma omp single // OK
+        {
+          bar();
+        }
+#pragma omp for // OK
+        for (int i = 0; i < 10; ++i)
+          ;
+#pragma omp sections // OK
+        {
+          bar();
+        }
+      }
+    }
+  }
+#pragma omp sections
+  {
+#pragma omp section
+    {
+#pragma omp parallel for
+      for (int i = 0; i < 10; ++i)
+        ;
+    }
+  }
+#pragma omp sections
+  {
+#pragma omp section
+    {
+#pragma omp parallel sections
+      {
+        bar();
+      }
+    }
+  }
+#pragma omp sections
+  {
+#pragma omp section
+    {
+#pragma omp task
+      {
+        bar();
+      }
+    }
+  }
 
 // SINGLE DIRECTIVE
 #pragma omp single
@@ -744,6 +1062,13 @@ void foo() {
       bar();
     }
   }
+#pragma omp single
+  {
+#pragma omp task
+    {
+      bar();
+    }
+  }
 
 // PARALLEL FOR DIRECTIVE
 #pragma omp parallel for
@@ -815,6 +1140,13 @@ void foo() {
       bar();
     }
   }
+#pragma omp parallel for
+  for (int i = 0; i < 10; ++i) {
+#pragma omp task
+    {
+      bar();
+    }
+  }
 
 // PARALLEL SECTIONS DIRECTIVE
 #pragma omp parallel sections
@@ -887,6 +1219,50 @@ void foo() {
       bar();
     }
   }
+#pragma omp parallel sections
+  {
+#pragma omp task
+    {
+      bar();
+    }
+  }
+
+// TASK DIRECTIVE
+#pragma omp task
+#pragma omp for // expected-error {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}}
+  for (int i = 0; i < 10; ++i)
+    ;
+#pragma omp task
+#pragma omp simd
+  for (int i = 0; i < 10; ++i)
+    ;
+#pragma omp task
+#pragma omp sections // expected-error {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp sections' directive into a parallel region?}}
+  {
+    bar();
+  }
+#pragma omp task
+#pragma omp section // expected-error {{'omp section' directive must be closely nested to a sections region, not a task region}}
+  {
+    bar();
+  }
+#pragma omp task
+#pragma omp single // expected-error {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}}
+  bar();
+#pragma omp task
+#pragma omp parallel for
+  for (int i = 0; i < 10; ++i)
+    ;
+#pragma omp task
+#pragma omp parallel sections
+  {
+    bar();
+  }
+#pragma omp task
+#pragma omp task
+  {
+    bar();
+  }
   return foo<int>();
 }
 

Modified: cfe/trunk/test/OpenMP/parallel_sections_private_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_sections_private_messages.cpp?rev=212804&r1=212803&r2=212804&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/parallel_sections_private_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/parallel_sections_private_messages.cpp Fri Jul 11 06:25:16 2014
@@ -96,7 +96,7 @@ int foomain(I argc, C **argv) {
   {
     foo();
   }
-#pragma omp parallel sections copyprivate(i) // expected-error {{unexpected OpenMP clause 'copyprivate' in directive '#pragma omp parallel sections'}}
+#pragma omp parallel sections copyprivate(h) // expected-error {{unexpected OpenMP clause 'copyprivate' in directive '#pragma omp parallel sections'}}
   {
     foo();
   }
@@ -176,7 +176,7 @@ int main(int argc, char **argv) {
   {
     foo();
   }
-#pragma omp parallel sections copyprivate(i) // expected-error {{unexpected OpenMP clause 'copyprivate' in directive '#pragma omp parallel sections'}}
+#pragma omp parallel sections copyprivate(h) // expected-error {{unexpected OpenMP clause 'copyprivate' in directive '#pragma omp parallel sections'}}
   {
     foo();
   }

Added: cfe/trunk/test/OpenMP/task_ast_print.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/task_ast_print.cpp?rev=212804&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/task_ast_print.cpp (added)
+++ cfe/trunk/test/OpenMP/task_ast_print.cpp Fri Jul 11 06:25:16 2014
@@ -0,0 +1,96 @@
+// 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 <class T>
+struct S {
+  operator T() { return T(); }
+  static T TS;
+#pragma omp threadprivate(TS)
+};
+
+// CHECK:      template <class T = int> struct S {
+// CHECK:        static int TS;
+// CHECK-NEXT:   #pragma omp threadprivate(S<int>::TS)
+// CHECK-NEXT: }
+// CHECK:      template <class T = long> struct S {
+// CHECK:        static long TS;
+// CHECK-NEXT:   #pragma omp threadprivate(S<long>::TS)
+// CHECK-NEXT: }
+// CHECK:      template <class T> struct S {
+// CHECK:        static T TS;
+// CHECK-NEXT:   #pragma omp threadprivate(S::TS)
+// CHECK:      };
+
+template <typename T, int C>
+T tmain(T argc, T *argv) {
+  T b = argc, c, d, e, f, g;
+  static T a;
+  S<T> s;
+#pragma omp task
+  a = 2;
+#pragma omp task default(none), private(argc, b) firstprivate(argv) shared(d) if (argc > 0)
+  foo();
+#pragma omp task if (C)
+  foo();
+  return 0;
+}
+
+// CHECK: template <typename T = int, int C = 5> int tmain(int argc, int *argv) {
+// CHECK-NEXT: int b = argc, c, d, e, f, g;
+// CHECK-NEXT: static int a;
+// CHECK-NEXT: S<int> s;
+// CHECK-NEXT: #pragma omp task
+// CHECK-NEXT: a = 2;
+// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0)
+// CHECK-NEXT: foo()
+// CHECK-NEXT: #pragma omp task if(5)
+// CHECK-NEXT: foo()
+// CHECK: template <typename T = long, int C = 1> long tmain(long argc, long *argv) {
+// CHECK-NEXT: long b = argc, c, d, e, f, g;
+// CHECK-NEXT: static long a;
+// CHECK-NEXT: S<long> s;
+// CHECK-NEXT: #pragma omp task
+// CHECK-NEXT: a = 2;
+// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0)
+// CHECK-NEXT: foo()
+// CHECK-NEXT: #pragma omp task if(1)
+// CHECK-NEXT: foo()
+// CHECK: template <typename T, int C> T tmain(T argc, T *argv) {
+// CHECK-NEXT: T b = argc, c, d, e, f, g;
+// CHECK-NEXT: static T a;
+// CHECK-NEXT: S<T> s;
+// CHECK-NEXT: #pragma omp task
+// CHECK-NEXT: a = 2;
+// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0)
+// CHECK-NEXT: foo()
+// CHECK-NEXT: #pragma omp task if(C)
+// CHECK-NEXT: foo()
+
+enum Enum {};
+
+int main(int argc, char **argv) {
+  long x;
+  int b = argc, c, d, e, f, g;
+  static int a;
+#pragma omp threadprivate(a)
+  Enum ee;
+// CHECK: Enum ee;
+#pragma omp task
+  // CHECK-NEXT: #pragma omp task
+  a = 2;
+// CHECK-NEXT: a = 2;
+#pragma omp task default(none), private(argc, b) firstprivate(argv) if (argc > 0)
+  // CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) if(argc > 0)
+  foo();
+  // CHECK-NEXT: foo();
+  return tmain<int, 5>(b, &b) + tmain<long, 1>(x, &x);
+}
+
+#endif

Propchange: cfe/trunk/test/OpenMP/task_ast_print.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/OpenMP/task_ast_print.cpp
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/test/OpenMP/task_ast_print.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cfe/trunk/test/OpenMP/task_default_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/task_default_messages.cpp?rev=212804&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/task_default_messages.cpp (added)
+++ cfe/trunk/test/OpenMP/task_default_messages.cpp Fri Jul 11 06:25:16 2014
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ferror-limit 100 -o - %s
+
+void foo();
+
+int main(int argc, char **argv) {
+#pragma omp task default                          // expected-error {{expected '(' after 'default'}}
+#pragma omp task default(                         // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp task default()                        // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp task default(none                     // expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp task default(shared), default(shared) // expected-error {{directive '#pragma omp task' cannot contain more than one 'default' clause}}
+#pragma omp task default(x)                       // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+  foo();
+
+#pragma omp task default(none)
+  ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
+
+#pragma omp task default(none)
+#pragma omp task default(shared)
+  ++argc;
+  return 0;
+}

Propchange: cfe/trunk/test/OpenMP/task_default_messages.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/OpenMP/task_default_messages.cpp
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/test/OpenMP/task_default_messages.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cfe/trunk/test/OpenMP/task_firstprivate_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/task_firstprivate_messages.cpp?rev=212804&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/task_firstprivate_messages.cpp (added)
+++ cfe/trunk/test/OpenMP/task_firstprivate_messages.cpp Fri Jul 11 06:25:16 2014
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ferror-limit 100 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+  return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note{{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+  mutable int a;
+
+public:
+  S2() : a(0) {}
+  S2(S2 &s2) : a(s2.a) {}
+  static float S2s;
+  static const float S2sc;
+};
+const float S2::S2sc = 0;
+const S2 b;
+const S2 ba[5];
+class S3 {
+  int a;
+
+public:
+  S3() : a(0) {}
+  S3(S3 &s3) : a(s3.a) {}
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 { // expected-note {{'S4' declared here}}
+  int a;
+  S4();
+  S4(const S4 &s4);
+
+public:
+  S4(int v) : a(v) {}
+};
+class S5 { // expected-note {{'S5' declared here}}
+  int a;
+  S5() : a(0) {}
+  S5(const S5 &s5) : a(s5.a) {}
+
+public:
+  S5(int v) : a(v) {}
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}}
+
+int main(int argc, char **argv) {
+  const int d = 5;
+  const int da[5] = {0};
+  S4 e(4); // expected-note {{'e' defined here}}
+  S5 g(5); // expected-note {{'g' defined here}}
+  int i;
+  int &j = i;                                               // expected-note {{'j' defined here}}
+#pragma omp task firstprivate                               // expected-error {{expected '(' after 'firstprivate'}}
+#pragma omp task firstprivate(                              // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp task firstprivate()                             // expected-error {{expected expression}}
+#pragma omp task firstprivate(argc                          // expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp task firstprivate(argc,                         // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp task firstprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+#pragma omp task firstprivate(argc)
+#pragma omp task firstprivate(S1)            // expected-error {{'S1' does not refer to a value}}
+#pragma omp task firstprivate(a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}}
+#pragma omp task firstprivate(argv[1])       // expected-error {{expected variable name}}
+#pragma omp task firstprivate(ba)
+#pragma omp task firstprivate(ca)
+#pragma omp task firstprivate(da)
+#pragma omp task firstprivate(S2::S2s)
+#pragma omp task firstprivate(S2::S2sc)
+#pragma omp task firstprivate(e, g)          // expected-error 2 {{firstprivate variable must have an accessible, unambiguous copy constructor}}
+#pragma omp task firstprivate(h)             // expected-error {{threadprivate or thread local variable cannot be firstprivate}}
+#pragma omp task private(i), firstprivate(i) // expected-error {{private variable cannot be firstprivate}} expected-note{{defined as private}}
+  foo();
+#pragma omp task shared(i)
+#pragma omp task firstprivate(i)
+#pragma omp task firstprivate(j) // expected-error {{arguments of OpenMP clause 'firstprivate' cannot be of reference type}}
+  foo();
+
+  return 0;
+}

Propchange: cfe/trunk/test/OpenMP/task_firstprivate_messages.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/OpenMP/task_firstprivate_messages.cpp
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/test/OpenMP/task_firstprivate_messages.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cfe/trunk/test/OpenMP/task_if_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/task_if_messages.cpp?rev=212804&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/task_if_messages.cpp (added)
+++ cfe/trunk/test/OpenMP/task_if_messages.cpp Fri Jul 11 06:25:16 2014
@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ferror-limit 100 %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 task if // expected-error {{expected '(' after 'if'}}
+  #pragma omp task if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp task if () // expected-error {{expected expression}}
+  #pragma omp task if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp task if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp task' are ignored}}
+  #pragma omp task if (argc > 0 ? argv[1] : argv[2])
+  #pragma omp task if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp task' cannot contain more than one 'if' clause}}
+  #pragma omp task if (S) // expected-error {{'S' does not refer to a value}}
+  #pragma omp task if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp task if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp task if(argc)
+  foo();
+
+  return 0;
+}
+
+int main(int argc, char **argv) {
+  #pragma omp task if // expected-error {{expected '(' after 'if'}}
+  #pragma omp task if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp task if () // expected-error {{expected expression}}
+  #pragma omp task if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp task if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp task' are ignored}}
+  #pragma omp task if (argc > 0 ? argv[1] : argv[2])
+  #pragma omp task if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp task' cannot contain more than one 'if' clause}}
+  #pragma omp task if (S1) // expected-error {{'S1' does not refer to a value}}
+  #pragma omp task if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp task if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp task if (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+  #pragma omp task if(if(tmain(argc, argv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  foo();
+
+  return tmain(argc, argv);
+}

Propchange: cfe/trunk/test/OpenMP/task_if_messages.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/OpenMP/task_if_messages.cpp
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/test/OpenMP/task_if_messages.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cfe/trunk/test/OpenMP/task_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/task_messages.cpp?rev=212804&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/task_messages.cpp (added)
+++ cfe/trunk/test/OpenMP/task_messages.cpp Fri Jul 11 06:25:16 2014
@@ -0,0 +1,263 @@
+// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ferror-limit 100 -std=c++11 -o - %s
+
+void foo() {
+}
+
+#pragma omp task // expected-error {{unexpected OpenMP directive '#pragma omp task'}}
+
+class S { // expected-note 6 {{'S' declared here}}
+  S(const S &s) { a = s.a + 12; }
+  int a;
+
+public:
+  S() : a(0) {}
+  S(int a) : a(a) {}
+  operator int() { return a; }
+  S &operator++() { return *this; }
+  S operator+(const S &) { return *this; }
+};
+
+template <class T>
+int foo() {
+  T a; // expected-note 3 {{'a' defined here}}
+  T &b = a; // expected-note 4 {{'b' defined here}}
+  int r;
+#pragma omp task default(none)
+#pragma omp task default(shared)
+  ++a;
+// expected-error at +2 {{predetermined as a firstprivate in a task construct variable must have an accessible, unambiguous copy constructor}}
+#pragma omp task default(none)
+#pragma omp task
+// expected-note at +1 {{used here}}
+  ++a;
+#pragma omp task
+// expected-error at +1 {{predetermined as a firstprivate in a task construct variable must have an accessible, unambiguous copy constructor}}
+#pragma omp task
+  // expected-note at +1 {{used here}}
+  ++a;
+#pragma omp task default(shared)
+#pragma omp task
+  ++a;
+#pragma omp task
+#pragma omp parallel
+  ++a;
+// expected-error at +2 {{predetermined as a firstprivate in a task construct variable cannot be of reference type 'int &'}}
+// expected-error at +1 {{predetermined as a firstprivate in a task construct variable cannot be of reference type 'S &'}}
+#pragma omp task
+  // expected-note at +1 2 {{used here}}
+  ++b;
+// expected-error at +3 {{predetermined as a firstprivate in a task construct variable cannot be of reference type 'int &'}}
+// expected-error at +2 {{predetermined as a firstprivate in a task construct variable cannot be of reference type 'S &'}}
+// expected-error at +1 {{predetermined as a firstprivate in a task construct variable must have an accessible, unambiguous copy constructor}}
+#pragma omp task
+// expected-note at +1 3 {{used here}}
+#pragma omp parallel shared(a, b)
+  ++a, ++b;
+// expected-note at +1 3 {{defined as reduction}}
+#pragma omp parallel reduction(+ : r)
+// expected-error at +1 {{argument of a reduction clause of a parallel construct must not appear in a firstprivate clause on a task construct}}
+#pragma omp task firstprivate(r)
+  // expected-error at +1 2 {{reduction variables may not be accessed in an explicit task}}
+  ++r;
+// expected-note at +1 2 {{defined as reduction}}
+#pragma omp parallel reduction(+ : r)
+#pragma omp task default(shared)
+  // expected-error at +1 2 {{reduction variables may not be accessed in an explicit task}}
+  ++r;
+// expected-note at +1 2 {{defined as reduction}}
+#pragma omp parallel reduction(+ : r)
+#pragma omp task
+  // expected-error at +1 2 {{reduction variables may not be accessed in an explicit task}}
+  ++r;
+#pragma omp parallel
+// expected-note at +1 3 {{defined as reduction}}
+#pragma omp for reduction(+ : r)
+  for (int i = 0; i < 10; ++i)
+// expected-error at +1 {{argument of a reduction clause of a for construct must not appear in a firstprivate clause on a task construct}}
+#pragma omp task firstprivate(r)
+    // expected-error at +1 2 {{reduction variables may not be accessed in an explicit task}}
+    ++r;
+#pragma omp parallel
+// expected-note at +1 2 {{defined as reduction}}
+#pragma omp for reduction(+ : r)
+  for (int i = 0; i < 10; ++i)
+#pragma omp task default(shared)
+    // expected-error at +1 2 {{reduction variables may not be accessed in an explicit task}}
+    ++r;
+#pragma omp parallel
+// expected-note at +1 2 {{defined as reduction}}
+#pragma omp for reduction(+ : r)
+  for (int i = 0; i < 10; ++i)
+#pragma omp task
+    // expected-error at +1 2 {{reduction variables may not be accessed in an explicit task}}
+    ++r;
+// expected-note at +1 {{non-shared variable in a task construct is predetermined as firstprivate}}
+#pragma omp task
+// expected-error at +2 {{reduction variable must be shared}}
+// expected-error at +1 {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}}
+#pragma omp for reduction(+ : r)
+  ++r;
+  return a + b;
+}
+
+int main(int argc, char **argv) {
+  int a;
+  int &b = a; // expected-note 2 {{'b' defined here}}
+  S sa;       // expected-note 3 {{'sa' defined here}}
+  S &sb = sa; // expected-note 2 {{'sb' defined here}}
+  int r;
+#pragma omp task { // expected-warning {{extra tokens at the end of '#pragma omp task' are ignored}}
+  foo();
+#pragma omp task( // expected-warning {{extra tokens at the end of '#pragma omp task' are ignored}}
+  foo();
+#pragma omp task[ // expected-warning {{extra tokens at the end of '#pragma omp task' are ignored}}
+  foo();
+#pragma omp task] // expected-warning {{extra tokens at the end of '#pragma omp task' are ignored}}
+  foo();
+#pragma omp task) // expected-warning {{extra tokens at the end of '#pragma omp task' are ignored}}
+  foo();
+#pragma omp task } // expected-warning {{extra tokens at the end of '#pragma omp task' are ignored}}
+  foo();
+#pragma omp task
+// expected-warning at +1 {{extra tokens at the end of '#pragma omp task' are ignored}}
+#pragma omp task unknown()
+  foo();
+L1:
+  foo();
+#pragma omp task
+  ;
+#pragma omp task
+  {
+    goto L1; // expected-error {{use of undeclared label 'L1'}}
+    argc++;
+  }
+
+  for (int i = 0; i < 10; ++i) {
+    switch (argc) {
+    case (0):
+#pragma omp task
+    {
+      foo();
+      break;    // expected-error {{'break' statement not in loop or switch statement}}
+      continue; // expected-error {{'continue' statement not in loop statement}}
+    }
+    default:
+      break;
+    }
+  }
+#pragma omp task default(none)
+  ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
+
+  goto L2; // expected-error {{use of undeclared label 'L2'}}
+#pragma omp task
+L2:
+  foo();
+#pragma omp task
+  {
+    return 1; // expected-error {{cannot return from OpenMP region}}
+  }
+
+  [[]] // expected-error {{an attribute list cannot appear here}}
+#pragma omp task
+      for (int n = 0; n < 100; ++n) {
+  }
+
+#pragma omp task default(none)
+#pragma omp task default(shared)
+  ++a;
+#pragma omp task default(none)
+#pragma omp task
+  ++a;
+#pragma omp task default(shared)
+#pragma omp task
+  ++a;
+#pragma omp task
+#pragma omp parallel
+  ++a;
+// expected-error at +1 {{predetermined as a firstprivate in a task construct variable cannot be of reference type 'int &'}}
+#pragma omp task
+  // expected-note at +1 {{used here}}
+  ++b;
+// expected-error at +1 {{predetermined as a firstprivate in a task construct variable cannot be of reference type 'int &'}}
+#pragma omp task
+// expected-note at +1 {{used here}}
+#pragma omp parallel shared(a, b)
+  ++a, ++b;
+#pragma omp task default(none)
+#pragma omp task default(shared)
+  ++sa;
+#pragma omp task default(none)
+// expected-error at +1 {{predetermined as a firstprivate in a task construct variable must have an accessible, unambiguous copy constructor}}
+#pragma omp task
+// expected-note at +1 {{used here}}
+  ++sa;
+#pragma omp task
+// expected-error at +1 {{predetermined as a firstprivate in a task construct variable must have an accessible, unambiguous copy constructor}}
+#pragma omp task
+// expected-note at +1 {{used here}}
+  ++sa;
+#pragma omp task default(shared)
+#pragma omp task
+  ++sa;
+#pragma omp task
+#pragma omp parallel
+  ++sa;
+// expected-error at +1 {{predetermined as a firstprivate in a task construct variable cannot be of reference type 'S &'}}
+#pragma omp task
+  // expected-note at +1 {{used here}}
+  ++sb;
+// expected-error at +2 {{predetermined as a firstprivate in a task construct variable cannot be of reference type 'S &'}}
+// expected-error at +1 {{predetermined as a firstprivate in a task construct variable must have an accessible, unambiguous copy constructor}}
+#pragma omp task
+// expected-note at +1 2 {{used here}}
+#pragma omp parallel shared(sa, sb)
+  ++sa, ++sb;
+// expected-note at +1 2 {{defined as reduction}}
+#pragma omp parallel reduction(+ : r)
+// expected-error at +1 {{argument of a reduction clause of a parallel construct must not appear in a firstprivate clause on a task construct}}
+#pragma omp task firstprivate(r)
+  // expected-error at +1 {{reduction variables may not be accessed in an explicit task}}
+  ++r;
+// expected-note at +1 {{defined as reduction}}
+#pragma omp parallel reduction(+ : r)
+#pragma omp task default(shared)
+  // expected-error at +1 {{reduction variables may not be accessed in an explicit task}}
+  ++r;
+// expected-note at +1 {{defined as reduction}}
+#pragma omp parallel reduction(+ : r)
+#pragma omp task
+  // expected-error at +1 {{reduction variables may not be accessed in an explicit task}}
+  ++r;
+#pragma omp parallel
+// expected-note at +1 2 {{defined as reduction}}
+#pragma omp for reduction(+ : r)
+  for (int i = 0; i < 10; ++i)
+// expected-error at +1 {{argument of a reduction clause of a for construct must not appear in a firstprivate clause on a task construct}}
+#pragma omp task firstprivate(r)
+    // expected-error at +1 {{reduction variables may not be accessed in an explicit task}}
+    ++r;
+#pragma omp parallel
+// expected-note at +1 {{defined as reduction}}
+#pragma omp for reduction(+ : r)
+  for (int i = 0; i < 10; ++i)
+#pragma omp task default(shared)
+    // expected-error at +1 {{reduction variables may not be accessed in an explicit task}}
+    ++r;
+#pragma omp parallel
+// expected-note at +1 {{defined as reduction}}
+#pragma omp for reduction(+ : r)
+  for (int i = 0; i < 10; ++i)
+#pragma omp task
+    // expected-error at +1 {{reduction variables may not be accessed in an explicit task}}
+    ++r;
+// expected-note at +1 {{non-shared variable in a task construct is predetermined as firstprivate}}
+#pragma omp task
+// expected-error at +2 {{reduction variable must be shared}}
+// expected-error at +1 {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}}
+#pragma omp for reduction(+ : r)
+  ++r;
+  // expected-note at +2 {{in instantiation of function template specialization 'foo<int>' requested here}}
+  // expected-note at +1 {{in instantiation of function template specialization 'foo<S>' requested here}}
+  return foo<int>() + foo<S>();
+}
+

Propchange: cfe/trunk/test/OpenMP/task_messages.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/OpenMP/task_messages.cpp
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/test/OpenMP/task_messages.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cfe/trunk/test/OpenMP/task_private_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/task_private_messages.cpp?rev=212804&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/task_private_messages.cpp (added)
+++ cfe/trunk/test/OpenMP/task_private_messages.cpp Fri Jul 11 06:25:16 2014
@@ -0,0 +1,85 @@
+// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ferror-limit 100 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+  return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note{{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+  mutable int a;
+
+public:
+  S2() : a(0) {}
+  static float S2s; // expected-note {{static data member is predetermined as shared}}
+};
+const S2 b;
+const S2 ba[5];
+class S3 {
+  int a;
+
+public:
+  S3() : a(0) {}
+};
+const S3 c;         // expected-note {{global variable is predetermined as shared}}
+const S3 ca[5];     // expected-note {{global variable is predetermined as shared}}
+extern const int f; // expected-note {{global variable is predetermined as shared}}
+class S4 {          // expected-note {{'S4' declared here}}
+  int a;
+  S4();
+
+public:
+  S4(int v) : a(v) {}
+};
+class S5 { // expected-note {{'S5' declared here}}
+  int a;
+  S5() : a(0) {}
+
+public:
+  S5(int v) : a(v) {}
+};
+
+int threadvar;
+#pragma omp threadprivate(threadvar) // expected-note {{defined as threadprivate or thread local}}
+
+int main(int argc, char **argv) {
+  const int d = 5;       // expected-note {{constant variable is predetermined as shared}}
+  const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+  S4 e(4);               // expected-note {{'e' defined here}}
+  S5 g(5);               // expected-note {{'g' defined here}}
+  int i;
+  int &j = i;                                          // expected-note {{'j' defined here}}
+#pragma omp task private                               // expected-error {{expected '(' after 'private'}}
+#pragma omp task private(                              // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp task private()                             // expected-error {{expected expression}}
+#pragma omp task private(argc                          // expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp task private(argc,                         // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp task private(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+#pragma omp task private(argc argv)                    // expected-error {{expected ',' or ')' in 'private' clause}}
+#pragma omp task private(S1)                           // expected-error {{'S1' does not refer to a value}}
+#pragma omp task private(a, b, c, d, f)                // expected-error {{a private variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be private}}
+#pragma omp task private(argv[1])                      // expected-error {{expected variable name}}
+#pragma omp task private(ba)
+#pragma omp task private(ca)           // expected-error {{shared variable cannot be private}}
+#pragma omp task private(da)           // expected-error {{shared variable cannot be private}}
+#pragma omp task private(S2::S2s)      // expected-error {{shared variable cannot be private}}
+#pragma omp task private(e, g)         // expected-error 2 {{private variable must have an accessible, unambiguous default constructor}}
+#pragma omp task private(threadvar)    // expected-error {{threadprivate or thread local variable cannot be private}}
+#pragma omp task shared(i), private(i) // expected-error {{shared variable cannot be private}} expected-note {{defined as shared}}
+  foo();
+#pragma omp task firstprivate(i) private(i) // expected-error {{firstprivate variable cannot be private}} expected-note {{defined as firstprivate}}
+  foo();
+#pragma omp task private(i)
+#pragma omp task private(j) // expected-error {{arguments of OpenMP clause 'private' cannot be of reference type 'int &'}}
+  foo();
+#pragma omp task firstprivate(i)
+  for (int k = 0; k < 10; ++k) {
+#pragma omp task private(i)
+    foo();
+  }
+
+  return 0;
+}

Propchange: cfe/trunk/test/OpenMP/task_private_messages.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/OpenMP/task_private_messages.cpp
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/test/OpenMP/task_private_messages.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cfe/trunk/test/OpenMP/task_shared_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/task_shared_messages.cpp?rev=212804&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/task_shared_messages.cpp (added)
+++ cfe/trunk/test/OpenMP/task_shared_messages.cpp Fri Jul 11 06:25:16 2014
@@ -0,0 +1,102 @@
+// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ferror-limit 100 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+  return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+extern S1 a;
+class S2 {
+  mutable int a;
+
+public:
+  S2() : a(0) {}
+  S2(S2 &s2) : a(s2.a) {}
+};
+const S2 b;
+const S2 ba[5];
+class S3 {
+  int a;
+
+public:
+  S3() : a(0) {}
+  S3(S3 &s3) : a(s3.a) {}
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+  int a;
+  S4();
+  S4(const S4 &s4);
+
+public:
+  S4(int v) : a(v) {}
+};
+class S5 {
+  int a;
+  S5() : a(0) {}
+  S5(const S5 &s5) : a(s5.a) {}
+
+public:
+  S5(int v) : a(v) {}
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}}
+
+int main(int argc, char **argv) {
+  const int d = 5;
+  const int da[5] = {0};
+  S4 e(4);
+  S5 g(5);
+  int i;
+  int &j = i;
+#pragma omp task shared                               // expected-error {{expected '(' after 'shared'}}
+  foo();
+#pragma omp task shared(                              // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  foo();
+#pragma omp task shared()                             // expected-error {{expected expression}}
+  foo();
+#pragma omp task shared(argc                          // expected-error {{expected ')'}} expected-note {{to match this '('}}
+  foo();
+#pragma omp task shared(argc,                         // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  foo();
+#pragma omp task shared(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+  foo();
+#pragma omp task shared(argc)
+  foo();
+#pragma omp task shared(S1) // expected-error {{'S1' does not refer to a value}}
+  foo();
+#pragma omp task shared(a, b, c, d, f)
+  foo();
+#pragma omp task shared(argv[1]) // expected-error {{expected variable name}}
+  foo();
+#pragma omp task shared(ba)
+  foo();
+#pragma omp task shared(ca)
+  foo();
+#pragma omp task shared(da)
+  foo();
+#pragma omp task shared(e, g)
+  foo();
+#pragma omp task shared(h)             // expected-error {{threadprivate or thread local variable cannot be shared}}
+  foo();
+#pragma omp task private(i), shared(i) // expected-error {{private variable cannot be shared}} expected-note {{defined as private}}
+  foo();
+#pragma omp task firstprivate(i), shared(i) // expected-error {{firstprivate variable cannot be shared}} expected-note {{defined as firstprivate}}
+  foo();
+#pragma omp parallel private(i)
+#pragma omp task shared(i)
+#pragma omp task shared(j)
+  foo();
+#pragma omp parallel firstprivate(i)
+#pragma omp task shared(i)
+#pragma omp task shared(j)
+  foo();
+
+  return 0;
+}

Propchange: cfe/trunk/test/OpenMP/task_shared_messages.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/OpenMP/task_shared_messages.cpp
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/test/OpenMP/task_shared_messages.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=212804&r1=212803&r2=212804&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Fri Jul 11 06:25:16 2014
@@ -1862,6 +1862,7 @@ public:
   void VisitOMPSingleDirective(const OMPSingleDirective *D);
   void VisitOMPParallelForDirective(const OMPParallelForDirective *D);
   void VisitOMPParallelSectionsDirective(const OMPParallelSectionsDirective *D);
+  void VisitOMPTaskDirective(const OMPTaskDirective *D);
 
 private:
   void AddDeclarationNameInfo(const Stmt *S);
@@ -2323,6 +2324,10 @@ void EnqueueVisitor::VisitOMPParallelSec
   VisitOMPExecutableDirective(D);
 }
 
+void EnqueueVisitor::VisitOMPTaskDirective(const OMPTaskDirective *D) {
+  VisitOMPExecutableDirective(D);
+}
+
 void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, const Stmt *S) {
   EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU,RegionOfInterest)).Visit(S);
 }
@@ -4011,6 +4016,8 @@ CXString clang_getCursorKindSpelling(enu
     return cxstring::createRef("OMPParallelForDirective");
   case CXCursor_OMPParallelSectionsDirective:
     return cxstring::createRef("OMPParallelSectionsDirective");
+  case CXCursor_OMPTaskDirective:
+    return cxstring::createRef("OMPTaskDirective");
   }
 
   llvm_unreachable("Unhandled CXCursorKind");

Modified: cfe/trunk/tools/libclang/CXCursor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=212804&r1=212803&r2=212804&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXCursor.cpp (original)
+++ cfe/trunk/tools/libclang/CXCursor.cpp Fri Jul 11 06:25:16 2014
@@ -541,6 +541,9 @@ CXCursor cxcursor::MakeCXCursor(const St
   case Stmt::OMPParallelSectionsDirectiveClass:
     K = CXCursor_OMPParallelSectionsDirective;
     break;
+  case Stmt::OMPTaskDirectiveClass:
+    K = CXCursor_OMPTaskDirective;
+    break;
   }
 
   CXCursor C = { K, 0, { Parent, S, TU } };





More information about the cfe-commits mailing list