<div dir="ltr"><div>I have reviewed this while reviewing: <br><h2>r212516 - [OPENMP] Parsing and sema analysis for 'omp parallel sections' directive.</h2><span><table cellpadding="0">
<tbody><tr><td style="background-color:rgb(221,221,221);color:rgb(102,102,102)"><br></td><td style="background-color:rgb(221,221,221);color:rgb(102,102,102)"><br></td></tr></tbody></table></span><br>
</div>All the code is a similar pattern and looks good.</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Fri, Jun 27, 2014 at 6:37 AM, Alexey Bataev <span dir="ltr"><<a href="mailto:a.bataev@hotmail.com" target="_blank">a.bataev@hotmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: abataev<br>
Date: Fri Jun 27 05:37:06 2014<br>
New Revision: 211886<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=211886&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=211886&view=rev</a><br>
Log:<br>
[OPENMP] Parsing and sema analysis for 'copyprivate' clause.<br>
<br>
Added:<br>
    cfe/trunk/test/OpenMP/single_copyprivate_messages.cpp   (with props)<br>
Modified:<br>
    cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h<br>
    cfe/trunk/include/clang/AST/OpenMPClause.h<br>
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h<br>
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
    cfe/trunk/include/clang/Basic/OpenMPKinds.def<br>
    cfe/trunk/include/clang/Sema/Sema.h<br>
    cfe/trunk/lib/AST/Stmt.cpp<br>
    cfe/trunk/lib/AST/StmtPrinter.cpp<br>
    cfe/trunk/lib/AST/StmtProfile.cpp<br>
    cfe/trunk/lib/Basic/OpenMPKinds.cpp<br>
    cfe/trunk/lib/Parse/ParseOpenMP.cpp<br>
    cfe/trunk/lib/Sema/SemaOpenMP.cpp<br>
    cfe/trunk/lib/Sema/TreeTransform.h<br>
    cfe/trunk/lib/Serialization/ASTReaderStmt.cpp<br>
    cfe/trunk/lib/Serialization/ASTWriterStmt.cpp<br>
    cfe/trunk/test/OpenMP/single_ast_print.cpp<br>
    cfe/trunk/tools/libclang/CIndex.cpp<br>
<br>
Modified: cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h?rev=211886&r1=211885&r2=211886&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h?rev=211886&r1=211885&r2=211886&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h (original)<br>
+++ cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h Fri Jun 27 05:37:06 2014<br>
@@ -2434,6 +2434,13 @@ bool RecursiveASTVisitor<Derived>::Visit<br>
 }<br>
<br>
 template <typename Derived><br>
+bool RecursiveASTVisitor<Derived>::VisitOMPCopyprivateClause(<br>
+    OMPCopyprivateClause *C) {<br>
+  VisitOMPClauseList(C);<br>
+  return true;<br>
+}<br>
+<br>
+template <typename Derived><br>
 bool<br>
 RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) {<br>
   TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc()));<br>
<br>
Modified: cfe/trunk/include/clang/AST/OpenMPClause.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/OpenMPClause.h?rev=211886&r1=211885&r2=211886&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/OpenMPClause.h?rev=211886&r1=211885&r2=211886&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/AST/OpenMPClause.h (original)<br>
+++ cfe/trunk/include/clang/AST/OpenMPClause.h Fri Jun 27 05:37:06 2014<br>
@@ -1218,6 +1218,66 @@ public:<br>
   }<br>
 };<br>
<br>
+/// \brief This represents clause 'copyprivate' in the '#pragma omp ...'<br>
+/// directives.<br>
+///<br>
+/// \code<br>
+/// #pragma omp single copyprivate(a,b)<br>
+/// \endcode<br>
+/// In this example directive '#pragma omp single' has clause 'copyprivate'<br>
+/// with the variables 'a' and 'b'.<br>
+///<br>
+class OMPCopyprivateClause : public OMPVarListClause<OMPCopyprivateClause> {<br>
+  /// \brief Build clause with number of variables \a N.<br>
+  ///<br>
+  /// \param StartLoc Starting location of the clause.<br>
+  /// \param LParenLoc Location of '('.<br>
+  /// \param EndLoc Ending location of the clause.<br>
+  /// \param N Number of the variables in the clause.<br>
+  ///<br>
+  OMPCopyprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc,<br>
+                       SourceLocation EndLoc, unsigned N)<br>
+      : OMPVarListClause<OMPCopyprivateClause>(OMPC_copyprivate, StartLoc,<br>
+                                               LParenLoc, EndLoc, N) {}<br>
+<br>
+  /// \brief Build an empty clause.<br>
+  ///<br>
+  /// \param N Number of variables.<br>
+  ///<br>
+  explicit OMPCopyprivateClause(unsigned N)<br>
+      : OMPVarListClause<OMPCopyprivateClause>(<br>
+            OMPC_copyprivate, SourceLocation(), SourceLocation(),<br>
+            SourceLocation(), N) {}<br>
+<br>
+public:<br>
+  /// \brief Creates clause with a list of variables \a VL.<br>
+  ///<br>
+  /// \param C AST context.<br>
+  /// \param StartLoc Starting location of the clause.<br>
+  /// \param LParenLoc Location of '('.<br>
+  /// \param EndLoc Ending location of the clause.<br>
+  /// \param VL List of references to the variables.<br>
+  ///<br>
+  static OMPCopyprivateClause *<br>
+  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,<br>
+         SourceLocation EndLoc, ArrayRef<Expr *> VL);<br>
+  /// \brief Creates an empty clause with \a N variables.<br>
+  ///<br>
+  /// \param C AST context.<br>
+  /// \param N The number of variables.<br>
+  ///<br>
+  static OMPCopyprivateClause *CreateEmpty(const ASTContext &C, unsigned N);<br>
+<br>
+  StmtRange children() {<br>
+    return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),<br>
+                     reinterpret_cast<Stmt **>(varlist_end()));<br>
+  }<br>
+<br>
+  static bool classof(const OMPClause *T) {<br>
+    return T->getClauseKind() == OMPC_copyprivate;<br>
+  }<br>
+};<br>
+<br>
 } // end namespace clang<br>
<br>
 #endif<br>
<br>
Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=211886&r1=211885&r2=211886&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=211886&r1=211885&r2=211886&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)<br>
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Fri Jun 27 05:37:06 2014<br>
@@ -2456,6 +2456,13 @@ bool RecursiveASTVisitor<Derived>::Visit<br>
 }<br>
<br>
 template <typename Derived><br>
+bool RecursiveASTVisitor<Derived>::VisitOMPCopyprivateClause(<br>
+    OMPCopyprivateClause *C) {<br>
+  VisitOMPClauseList(C);<br>
+  return true;<br>
+}<br>
+<br>
+template <typename Derived><br>
 bool<br>
 RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) {<br>
   TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc()));<br>
<br>
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=211886&r1=211885&r2=211886&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=211886&r1=211885&r2=211886&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Jun 27 05:37:06 2014<br>
@@ -7026,6 +7026,8 @@ def note_omp_predetermined_dsa : Note<<br>
   "global variable is predetermined as shared|"<br>
   "variable with automatic storage duration is predetermined as private}0"<br>
   "%select{|; perhaps you forget to enclose 'omp %2' directive into a parallel or another task region?}1">;<br>
+def note_omp_implicit_dsa : Note<<br>
+  "implicitly determined as %0">;<br>
 def err_omp_loop_var_dsa : Error<<br>
   "loop iteration variable may not be %0">;<br>
 def err_omp_not_for : Error<<br>
<br>
Modified: cfe/trunk/include/clang/Basic/OpenMPKinds.def<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/OpenMPKinds.def?rev=211886&r1=211885&r2=211886&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/OpenMPKinds.def?rev=211886&r1=211885&r2=211886&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/Basic/OpenMPKinds.def (original)<br>
+++ cfe/trunk/include/clang/Basic/OpenMPKinds.def Fri Jun 27 05:37:06 2014<br>
@@ -67,6 +67,7 @@ OPENMP_CLAUSE(reduction,  OMPReductionCl<br>
 OPENMP_CLAUSE(linear,  OMPLinearClause)<br>
 OPENMP_CLAUSE(aligned, OMPAlignedClause)<br>
 OPENMP_CLAUSE(copyin,  OMPCopyinClause)<br>
+OPENMP_CLAUSE(copyprivate,  OMPCopyprivateClause)<br>
 OPENMP_CLAUSE(proc_bind, OMPProcBindClause)<br>
 OPENMP_CLAUSE(schedule, OMPScheduleClause)<br>
 OPENMP_CLAUSE(ordered, OMPOrderedClause)<br>
@@ -111,6 +112,7 @@ OPENMP_SECTIONS_CLAUSE(nowait)<br>
 // TODO more clauses allowed for directive 'omp single'.<br>
 OPENMP_SINGLE_CLAUSE(private)<br>
 OPENMP_SINGLE_CLAUSE(firstprivate)<br>
+OPENMP_SINGLE_CLAUSE(copyprivate)<br>
 OPENMP_SINGLE_CLAUSE(nowait)<br>
<br>
 // Static attributes for 'default' clause.<br>
<br>
Modified: cfe/trunk/include/clang/Sema/Sema.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=211886&r1=211885&r2=211886&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=211886&r1=211885&r2=211886&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/Sema/Sema.h (original)<br>
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Jun 27 05:37:06 2014<br>
@@ -7279,8 +7279,8 @@ public:<br>
                                                     Expr *Op);<br>
   /// \brief Called on start of new data sharing attribute block.<br>
   void StartOpenMPDSABlock(OpenMPDirectiveKind K,<br>
-                           const DeclarationNameInfo &DirName,<br>
-                           Scope *CurScope);<br>
+                           const DeclarationNameInfo &DirName, Scope *CurScope,<br>
+                           SourceLocation Loc);<br>
   /// \brief Called on end of data sharing attribute block.<br>
   void EndOpenMPDSABlock(Stmt *CurDirective);<br>
<br>
@@ -7300,8 +7300,7 @@ public:<br>
                                      ArrayRef<Expr *> VarList);<br>
<br>
   // brief Initialization of captured region for OpenMP region.<br>
-  void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, SourceLocation Loc,<br>
-                              Scope *CurScope);<br>
+  void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope);<br>
   StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,<br>
                                             ArrayRef<OMPClause *> Clauses,<br>
                                             Stmt *AStmt,<br>
@@ -7460,6 +7459,11 @@ public:<br>
                                      SourceLocation StartLoc,<br>
                                      SourceLocation LParenLoc,<br>
                                      SourceLocation EndLoc);<br>
+  /// \brief Called on well-formed 'copyprivate' clause.<br>
+  OMPClause *ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,<br>
+                                          SourceLocation StartLoc,<br>
+                                          SourceLocation LParenLoc,<br>
+                                          SourceLocation EndLoc);<br>
<br>
   /// \brief The kind of conversion being performed.<br>
   enum CheckedConversionKind {<br>
<br>
Modified: cfe/trunk/lib/AST/Stmt.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Stmt.cpp?rev=211886&r1=211885&r2=211886&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Stmt.cpp?rev=211886&r1=211885&r2=211886&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/AST/Stmt.cpp (original)<br>
+++ cfe/trunk/lib/AST/Stmt.cpp Fri Jun 27 05:37:06 2014<br>
@@ -1280,6 +1280,28 @@ OMPCopyinClause *OMPCopyinClause::Create<br>
   return new (Mem) OMPCopyinClause(N);<br>
 }<br>
<br>
+OMPCopyprivateClause *OMPCopyprivateClause::Create(const ASTContext &C,<br>
+                                                   SourceLocation StartLoc,<br>
+                                                   SourceLocation LParenLoc,<br>
+                                                   SourceLocation EndLoc,<br>
+                                                   ArrayRef<Expr *> VL) {<br>
+  void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyprivateClause),<br>
+                                                  llvm::alignOf<Expr *>()) +<br>
+                         sizeof(Expr *) * VL.size());<br>
+  OMPCopyprivateClause *Clause =<br>
+      new (Mem) OMPCopyprivateClause(StartLoc, LParenLoc, EndLoc, VL.size());<br>
+  Clause->setVarRefs(VL);<br>
+  return Clause;<br>
+}<br>
+<br>
+OMPCopyprivateClause *OMPCopyprivateClause::CreateEmpty(const ASTContext &C,<br>
+                                                        unsigned N) {<br>
+  void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyprivateClause),<br>
+                                                  llvm::alignOf<Expr *>()) +<br>
+                         sizeof(Expr *) * N);<br>
+  return new (Mem) OMPCopyprivateClause(N);<br>
+}<br>
+<br>
 void OMPExecutableDirective::setClauses(ArrayRef<OMPClause *> Clauses) {<br>
   assert(Clauses.size() == getNumClauses() &&<br>
          "Number of clauses is not the same as the preallocated buffer");<br>
<br>
Modified: cfe/trunk/lib/AST/StmtPrinter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=211886&r1=211885&r2=211886&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=211886&r1=211885&r2=211886&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)<br>
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Fri Jun 27 05:37:06 2014<br>
@@ -748,6 +748,14 @@ void OMPClausePrinter::VisitOMPCopyinCla<br>
   }<br>
 }<br>
<br>
+void OMPClausePrinter::VisitOMPCopyprivateClause(OMPCopyprivateClause *Node) {<br>
+  if (!Node->varlist_empty()) {<br>
+    OS << "copyprivate";<br>
+    VisitOMPClauseList(Node, '(');<br>
+    OS << ")";<br>
+  }<br>
+}<br>
+<br>
 }<br>
<br>
 //===----------------------------------------------------------------------===//<br>
<br>
Modified: cfe/trunk/lib/AST/StmtProfile.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=211886&r1=211885&r2=211886&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=211886&r1=211885&r2=211886&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/AST/StmtProfile.cpp (original)<br>
+++ cfe/trunk/lib/AST/StmtProfile.cpp Fri Jun 27 05:37:06 2014<br>
@@ -335,6 +335,10 @@ void OMPClauseProfiler::VisitOMPAlignedC<br>
 void OMPClauseProfiler::VisitOMPCopyinClause(const OMPCopyinClause *C) {<br>
   VisitOMPClauseList(C);<br>
 }<br>
+void<br>
+OMPClauseProfiler::VisitOMPCopyprivateClause(const OMPCopyprivateClause *C) {<br>
+  VisitOMPClauseList(C);<br>
+}<br>
 }<br>
<br>
 void<br>
<br>
Modified: cfe/trunk/lib/Basic/OpenMPKinds.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/OpenMPKinds.cpp?rev=211886&r1=211885&r2=211886&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/OpenMPKinds.cpp?rev=211886&r1=211885&r2=211886&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Basic/OpenMPKinds.cpp (original)<br>
+++ cfe/trunk/lib/Basic/OpenMPKinds.cpp Fri Jun 27 05:37:06 2014<br>
@@ -95,6 +95,7 @@ unsigned clang::getOpenMPSimpleClauseTyp<br>
   case OMPC_linear:<br>
   case OMPC_aligned:<br>
   case OMPC_copyin:<br>
+  case OMPC_copyprivate:<br>
   case OMPC_ordered:<br>
   case OMPC_nowait:<br>
     break;<br>
@@ -149,6 +150,7 @@ const char *clang::getOpenMPSimpleClause<br>
   case OMPC_linear:<br>
   case OMPC_aligned:<br>
   case OMPC_copyin:<br>
+  case OMPC_copyprivate:<br>
   case OMPC_ordered:<br>
   case OMPC_nowait:<br>
     break;<br>
@@ -193,7 +195,7 @@ bool clang::isAllowedClauseForDirective(<br>
     break;<br>
   case OMPD_sections:<br>
     switch (CKind) {<br>
-#define OPENMP_SECTIONS_CLAUSE(Name)                                                \<br>
+#define OPENMP_SECTIONS_CLAUSE(Name)                                           \<br>
   case OMPC_##Name:                                                            \<br>
     return true;<br>
 #include "clang/Basic/OpenMPKinds.def"<br>
@@ -203,7 +205,7 @@ bool clang::isAllowedClauseForDirective(<br>
     break;<br>
   case OMPD_single:<br>
     switch (CKind) {<br>
-#define OPENMP_SINGLE_CLAUSE(Name)                                                \<br>
+#define OPENMP_SINGLE_CLAUSE(Name)                                             \<br>
   case OMPC_##Name:                                                            \<br>
     return true;<br>
 #include "clang/Basic/OpenMPKinds.def"<br>
<br>
Modified: cfe/trunk/lib/Parse/ParseOpenMP.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseOpenMP.cpp?rev=211886&r1=211885&r2=211886&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseOpenMP.cpp?rev=211886&r1=211885&r2=211886&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Parse/ParseOpenMP.cpp (original)<br>
+++ cfe/trunk/lib/Parse/ParseOpenMP.cpp Fri Jun 27 05:37:06 2014<br>
@@ -131,7 +131,7 @@ StmtResult Parser::ParseOpenMPDeclarativ<br>
     if (isOpenMPSimdDirective(DKind))<br>
       ScopeFlags |= Scope::OpenMPSimdDirectiveScope;<br>
     ParseScope OMPDirectiveScope(this, ScopeFlags);<br>
-    Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope());<br>
+    Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);<br>
<br>
     while (Tok.isNot(tok::annot_pragma_openmp_end)) {<br>
       OpenMPClauseKind CKind = Tok.isAnnotation()<br>
@@ -159,7 +159,7 @@ StmtResult Parser::ParseOpenMPDeclarativ<br>
     {<br>
       // The body is a block scope like in Lambdas and Blocks.<br>
       Sema::CompoundScopeRAII CompoundScope(Actions);<br>
-      Actions.ActOnOpenMPRegionStart(DKind, Loc, getCurScope());<br>
+      Actions.ActOnOpenMPRegionStart(DKind, getCurScope());<br>
       Actions.ActOnStartOfCompoundStmt();<br>
       // Parse statement<br>
       AssociatedStmt = ParseStatement();<br>
@@ -269,7 +269,8 @@ bool Parser::ParseOpenMPSimpleVarList(Op<br>
 ///       if-clause | num_threads-clause | safelen-clause | default-clause |<br>
 ///       private-clause | firstprivate-clause | shared-clause | linear-clause |<br>
 ///       aligned-clause | collapse-clause | lastprivate-clause |<br>
-///       reduction-clause | proc_bind-clause | schedule-clause<br>
+///       reduction-clause | proc_bind-clause | schedule-clause |<br>
+///       copyin-clause | copyprivate-clause<br>
 ///<br>
 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,<br>
                                      OpenMPClauseKind CKind, bool FirstClause) {<br>
@@ -345,6 +346,7 @@ OMPClause *Parser::ParseOpenMPClause(Ope<br>
   case OMPC_linear:<br>
   case OMPC_aligned:<br>
   case OMPC_copyin:<br>
+  case OMPC_copyprivate:<br>
     Clause = ParseOpenMPVarListClause(CKind);<br>
     break;<br>
   case OMPC_unknown:<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=211886&r1=211885&r2=211886&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=211886&r1=211885&r2=211886&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Fri Jun 27 05:37:06 2014<br>
@@ -68,7 +68,10 @@ public:<br>
     OpenMPDirectiveKind DKind;<br>
     OpenMPClauseKind CKind;<br>
     DeclRefExpr *RefExpr;<br>
-    DSAVarData() : DKind(OMPD_unknown), CKind(OMPC_unknown), RefExpr(nullptr) {}<br>
+    SourceLocation ImplicitDSALoc;<br>
+    DSAVarData()<br>
+        : DKind(OMPD_unknown), CKind(OMPC_unknown), RefExpr(nullptr),<br>
+          ImplicitDSALoc() {}<br>
   };<br>
<br>
 private:<br>
@@ -83,17 +86,20 @@ private:<br>
     DeclSAMapTy SharingMap;<br>
     AlignedMapTy AlignedMap;<br>
     DefaultDataSharingAttributes DefaultAttr;<br>
+    SourceLocation DefaultAttrLoc;<br>
     OpenMPDirectiveKind Directive;<br>
     DeclarationNameInfo DirectiveName;<br>
     Scope *CurScope;<br>
+    SourceLocation ConstructLoc;<br>
     SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,<br>
-                 Scope *CurScope)<br>
+                 Scope *CurScope, SourceLocation Loc)<br>
         : SharingMap(), AlignedMap(), DefaultAttr(DSA_unspecified),<br>
-          Directive(DKind), DirectiveName(std::move(Name)), CurScope(CurScope) {<br>
-    }<br>
+          Directive(DKind), DirectiveName(std::move(Name)), CurScope(CurScope),<br>
+          ConstructLoc(Loc) {}<br>
     SharingMapTy()<br>
         : SharingMap(), AlignedMap(), DefaultAttr(DSA_unspecified),<br>
-          Directive(OMPD_unknown), DirectiveName(), CurScope(nullptr) {}<br>
+          Directive(OMPD_unknown), DirectiveName(), CurScope(nullptr),<br>
+          ConstructLoc() {}<br>
   };<br>
<br>
   typedef SmallVector<SharingMapTy, 64> StackTy;<br>
@@ -113,8 +119,9 @@ public:<br>
   explicit DSAStackTy(Sema &S) : Stack(1), SemaRef(S) {}<br>
<br>
   void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,<br>
-            Scope *CurScope) {<br>
-    Stack.push_back(SharingMapTy(DKind, DirName, CurScope));<br>
+            Scope *CurScope, SourceLocation Loc) {<br>
+    Stack.push_back(SharingMapTy(DKind, DirName, CurScope, Loc));<br>
+    Stack.back().DefaultAttrLoc = Loc;<br>
   }<br>
<br>
   void pop() {<br>
@@ -160,13 +167,22 @@ public:<br>
   }<br>
<br>
   /// \brief Set default data sharing attribute to none.<br>
-  void setDefaultDSANone() { Stack.back().DefaultAttr = DSA_none; }<br>
+  void setDefaultDSANone(SourceLocation Loc) {<br>
+    Stack.back().DefaultAttr = DSA_none;<br>
+    Stack.back().DefaultAttrLoc = Loc;<br>
+  }<br>
   /// \brief Set default data sharing attribute to shared.<br>
-  void setDefaultDSAShared() { Stack.back().DefaultAttr = DSA_shared; }<br>
+  void setDefaultDSAShared(SourceLocation Loc) {<br>
+    Stack.back().DefaultAttr = DSA_shared;<br>
+    Stack.back().DefaultAttrLoc = Loc;<br>
+  }<br>
<br>
   DefaultDataSharingAttributes getDefaultDSA() const {<br>
     return Stack.back().DefaultAttr;<br>
   }<br>
+  SourceLocation getDefaultDSALocation() const {<br>
+    return Stack.back().DefaultAttrLoc;<br>
+  }<br>
<br>
   /// \brief Checks if the specified variable is a threadprivate.<br>
   bool isThreadPrivate(VarDecl *D) {<br>
@@ -176,6 +192,7 @@ public:<br>
<br>
   Scope *getCurScope() const { return Stack.back().CurScope; }<br>
   Scope *getCurScope() { return Stack.back().CurScope; }<br>
+  SourceLocation getConstructLoc() { return Stack.back().ConstructLoc; }<br>
 };<br>
 } // namespace<br>
<br>
@@ -227,6 +244,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDS<br>
   switch (Iter->DefaultAttr) {<br>
   case DSA_shared:<br>
     DVar.CKind = OMPC_shared;<br>
+    DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;<br>
     return DVar;<br>
   case DSA_none:<br>
     return DVar;<br>
@@ -235,6 +253,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDS<br>
     // in a Construct, implicitly determined, p.2]<br>
     //  In a parallel construct, if no default clause is present, these<br>
     //  variables are shared.<br>
+    DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;<br>
     if (isOpenMPParallelDirective(DVar.DKind)) {<br>
       DVar.CKind = OMPC_shared;<br>
       return DVar;<br>
@@ -456,8 +475,8 @@ void Sema::DestroyDataSharingAttributesS<br>
<br>
 void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,<br>
                                const DeclarationNameInfo &DirName,<br>
-                               Scope *CurScope) {<br>
-  DSAStack->push(DKind, DirName, CurScope);<br>
+                               Scope *CurScope, SourceLocation Loc) {<br>
+  DSAStack->push(DKind, DirName, CurScope, Loc);<br>
   PushExpressionEvaluationContext(PotentiallyEvaluated);<br>
 }<br>
<br>
@@ -776,8 +795,9 @@ static void ReportOriginalDSA(Sema &Sema<br>
     PDSA_LoopIterVarLastprivate,<br>
     PDSA_ConstVarShared,<br>
     PDSA_GlobalVarShared,<br>
-    PDSA_LocalVarPrivate<br>
-  } Reason;<br>
+    PDSA_LocalVarPrivate,<br>
+    PDSA_Implicit<br>
+  } Reason = PDSA_Implicit;<br>
   bool ReportHint = false;<br>
   if (IsLoopIterVar) {<br>
     if (DVar.CKind == OMPC_private)<br>
@@ -794,14 +814,18 @@ static void ReportOriginalDSA(Sema &Sema<br>
     Reason = PDSA_GlobalVarShared;<br>
   else if (VD->getType().isConstant(SemaRef.getASTContext()))<br>
     Reason = PDSA_ConstVarShared;<br>
-  else {<br>
+  else if (VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {<br>
     ReportHint = true;<br>
     Reason = PDSA_LocalVarPrivate;<br>
   }<br>
-<br>
-  SemaRef.Diag(VD->getLocation(), diag::note_omp_predetermined_dsa)<br>
-      << Reason << ReportHint<br>
-      << getOpenMPDirectiveName(Stack->getCurrentDirective());<br>
+  if (Reason != PDSA_Implicit) {<br>
+    SemaRef.Diag(VD->getLocation(), diag::note_omp_predetermined_dsa)<br>
+        << Reason << ReportHint<br>
+        << getOpenMPDirectiveName(Stack->getCurrentDirective());<br>
+  } else if (DVar.ImplicitDSALoc.isValid()) {<br>
+    SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)<br>
+        << getOpenMPClauseName(DVar.CKind);<br>
+  }<br>
 }<br>
<br>
 namespace {<br>
@@ -882,8 +906,7 @@ public:<br>
 };<br>
 } // namespace<br>
<br>
-void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, SourceLocation Loc,<br>
-                                  Scope *CurScope) {<br>
+void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {<br>
   switch (DKind) {<br>
   case OMPD_parallel: {<br>
     QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);<br>
@@ -893,42 +916,48 @@ void Sema::ActOnOpenMPRegionStart(OpenMP<br>
         std::make_pair(".bound_tid.", KmpInt32PtrTy),<br>
         std::make_pair(StringRef(), QualType()) // __context with shared vars<br>
     };<br>
-    ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, Params);<br>
+    ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,<br>
+                             Params);<br>
     break;<br>
   }<br>
   case OMPD_simd: {<br>
     Sema::CapturedParamNameType Params[] = {<br>
         std::make_pair(StringRef(), QualType()) // __context with shared vars<br>
     };<br>
-    ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, Params);<br>
+    ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,<br>
+                             Params);<br>
     break;<br>
   }<br>
   case OMPD_for: {<br>
     Sema::CapturedParamNameType Params[] = {<br>
         std::make_pair(StringRef(), QualType()) // __context with shared vars<br>
     };<br>
-    ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, Params);<br>
+    ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,<br>
+                             Params);<br>
     break;<br>
   }<br>
   case OMPD_sections: {<br>
     Sema::CapturedParamNameType Params[] = {<br>
         std::make_pair(StringRef(), QualType()) // __context with shared vars<br>
     };<br>
-    ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, Params);<br>
+    ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,<br>
+                             Params);<br>
     break;<br>
   }<br>
   case OMPD_section: {<br>
     Sema::CapturedParamNameType Params[] = {<br>
         std::make_pair(StringRef(), QualType()) // __context with shared vars<br>
     };<br>
-    ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, Params);<br>
+    ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,<br>
+                             Params);<br>
     break;<br>
   }<br>
   case OMPD_single: {<br>
     Sema::CapturedParamNameType Params[] = {<br>
         std::make_pair(StringRef(), QualType()) // __context with shared vars<br>
     };<br>
-    ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, Params);<br>
+    ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,<br>
+                             Params);<br>
     break;<br>
   }<br>
   case OMPD_threadprivate:<br>
@@ -1695,6 +1724,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprCl<br>
   case OMPC_linear:<br>
   case OMPC_aligned:<br>
   case OMPC_copyin:<br>
+  case OMPC_copyprivate:<br>
   case OMPC_ordered:<br>
   case OMPC_nowait:<br>
   case OMPC_threadprivate:<br>
@@ -1874,6 +1904,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause<br>
   case OMPC_linear:<br>
   case OMPC_aligned:<br>
   case OMPC_copyin:<br>
+  case OMPC_copyprivate:<br>
   case OMPC_ordered:<br>
   case OMPC_nowait:<br>
   case OMPC_threadprivate:<br>
@@ -1914,10 +1945,10 @@ OMPClause *Sema::ActOnOpenMPDefaultClaus<br>
   }<br>
   switch (Kind) {<br>
   case OMPC_DEFAULT_none:<br>
-    DSAStack->setDefaultDSANone();<br>
+    DSAStack->setDefaultDSANone(KindKwLoc);<br>
     break;<br>
   case OMPC_DEFAULT_shared:<br>
-    DSAStack->setDefaultDSAShared();<br>
+    DSAStack->setDefaultDSAShared(KindKwLoc);<br>
     break;<br>
   case OMPC_DEFAULT_unknown:<br>
     llvm_unreachable("Clause kind is not allowed.");<br>
@@ -1984,6 +2015,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWi<br>
   case OMPC_linear:<br>
   case OMPC_aligned:<br>
   case OMPC_copyin:<br>
+  case OMPC_copyprivate:<br>
   case OMPC_ordered:<br>
   case OMPC_nowait:<br>
   case OMPC_threadprivate:<br>
@@ -2073,6 +2105,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenM<br>
   case OMPC_linear:<br>
   case OMPC_aligned:<br>
   case OMPC_copyin:<br>
+  case OMPC_copyprivate:<br>
   case OMPC_default:<br>
   case OMPC_proc_bind:<br>
   case OMPC_threadprivate:<br>
@@ -2126,6 +2159,9 @@ OMPClause *Sema::ActOnOpenMPVarListClaus<br>
   case OMPC_copyin:<br>
     Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);<br>
     break;<br>
+  case OMPC_copyprivate:<br>
+    Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);<br>
+    break;<br>
   case OMPC_if:<br>
   case OMPC_num_threads:<br>
   case OMPC_safelen:<br>
@@ -3281,4 +3317,108 @@ OMPClause *Sema::ActOnOpenMPCopyinClause<br>
   return OMPCopyinClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);<br>
 }<br>
<br>
+OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,<br>
+                                              SourceLocation StartLoc,<br>
+                                              SourceLocation LParenLoc,<br>
+                                              SourceLocation EndLoc) {<br>
+  SmallVector<Expr *, 8> Vars;<br>
+  for (auto &RefExpr : VarList) {<br>
+    assert(RefExpr && "NULL expr in OpenMP copyprivate clause.");<br>
+    if (isa<DependentScopeDeclRefExpr>(RefExpr)) {<br>
+      // It will be analyzed later.<br>
+      Vars.push_back(RefExpr);<br>
+      continue;<br>
+    }<br>
+<br>
+    SourceLocation ELoc = RefExpr->getExprLoc();<br>
+    // OpenMP [2.1, C/C++]<br>
+    //  A list item is a variable name.<br>
+    // OpenMP  [2.14.4.1, Restrictions, p.1]<br>
+    //  A list item that appears in a copyin clause must be threadprivate.<br>
+    DeclRefExpr *DE = dyn_cast<DeclRefExpr>(RefExpr);<br>
+    if (!DE || !isa<VarDecl>(DE->getDecl())) {<br>
+      Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange();<br>
+      continue;<br>
+    }<br>
+<br>
+    Decl *D = DE->getDecl();<br>
+    VarDecl *VD = cast<VarDecl>(D);<br>
+<br>
+    QualType Type = VD->getType();<br>
+    if (Type->isDependentType() || Type->isInstantiationDependentType()) {<br>
+      // It will be analyzed later.<br>
+      Vars.push_back(DE);<br>
+      continue;<br>
+    }<br>
+<br>
+    // OpenMP [2.14.4.2, Restrictions, p.2]<br>
+    //  A list item that appears in a copyprivate clause may not appear in a<br>
+    //  private or firstprivate clause on the single construct.<br>
+    if (!DSAStack->isThreadPrivate(VD)) {<br>
+      auto DVar = DSAStack->getTopDSA(VD);<br>
+      if (DVar.CKind != OMPC_copyprivate && DVar.CKind != OMPC_unknown &&<br>
+          !(DVar.CKind == OMPC_private && !DVar.RefExpr)) {<br>
+        Diag(ELoc, diag::err_omp_wrong_dsa)<br>
+            << getOpenMPClauseName(DVar.CKind)<br>
+            << getOpenMPClauseName(OMPC_copyprivate);<br>
+        ReportOriginalDSA(*this, DSAStack, VD, DVar);<br>
+        continue;<br>
+      }<br>
+<br>
+      // OpenMP [2.11.4.2, Restrictions, p.1]<br>
+      //  All list items that appear in a copyprivate clause must be either<br>
+      //  threadprivate or private in the enclosing context.<br>
+      if (DVar.CKind == OMPC_unknown) {<br>
+        DVar = DSAStack->getImplicitDSA(VD);<br>
+        if (DVar.CKind == OMPC_shared) {<br>
+          Diag(ELoc, diag::err_omp_required_access)<br>
+              << getOpenMPClauseName(OMPC_copyprivate)<br>
+              << "threadprivate or private in the enclosing context";<br>
+          ReportOriginalDSA(*this, DSAStack, VD, DVar);<br>
+          continue;<br>
+        }<br>
+      }<br>
+    }<br>
+<br>
+    // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]<br>
+    //  A variable of class type (or array thereof) that appears in a<br>
+    //  copyin clause requires an accessible, unambiguous copy assignment<br>
+    //  operator for the class type.<br>
+    Type = Context.getBaseElementType(Type);<br>
+    CXXRecordDecl *RD =<br>
+        getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr;<br>
+    // FIXME This code must be replaced by actual assignment of the<br>
+    // threadprivate variable.<br>
+    if (RD) {<br>
+      CXXMethodDecl *MD = LookupCopyingAssignment(RD, 0, false, 0);<br>
+      DeclAccessPair FoundDecl = DeclAccessPair::make(MD, MD->getAccess());<br>
+      if (MD) {<br>
+        if (CheckMemberAccess(ELoc, RD, FoundDecl) == AR_inaccessible ||<br>
+            MD->isDeleted()) {<br>
+          Diag(ELoc, diag::err_omp_required_method)<br>
+              << getOpenMPClauseName(OMPC_copyprivate) << 2;<br>
+          bool IsDecl = VD->isThisDeclarationADefinition(Context) ==<br>
+                        VarDecl::DeclarationOnly;<br>
+          Diag(VD->getLocation(),<br>
+               IsDecl ? diag::note_previous_decl : diag::note_defined_here)<br>
+              << VD;<br>
+          Diag(RD->getLocation(), diag::note_previous_decl) << RD;<br>
+          continue;<br>
+        }<br>
+        MarkFunctionReferenced(ELoc, MD);<br>
+        DiagnoseUseOfDecl(MD, ELoc);<br>
+      }<br>
+    }<br>
+<br>
+    // No need to mark vars as copyprivate, they are already threadprivate or<br>
+    // implicitly private.<br>
+    Vars.push_back(DE);<br>
+  }<br>
+<br>
+  if (Vars.empty())<br>
+    return nullptr;<br>
+<br>
+  return OMPCopyprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);<br>
+}<br>
+<br>
 #undef DSAStack<br>
<br>
Modified: cfe/trunk/lib/Sema/TreeTransform.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=211886&r1=211885&r2=211886&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=211886&r1=211885&r2=211886&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/TreeTransform.h (original)<br>
+++ cfe/trunk/lib/Sema/TreeTransform.h Fri Jun 27 05:37:06 2014<br>
@@ -1494,6 +1494,18 @@ public:<br>
                                              EndLoc);<br>
   }<br>
<br>
+  /// \brief Build a new OpenMP 'copyprivate' clause.<br>
+  ///<br>
+  /// By default, performs semantic analysis to build the new OpenMP clause.<br>
+  /// Subclasses may override this routine to provide different behavior.<br>
+  OMPClause *RebuildOMPCopyprivateClause(ArrayRef<Expr *> VarList,<br>
+                                         SourceLocation StartLoc,<br>
+                                         SourceLocation LParenLoc,<br>
+                                         SourceLocation EndLoc) {<br>
+    return getSema().ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc,<br>
+                                                  EndLoc);<br>
+  }<br>
+<br>
   /// \brief Rebuild the operand to an Objective-C \@synchronized statement.<br>
   ///<br>
   /// By default, performs semantic analysis to build the new statement.<br>
@@ -6403,7 +6415,8 @@ template <typename Derived><br>
 StmtResult<br>
 TreeTransform<Derived>::TransformOMPParallelDirective(OMPParallelDirective *D) {<br>
   DeclarationNameInfo DirName;<br>
-  getDerived().getSema().StartOpenMPDSABlock(OMPD_parallel, DirName, nullptr);<br>
+  getDerived().getSema().StartOpenMPDSABlock(OMPD_parallel, DirName, nullptr,<br>
+                                             D->getLocStart());<br>
   StmtResult Res = getDerived().TransformOMPExecutableDirective(D);<br>
   getDerived().getSema().EndOpenMPDSABlock(Res.get());<br>
   return Res;<br>
@@ -6413,7 +6426,8 @@ template <typename Derived><br>
 StmtResult<br>
 TreeTransform<Derived>::TransformOMPSimdDirective(OMPSimdDirective *D) {<br>
   DeclarationNameInfo DirName;<br>
-  getDerived().getSema().StartOpenMPDSABlock(OMPD_simd, DirName, nullptr);<br>
+  getDerived().getSema().StartOpenMPDSABlock(OMPD_simd, DirName, nullptr,<br>
+                                             D->getLocStart());<br>
   StmtResult Res = getDerived().TransformOMPExecutableDirective(D);<br>
   getDerived().getSema().EndOpenMPDSABlock(Res.get());<br>
   return Res;<br>
@@ -6423,7 +6437,8 @@ template <typename Derived><br>
 StmtResult<br>
 TreeTransform<Derived>::TransformOMPForDirective(OMPForDirective *D) {<br>
   DeclarationNameInfo DirName;<br>
-  getDerived().getSema().StartOpenMPDSABlock(OMPD_for, DirName, nullptr);<br>
+  getDerived().getSema().StartOpenMPDSABlock(OMPD_for, DirName, nullptr,<br>
+                                             D->getLocStart());<br>
   StmtResult Res = getDerived().TransformOMPExecutableDirective(D);<br>
   getDerived().getSema().EndOpenMPDSABlock(Res.get());<br>
   return Res;<br>
@@ -6433,7 +6448,8 @@ template <typename Derived><br>
 StmtResult<br>
 TreeTransform<Derived>::TransformOMPSectionsDirective(OMPSectionsDirective *D) {<br>
   DeclarationNameInfo DirName;<br>
-  getDerived().getSema().StartOpenMPDSABlock(OMPD_sections, DirName, nullptr);<br>
+  getDerived().getSema().StartOpenMPDSABlock(OMPD_sections, DirName, nullptr,<br>
+                                             D->getLocStart());<br>
   StmtResult Res = getDerived().TransformOMPExecutableDirective(D);<br>
   getDerived().getSema().EndOpenMPDSABlock(Res.get());<br>
   return Res;<br>
@@ -6443,7 +6459,8 @@ template <typename Derived><br>
 StmtResult<br>
 TreeTransform<Derived>::TransformOMPSectionDirective(OMPSectionDirective *D) {<br>
   DeclarationNameInfo DirName;<br>
-  getDerived().getSema().StartOpenMPDSABlock(OMPD_section, DirName, nullptr);<br>
+  getDerived().getSema().StartOpenMPDSABlock(OMPD_section, DirName, nullptr,<br>
+                                             D->getLocStart());<br>
   StmtResult Res = getDerived().TransformOMPExecutableDirective(D);<br>
   getDerived().getSema().EndOpenMPDSABlock(Res.get());<br>
   return Res;<br>
@@ -6453,7 +6470,8 @@ template <typename Derived><br>
 StmtResult<br>
 TreeTransform<Derived>::TransformOMPSingleDirective(OMPSingleDirective *D) {<br>
   DeclarationNameInfo DirName;<br>
-  getDerived().getSema().StartOpenMPDSABlock(OMPD_single, DirName, nullptr);<br>
+  getDerived().getSema().StartOpenMPDSABlock(OMPD_single, DirName, nullptr,<br>
+                                             D->getLocStart());<br>
   StmtResult Res = getDerived().TransformOMPExecutableDirective(D);<br>
   getDerived().getSema().EndOpenMPDSABlock(Res.get());<br>
   return Res;<br>
@@ -6680,6 +6698,21 @@ TreeTransform<Derived>::TransformOMPCopy<br>
                                              C->getLParenLoc(), C->getLocEnd());<br>
 }<br>
<br>
+template <typename Derived><br>
+OMPClause *<br>
+TreeTransform<Derived>::TransformOMPCopyprivateClause(OMPCopyprivateClause *C) {<br>
+  llvm::SmallVector<Expr *, 16> Vars;<br>
+  Vars.reserve(C->varlist_size());<br>
+  for (auto *VE : C->varlists()) {<br>
+    ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));<br>
+    if (EVar.isInvalid())<br>
+      return nullptr;<br>
+    Vars.push_back(EVar.get());<br>
+  }<br>
+  return getDerived().RebuildOMPCopyprivateClause(<br>
+      Vars, C->getLocStart(), C->getLParenLoc(), C->getLocEnd());<br>
+}<br>
+<br>
 //===----------------------------------------------------------------------===//<br>
 // Expression transformation<br>
 //===----------------------------------------------------------------------===//<br>
<br>
Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=211886&r1=211885&r2=211886&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=211886&r1=211885&r2=211886&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Fri Jun 27 05:37:06 2014<br>
@@ -1724,6 +1724,9 @@ OMPClause *OMPClauseReader::readClause()<br>
   case OMPC_copyin:<br>
     C = OMPCopyinClause::CreateEmpty(Context, Record[Idx++]);<br>
     break;<br>
+  case OMPC_copyprivate:<br>
+    C = OMPCopyprivateClause::CreateEmpty(Context, Record[Idx++]);<br>
+    break;<br>
   }<br>
   Visit(C);<br>
   C->setLocStart(Reader->ReadSourceLocation(Record, Idx));<br>
@@ -1865,6 +1868,16 @@ void OMPClauseReader::VisitOMPCopyinClau<br>
   C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));<br>
   unsigned NumVars = C->varlist_size();<br>
   SmallVector<Expr *, 16> Vars;<br>
+  Vars.reserve(NumVars);<br>
+  for (unsigned i = 0; i != NumVars; ++i)<br>
+    Vars.push_back(Reader->Reader.ReadSubExpr());<br>
+  C->setVarRefs(Vars);<br>
+}<br>
+<br>
+void OMPClauseReader::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) {<br>
+  C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));<br>
+  unsigned NumVars = C->varlist_size();<br>
+  SmallVector<Expr *, 16> Vars;<br>
   Vars.reserve(NumVars);<br>
   for (unsigned i = 0; i != NumVars; ++i)<br>
     Vars.push_back(Reader->Reader.ReadSubExpr());<br>
<br>
Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=211886&r1=211885&r2=211886&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=211886&r1=211885&r2=211886&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Fri Jun 27 05:37:06 2014<br>
@@ -1782,6 +1782,13 @@ void OMPClauseWriter::VisitOMPCopyinClau<br>
     Writer->Writer.AddStmt(VE);<br>
 }<br>
<br>
+void OMPClauseWriter::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) {<br>
+  Record.push_back(C->varlist_size());<br>
+  Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);<br>
+  for (auto *VE : C->varlists())<br>
+    Writer->Writer.AddStmt(VE);<br>
+}<br>
+<br>
 //===----------------------------------------------------------------------===//<br>
 // OpenMP Directives.<br>
 //===----------------------------------------------------------------------===//<br>
<br>
Modified: cfe/trunk/test/OpenMP/single_ast_print.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/single_ast_print.cpp?rev=211886&r1=211885&r2=211886&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/single_ast_print.cpp?rev=211886&r1=211885&r2=211886&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/OpenMP/single_ast_print.cpp (original)<br>
+++ cfe/trunk/test/OpenMP/single_ast_print.cpp Fri Jun 27 05:37:06 2014<br>
@@ -13,11 +13,11 @@ T tmain(T argc) {<br>
   T b = argc, c, d, e, f, g;<br>
   static T a;<br>
 // CHECK: static T a;<br>
-#pragma omp parallel<br>
-#pragma omp single private(argc, b), firstprivate(c, d), nowait<br>
+#pragma omp parallel private(g)<br>
+#pragma omp single private(argc, b), firstprivate(c, d), nowait copyprivate(g)<br>
   foo();<br>
-  // CHECK-NEXT: #pragma omp parallel<br>
-  // CHECK-NEXT: #pragma omp single private(argc,b) firstprivate(c,d) nowait<br>
+  // CHECK-NEXT: #pragma omp parallel private(g)<br>
+  // CHECK-NEXT: #pragma omp single private(argc,b) firstprivate(c,d) nowait copyprivate(g)<br>
   // CHECK-NEXT: foo();<br>
   return T();<br>
 }<br>
@@ -26,11 +26,11 @@ int main(int argc, char **argv) {<br>
   int b = argc, c, d, e, f, g;<br>
   static int a;<br>
 // CHECK: static int a;<br>
-#pragma omp parallel<br>
-#pragma omp single private(argc, b), firstprivate(argv, c), nowait<br>
+#pragma omp parallel private(g)<br>
+#pragma omp single private(argc, b), firstprivate(argv, c), nowait copyprivate(g)<br>
   foo();<br>
-  // CHECK-NEXT: #pragma omp parallel<br>
-  // CHECK-NEXT: #pragma omp single private(argc,b) firstprivate(argv,c) nowait<br>
+  // CHECK-NEXT: #pragma omp parallel private(g)<br>
+  // CHECK-NEXT: #pragma omp single private(argc,b) firstprivate(argv,c) nowait copyprivate(g)<br>
   // CHECK-NEXT: foo();<br>
   return (tmain<int, 5>(argc) + tmain<char, 1>(argv[0][0]));<br>
 }<br>
<br>
Added: cfe/trunk/test/OpenMP/single_copyprivate_messages.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/single_copyprivate_messages.cpp?rev=211886&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/single_copyprivate_messages.cpp?rev=211886&view=auto</a><br>

==============================================================================<br>
--- cfe/trunk/test/OpenMP/single_copyprivate_messages.cpp (added)<br>
+++ cfe/trunk/test/OpenMP/single_copyprivate_messages.cpp Fri Jun 27 05:37:06 2014<br>
@@ -0,0 +1,157 @@<br>
+// RUN: %clang_cc1 -verify -fopenmp=libiomp5 %s<br>
+<br>
+void foo() {<br>
+}<br>
+<br>
+struct S1; // expected-note 2 {{declared here}}<br>
+class S2 {<br>
+  mutable int a;<br>
+<br>
+public:<br>
+  S2() : a(0) {}<br>
+  S2 &operator=(S2 &s2) { return *this; }<br>
+};<br>
+class S3 {<br>
+  int a;<br>
+<br>
+public:<br>
+  S3() : a(0) {}<br>
+  S3 &operator=(S3 &s3) { return *this; }<br>
+};<br>
+class S4 { // expected-note 2 {{'S4' declared here}}<br>
+  int a;<br>
+  S4();<br>
+  S4 &operator=(const S4 &s4);<br>
+<br>
+public:<br>
+  S4(int v) : a(v) {}<br>
+};<br>
+class S5 { // expected-note 2 {{'S5' declared here}}<br>
+  int a;<br>
+  S5() : a(0) {}<br>
+  S5 &operator=(const S5 &s5) { return *this; }<br>
+<br>
+public:<br>
+  S5(int v) : a(v) {}<br>
+};<br>
+<br>
+S2 k;<br>
+S3 h;<br>
+S4 l(3); // expected-note 2 {{'l' defined here}}<br>
+S5 m(4); // expected-note 2 {{'m' defined here}}<br>
+#pragma omp threadprivate(h, k, l, m)<br>
+<br>
+template <class T, class C><br>
+T tmain(T argc, C **argv) {<br>
+  T i;<br>
+#pragma omp parallel<br>
+#pragma omp single copyprivate // expected-error {{expected '(' after 'copyprivate'}}<br>
+#pragma omp parallel<br>
+#pragma omp single copyprivate( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}<br>
+#pragma omp parallel<br>
+#pragma omp single copyprivate() // expected-error {{expected expression}}<br>
+#pragma omp parallel<br>
+#pragma omp single copyprivate(k // expected-error {{expected ')'}} expected-note {{to match this '('}}<br>
+#pragma omp parallel<br>
+#pragma omp single copyprivate(h, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}<br>
+#pragma omp parallel<br>
+#pragma omp single copyprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}<br>
+#pragma omp parallel<br>
+#pragma omp single copyprivate(l) // expected-error {{copyprivate variable must have an accessible, unambiguous copy assignment operator}}<br>
+#pragma omp parallel<br>
+#pragma omp single copyprivate(S1) // expected-error {{'S1' does not refer to a value}}<br>
+#pragma omp parallel<br>
+#pragma omp single copyprivate(argv[1]) // expected-error {{expected variable name}}<br>
+#pragma omp parallel // expected-note {{implicitly determined as shared}}<br>
+#pragma omp single copyprivate(i) // expected-error {{copyprivate variable must be threadprivate or private in the enclosing context}}<br>
+#pragma omp parallel<br>
+#pragma omp single copyprivate(m) // expected-error {{copyprivate variable must have an accessible, unambiguous copy assignment operator}}<br>
+  foo();<br>
+#pragma omp parallel private(i)<br>
+  {<br>
+#pragma omp single copyprivate(i)<br>
+    foo();<br>
+  }<br>
+#pragma omp parallel shared(i) // expected-note {{defined as shared}}<br>
+  {<br>
+#pragma omp single copyprivate(i) // expected-error {{copyprivate variable must be threadprivate or private in the enclosing context}}<br>
+    foo();<br>
+  }<br>
+#pragma omp parallel private(i)<br>
+#pragma omp parallel default(shared) // expected-note {{implicitly determined as shared}}<br>
+  {<br>
+#pragma omp single copyprivate(i) // expected-error {{copyprivate variable must be threadprivate or private in the enclosing context}}<br>
+    foo();<br>
+  }<br>
+#pragma omp parallel private(i)<br>
+#pragma omp parallel // expected-note {{implicitly determined as shared}}<br>
+  {<br>
+#pragma omp single copyprivate(i) // expected-error {{copyprivate variable must be threadprivate or private in the enclosing context}}<br>
+    foo();<br>
+  }<br>
+#pragma omp parallel<br>
+#pragma omp single private(i) copyprivate(i) // expected-error {{private variable cannot be copyprivate}} expected-note {{defined as private}}<br>
+  foo();<br>
+#pragma omp parallel<br>
+#pragma omp single firstprivate(i) copyprivate(i) // expected-error {{firstprivate variable cannot be copyprivate}} expected-note {{defined as firstprivate}}<br>
+  foo();<br>
+<br>
+  return T();<br>
+}<br>
+<br>
+int main(int argc, char **argv) {<br>
+  int i;<br>
+#pragma omp parallel<br>
+#pragma omp single copyprivate // expected-error {{expected '(' after 'copyprivate'}}<br>
+#pragma omp parallel<br>
+#pragma omp single copyprivate( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}<br>
+#pragma omp parallel<br>
+#pragma omp single copyprivate() // expected-error {{expected expression}}<br>
+#pragma omp parallel<br>
+#pragma omp single copyprivate(k // expected-error {{expected ')'}} expected-note {{to match this '('}}<br>
+#pragma omp parallel<br>
+#pragma omp single copyprivate(h, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}<br>
+#pragma omp parallel<br>
+#pragma omp single copyprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}<br>
+#pragma omp parallel<br>
+#pragma omp single copyprivate(l) // expected-error {{copyprivate variable must have an accessible, unambiguous copy assignment operator}}<br>
+#pragma omp parallel<br>
+#pragma omp single copyprivate(S1) // expected-error {{'S1' does not refer to a value}}<br>
+#pragma omp parallel<br>
+#pragma omp single copyprivate(argv[1]) // expected-error {{expected variable name}}<br>
+#pragma omp parallel // expected-note {{implicitly determined as shared}}<br>
+#pragma omp single copyprivate(i) // expected-error {{copyprivate variable must be threadprivate or private in the enclosing context}}<br>
+#pragma omp parallel<br>
+#pragma omp single copyprivate(m) // expected-error {{copyprivate variable must have an accessible, unambiguous copy assignment operator}}<br>
+  foo();<br>
+#pragma omp parallel private(i)<br>
+  {<br>
+#pragma omp single copyprivate(i)<br>
+    foo();<br>
+  }<br>
+#pragma omp parallel shared(i) // expected-note {{defined as shared}}<br>
+  {<br>
+#pragma omp single copyprivate(i) // expected-error {{copyprivate variable must be threadprivate or private in the enclosing context}}<br>
+    foo();<br>
+  }<br>
+#pragma omp parallel private(i)<br>
+#pragma omp parallel default(shared) // expected-note {{implicitly determined as shared}}<br>
+  {<br>
+#pragma omp single copyprivate(i) // expected-error {{copyprivate variable must be threadprivate or private in the enclosing context}}<br>
+    foo();<br>
+  }<br>
+#pragma omp parallel private(i)<br>
+#pragma omp parallel // expected-note {{implicitly determined as shared}}<br>
+  {<br>
+#pragma omp single copyprivate(i) // expected-error {{copyprivate variable must be threadprivate or private in the enclosing context}}<br>
+    foo();<br>
+  }<br>
+#pragma omp parallel<br>
+#pragma omp single private(i) copyprivate(i) // expected-error {{private variable cannot be copyprivate}} expected-note {{defined as private}}<br>
+  foo();<br>
+#pragma omp parallel<br>
+#pragma omp single firstprivate(i) copyprivate(i) // expected-error {{firstprivate variable cannot be copyprivate}} expected-note {{defined as firstprivate}}<br>
+  foo();<br>
+<br>
+  return tmain(argc, argv); // expected-note {{in instantiation of function template specialization 'tmain<int, char>' requested here}}<br>
+}<br>
<br>
Propchange: cfe/trunk/test/OpenMP/single_copyprivate_messages.cpp<br>
------------------------------------------------------------------------------<br>
    svn:eol-style = native<br>
<br>
Propchange: cfe/trunk/test/OpenMP/single_copyprivate_messages.cpp<br>
------------------------------------------------------------------------------<br>
    svn:keywords = Author Date Id Rev URL<br>
<br>
Propchange: cfe/trunk/test/OpenMP/single_copyprivate_messages.cpp<br>
------------------------------------------------------------------------------<br>
    svn:mime-type = text/plain<br>
<br>
Modified: cfe/trunk/tools/libclang/CIndex.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=211886&r1=211885&r2=211886&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=211886&r1=211885&r2=211886&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/tools/libclang/CIndex.cpp (original)<br>
+++ cfe/trunk/tools/libclang/CIndex.cpp Fri Jun 27 05:37:06 2014<br>
@@ -1989,6 +1989,10 @@ void OMPClauseEnqueue::VisitOMPAlignedCl<br>
 void OMPClauseEnqueue::VisitOMPCopyinClause(const OMPCopyinClause *C) {<br>
   VisitOMPClauseList(C);<br>
 }<br>
+void<br>
+OMPClauseEnqueue::VisitOMPCopyprivateClause(const OMPCopyprivateClause *C) {<br>
+  VisitOMPClauseList(C);<br>
+}<br>
 }<br>
<br>
 void EnqueueVisitor::EnqueueChildren(const OMPClause *S) {<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>