r211886 - [OPENMP] Parsing and sema analysis for 'copyprivate' clause.

Michael Wong fraggamuffin at gmail.com
Mon Jul 21 12:45:47 PDT 2014


I have reviewed this while reviewing:
r212516 - [OPENMP] Parsing and sema analysis for 'omp parallel sections'
directive.


All the code is a similar pattern and looks good.


On Fri, Jun 27, 2014 at 6:37 AM, Alexey Bataev <a.bataev at hotmail.com> wrote:

> Author: abataev
> Date: Fri Jun 27 05:37:06 2014
> New Revision: 211886
>
> URL: http://llvm.org/viewvc/llvm-project?rev=211886&view=rev
> Log:
> [OPENMP] Parsing and sema analysis for 'copyprivate' clause.
>
> Added:
>     cfe/trunk/test/OpenMP/single_copyprivate_messages.cpp   (with props)
> Modified:
>     cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h
>     cfe/trunk/include/clang/AST/OpenMPClause.h
>     cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
>     cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>     cfe/trunk/include/clang/Basic/OpenMPKinds.def
>     cfe/trunk/include/clang/Sema/Sema.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/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/test/OpenMP/single_ast_print.cpp
>     cfe/trunk/tools/libclang/CIndex.cpp
>
> Modified: cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h?rev=211886&r1=211885&r2=211886&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h (original)
> +++ cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h Fri Jun 27
> 05:37:06 2014
> @@ -2434,6 +2434,13 @@ bool RecursiveASTVisitor<Derived>::Visit
>  }
>
>  template <typename Derived>
> +bool RecursiveASTVisitor<Derived>::VisitOMPCopyprivateClause(
> +    OMPCopyprivateClause *C) {
> +  VisitOMPClauseList(C);
> +  return true;
> +}
> +
> +template <typename Derived>
>  bool
>  RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause
> *C) {
>    TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc()));
>
> Modified: cfe/trunk/include/clang/AST/OpenMPClause.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/OpenMPClause.h?rev=211886&r1=211885&r2=211886&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/OpenMPClause.h (original)
> +++ cfe/trunk/include/clang/AST/OpenMPClause.h Fri Jun 27 05:37:06 2014
> @@ -1218,6 +1218,66 @@ public:
>    }
>  };
>
> +/// \brief This represents clause 'copyprivate' in the '#pragma omp ...'
> +/// directives.
> +///
> +/// \code
> +/// #pragma omp single copyprivate(a,b)
> +/// \endcode
> +/// In this example directive '#pragma omp single' has clause
> 'copyprivate'
> +/// with the variables 'a' and 'b'.
> +///
> +class OMPCopyprivateClause : public
> OMPVarListClause<OMPCopyprivateClause> {
> +  /// \brief Build clause with number of variables \a N.
> +  ///
> +  /// \param StartLoc Starting location of the clause.
> +  /// \param LParenLoc Location of '('.
> +  /// \param EndLoc Ending location of the clause.
> +  /// \param N Number of the variables in the clause.
> +  ///
> +  OMPCopyprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc,
> +                       SourceLocation EndLoc, unsigned N)
> +      : OMPVarListClause<OMPCopyprivateClause>(OMPC_copyprivate, StartLoc,
> +                                               LParenLoc, EndLoc, N) {}
> +
> +  /// \brief Build an empty clause.
> +  ///
> +  /// \param N Number of variables.
> +  ///
> +  explicit OMPCopyprivateClause(unsigned N)
> +      : OMPVarListClause<OMPCopyprivateClause>(
> +            OMPC_copyprivate, SourceLocation(), SourceLocation(),
> +            SourceLocation(), N) {}
> +
> +public:
> +  /// \brief Creates clause with a list of variables \a VL.
> +  ///
> +  /// \param C AST context.
> +  /// \param StartLoc Starting location of the clause.
> +  /// \param LParenLoc Location of '('.
> +  /// \param EndLoc Ending location of the clause.
> +  /// \param VL List of references to the variables.
> +  ///
> +  static OMPCopyprivateClause *
> +  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation
> LParenLoc,
> +         SourceLocation EndLoc, ArrayRef<Expr *> VL);
> +  /// \brief Creates an empty clause with \a N variables.
> +  ///
> +  /// \param C AST context.
> +  /// \param N The number of variables.
> +  ///
> +  static OMPCopyprivateClause *CreateEmpty(const ASTContext &C, unsigned
> N);
> +
> +  StmtRange children() {
> +    return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
> +                     reinterpret_cast<Stmt **>(varlist_end()));
> +  }
> +
> +  static bool classof(const OMPClause *T) {
> +    return T->getClauseKind() == OMPC_copyprivate;
> +  }
> +};
> +
>  } // end namespace clang
>
>  #endif
>
> Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=211886&r1=211885&r2=211886&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
> +++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Fri Jun 27 05:37:06
> 2014
> @@ -2456,6 +2456,13 @@ bool RecursiveASTVisitor<Derived>::Visit
>  }
>
>  template <typename Derived>
> +bool RecursiveASTVisitor<Derived>::VisitOMPCopyprivateClause(
> +    OMPCopyprivateClause *C) {
> +  VisitOMPClauseList(C);
> +  return true;
> +}
> +
> +template <typename Derived>
>  bool
>  RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause
> *C) {
>    TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc()));
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=211886&r1=211885&r2=211886&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Jun 27
> 05:37:06 2014
> @@ -7026,6 +7026,8 @@ def note_omp_predetermined_dsa : Note<
>    "global variable is predetermined as shared|"
>    "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<
> +  "implicitly determined as %0">;
>  def err_omp_loop_var_dsa : Error<
>    "loop iteration variable may not be %0">;
>  def err_omp_not_for : Error<
>
> Modified: cfe/trunk/include/clang/Basic/OpenMPKinds.def
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/OpenMPKinds.def?rev=211886&r1=211885&r2=211886&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/OpenMPKinds.def (original)
> +++ cfe/trunk/include/clang/Basic/OpenMPKinds.def Fri Jun 27 05:37:06 2014
> @@ -67,6 +67,7 @@ OPENMP_CLAUSE(reduction,  OMPReductionCl
>  OPENMP_CLAUSE(linear,  OMPLinearClause)
>  OPENMP_CLAUSE(aligned, OMPAlignedClause)
>  OPENMP_CLAUSE(copyin,  OMPCopyinClause)
> +OPENMP_CLAUSE(copyprivate,  OMPCopyprivateClause)
>  OPENMP_CLAUSE(proc_bind, OMPProcBindClause)
>  OPENMP_CLAUSE(schedule, OMPScheduleClause)
>  OPENMP_CLAUSE(ordered, OMPOrderedClause)
> @@ -111,6 +112,7 @@ OPENMP_SECTIONS_CLAUSE(nowait)
>  // TODO more clauses allowed for directive 'omp single'.
>  OPENMP_SINGLE_CLAUSE(private)
>  OPENMP_SINGLE_CLAUSE(firstprivate)
> +OPENMP_SINGLE_CLAUSE(copyprivate)
>  OPENMP_SINGLE_CLAUSE(nowait)
>
>  // Static attributes for 'default' clause.
>
> Modified: cfe/trunk/include/clang/Sema/Sema.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=211886&r1=211885&r2=211886&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/Sema.h (original)
> +++ cfe/trunk/include/clang/Sema/Sema.h Fri Jun 27 05:37:06 2014
> @@ -7279,8 +7279,8 @@ public:
>                                                      Expr *Op);
>    /// \brief Called on start of new data sharing attribute block.
>    void StartOpenMPDSABlock(OpenMPDirectiveKind K,
> -                           const DeclarationNameInfo &DirName,
> -                           Scope *CurScope);
> +                           const DeclarationNameInfo &DirName, Scope
> *CurScope,
> +                           SourceLocation Loc);
>    /// \brief Called on end of data sharing attribute block.
>    void EndOpenMPDSABlock(Stmt *CurDirective);
>
> @@ -7300,8 +7300,7 @@ public:
>                                       ArrayRef<Expr *> VarList);
>
>    // brief Initialization of captured region for OpenMP region.
> -  void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, SourceLocation
> Loc,
> -                              Scope *CurScope);
> +  void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope);
>    StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
>                                              ArrayRef<OMPClause *> Clauses,
>                                              Stmt *AStmt,
> @@ -7460,6 +7459,11 @@ public:
>                                       SourceLocation StartLoc,
>                                       SourceLocation LParenLoc,
>                                       SourceLocation EndLoc);
> +  /// \brief Called on well-formed 'copyprivate' clause.
> +  OMPClause *ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
> +                                          SourceLocation StartLoc,
> +                                          SourceLocation LParenLoc,
> +                                          SourceLocation EndLoc);
>
>    /// \brief The kind of conversion being performed.
>    enum CheckedConversionKind {
>
> Modified: cfe/trunk/lib/AST/Stmt.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Stmt.cpp?rev=211886&r1=211885&r2=211886&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/Stmt.cpp (original)
> +++ cfe/trunk/lib/AST/Stmt.cpp Fri Jun 27 05:37:06 2014
> @@ -1280,6 +1280,28 @@ OMPCopyinClause *OMPCopyinClause::Create
>    return new (Mem) OMPCopyinClause(N);
>  }
>
> +OMPCopyprivateClause *OMPCopyprivateClause::Create(const ASTContext &C,
> +                                                   SourceLocation
> StartLoc,
> +                                                   SourceLocation
> LParenLoc,
> +                                                   SourceLocation EndLoc,
> +                                                   ArrayRef<Expr *> VL) {
> +  void *Mem =
> C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyprivateClause),
> +                                                  llvm::alignOf<Expr
> *>()) +
> +                         sizeof(Expr *) * VL.size());
> +  OMPCopyprivateClause *Clause =
> +      new (Mem) OMPCopyprivateClause(StartLoc, LParenLoc, EndLoc,
> VL.size());
> +  Clause->setVarRefs(VL);
> +  return Clause;
> +}
> +
> +OMPCopyprivateClause *OMPCopyprivateClause::CreateEmpty(const ASTContext
> &C,
> +                                                        unsigned N) {
> +  void *Mem =
> C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyprivateClause),
> +                                                  llvm::alignOf<Expr
> *>()) +
> +                         sizeof(Expr *) * N);
> +  return new (Mem) OMPCopyprivateClause(N);
> +}
> +
>  void OMPExecutableDirective::setClauses(ArrayRef<OMPClause *> Clauses) {
>    assert(Clauses.size() == getNumClauses() &&
>           "Number of clauses is not the same as the preallocated buffer");
>
> Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=211886&r1=211885&r2=211886&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
> +++ cfe/trunk/lib/AST/StmtPrinter.cpp Fri Jun 27 05:37:06 2014
> @@ -748,6 +748,14 @@ void OMPClausePrinter::VisitOMPCopyinCla
>    }
>  }
>
> +void OMPClausePrinter::VisitOMPCopyprivateClause(OMPCopyprivateClause
> *Node) {
> +  if (!Node->varlist_empty()) {
> +    OS << "copyprivate";
> +    VisitOMPClauseList(Node, '(');
> +    OS << ")";
> +  }
> +}
> +
>  }
>
>
>  //===----------------------------------------------------------------------===//
>
> Modified: cfe/trunk/lib/AST/StmtProfile.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=211886&r1=211885&r2=211886&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/StmtProfile.cpp (original)
> +++ cfe/trunk/lib/AST/StmtProfile.cpp Fri Jun 27 05:37:06 2014
> @@ -335,6 +335,10 @@ void OMPClauseProfiler::VisitOMPAlignedC
>  void OMPClauseProfiler::VisitOMPCopyinClause(const OMPCopyinClause *C) {
>    VisitOMPClauseList(C);
>  }
> +void
> +OMPClauseProfiler::VisitOMPCopyprivateClause(const OMPCopyprivateClause
> *C) {
> +  VisitOMPClauseList(C);
> +}
>  }
>
>  void
>
> Modified: cfe/trunk/lib/Basic/OpenMPKinds.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/OpenMPKinds.cpp?rev=211886&r1=211885&r2=211886&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Basic/OpenMPKinds.cpp (original)
> +++ cfe/trunk/lib/Basic/OpenMPKinds.cpp Fri Jun 27 05:37:06 2014
> @@ -95,6 +95,7 @@ unsigned clang::getOpenMPSimpleClauseTyp
>    case OMPC_linear:
>    case OMPC_aligned:
>    case OMPC_copyin:
> +  case OMPC_copyprivate:
>    case OMPC_ordered:
>    case OMPC_nowait:
>      break;
> @@ -149,6 +150,7 @@ const char *clang::getOpenMPSimpleClause
>    case OMPC_linear:
>    case OMPC_aligned:
>    case OMPC_copyin:
> +  case OMPC_copyprivate:
>    case OMPC_ordered:
>    case OMPC_nowait:
>      break;
> @@ -193,7 +195,7 @@ bool clang::isAllowedClauseForDirective(
>      break;
>    case OMPD_sections:
>      switch (CKind) {
> -#define OPENMP_SECTIONS_CLAUSE(Name)
>            \
> +#define OPENMP_SECTIONS_CLAUSE(Name)
>       \
>    case OMPC_##Name:
>      \
>      return true;
>  #include "clang/Basic/OpenMPKinds.def"
> @@ -203,7 +205,7 @@ bool clang::isAllowedClauseForDirective(
>      break;
>    case OMPD_single:
>      switch (CKind) {
> -#define OPENMP_SINGLE_CLAUSE(Name)
>          \
> +#define OPENMP_SINGLE_CLAUSE(Name)
>       \
>    case OMPC_##Name:
>      \
>      return true;
>  #include "clang/Basic/OpenMPKinds.def"
>
> Modified: cfe/trunk/lib/Parse/ParseOpenMP.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseOpenMP.cpp?rev=211886&r1=211885&r2=211886&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseOpenMP.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseOpenMP.cpp Fri Jun 27 05:37:06 2014
> @@ -131,7 +131,7 @@ StmtResult Parser::ParseOpenMPDeclarativ
>      if (isOpenMPSimdDirective(DKind))
>        ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
>      ParseScope OMPDirectiveScope(this, ScopeFlags);
> -    Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope());
> +    Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(),
> Loc);
>
>      while (Tok.isNot(tok::annot_pragma_openmp_end)) {
>        OpenMPClauseKind CKind = Tok.isAnnotation()
> @@ -159,7 +159,7 @@ StmtResult Parser::ParseOpenMPDeclarativ
>      {
>        // The body is a block scope like in Lambdas and Blocks.
>        Sema::CompoundScopeRAII CompoundScope(Actions);
> -      Actions.ActOnOpenMPRegionStart(DKind, Loc, getCurScope());
> +      Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
>        Actions.ActOnStartOfCompoundStmt();
>        // Parse statement
>        AssociatedStmt = ParseStatement();
> @@ -269,7 +269,8 @@ bool Parser::ParseOpenMPSimpleVarList(Op
>  ///       if-clause | num_threads-clause | safelen-clause |
> default-clause |
>  ///       private-clause | firstprivate-clause | shared-clause |
> linear-clause |
>  ///       aligned-clause | collapse-clause | lastprivate-clause |
> -///       reduction-clause | proc_bind-clause | schedule-clause
> +///       reduction-clause | proc_bind-clause | schedule-clause |
> +///       copyin-clause | copyprivate-clause
>  ///
>  OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
>                                       OpenMPClauseKind CKind, bool
> FirstClause) {
> @@ -345,6 +346,7 @@ OMPClause *Parser::ParseOpenMPClause(Ope
>    case OMPC_linear:
>    case OMPC_aligned:
>    case OMPC_copyin:
> +  case OMPC_copyprivate:
>      Clause = ParseOpenMPVarListClause(CKind);
>      break;
>    case OMPC_unknown:
>
> Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=211886&r1=211885&r2=211886&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Fri Jun 27 05:37:06 2014
> @@ -68,7 +68,10 @@ public:
>      OpenMPDirectiveKind DKind;
>      OpenMPClauseKind CKind;
>      DeclRefExpr *RefExpr;
> -    DSAVarData() : DKind(OMPD_unknown), CKind(OMPC_unknown),
> RefExpr(nullptr) {}
> +    SourceLocation ImplicitDSALoc;
> +    DSAVarData()
> +        : DKind(OMPD_unknown), CKind(OMPC_unknown), RefExpr(nullptr),
> +          ImplicitDSALoc() {}
>    };
>
>  private:
> @@ -83,17 +86,20 @@ private:
>      DeclSAMapTy SharingMap;
>      AlignedMapTy AlignedMap;
>      DefaultDataSharingAttributes DefaultAttr;
> +    SourceLocation DefaultAttrLoc;
>      OpenMPDirectiveKind Directive;
>      DeclarationNameInfo DirectiveName;
>      Scope *CurScope;
> +    SourceLocation ConstructLoc;
>      SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
> -                 Scope *CurScope)
> +                 Scope *CurScope, SourceLocation Loc)
>          : SharingMap(), AlignedMap(), DefaultAttr(DSA_unspecified),
> -          Directive(DKind), DirectiveName(std::move(Name)),
> CurScope(CurScope) {
> -    }
> +          Directive(DKind), DirectiveName(std::move(Name)),
> CurScope(CurScope),
> +          ConstructLoc(Loc) {}
>      SharingMapTy()
>          : SharingMap(), AlignedMap(), DefaultAttr(DSA_unspecified),
> -          Directive(OMPD_unknown), DirectiveName(), CurScope(nullptr) {}
> +          Directive(OMPD_unknown), DirectiveName(), CurScope(nullptr),
> +          ConstructLoc() {}
>    };
>
>    typedef SmallVector<SharingMapTy, 64> StackTy;
> @@ -113,8 +119,9 @@ public:
>    explicit DSAStackTy(Sema &S) : Stack(1), SemaRef(S) {}
>
>    void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
> -            Scope *CurScope) {
> -    Stack.push_back(SharingMapTy(DKind, DirName, CurScope));
> +            Scope *CurScope, SourceLocation Loc) {
> +    Stack.push_back(SharingMapTy(DKind, DirName, CurScope, Loc));
> +    Stack.back().DefaultAttrLoc = Loc;
>    }
>
>    void pop() {
> @@ -160,13 +167,22 @@ public:
>    }
>
>    /// \brief Set default data sharing attribute to none.
> -  void setDefaultDSANone() { Stack.back().DefaultAttr = DSA_none; }
> +  void setDefaultDSANone(SourceLocation Loc) {
> +    Stack.back().DefaultAttr = DSA_none;
> +    Stack.back().DefaultAttrLoc = Loc;
> +  }
>    /// \brief Set default data sharing attribute to shared.
> -  void setDefaultDSAShared() { Stack.back().DefaultAttr = DSA_shared; }
> +  void setDefaultDSAShared(SourceLocation Loc) {
> +    Stack.back().DefaultAttr = DSA_shared;
> +    Stack.back().DefaultAttrLoc = Loc;
> +  }
>
>    DefaultDataSharingAttributes getDefaultDSA() const {
>      return Stack.back().DefaultAttr;
>    }
> +  SourceLocation getDefaultDSALocation() const {
> +    return Stack.back().DefaultAttrLoc;
> +  }
>
>    /// \brief Checks if the specified variable is a threadprivate.
>    bool isThreadPrivate(VarDecl *D) {
> @@ -176,6 +192,7 @@ public:
>
>    Scope *getCurScope() const { return Stack.back().CurScope; }
>    Scope *getCurScope() { return Stack.back().CurScope; }
> +  SourceLocation getConstructLoc() { return Stack.back().ConstructLoc; }
>  };
>  } // namespace
>
> @@ -227,6 +244,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDS
>    switch (Iter->DefaultAttr) {
>    case DSA_shared:
>      DVar.CKind = OMPC_shared;
> +    DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
>      return DVar;
>    case DSA_none:
>      return DVar;
> @@ -235,6 +253,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDS
>      // in a Construct, implicitly determined, p.2]
>      //  In a parallel construct, if no default clause is present, these
>      //  variables are shared.
> +    DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
>      if (isOpenMPParallelDirective(DVar.DKind)) {
>        DVar.CKind = OMPC_shared;
>        return DVar;
> @@ -456,8 +475,8 @@ void Sema::DestroyDataSharingAttributesS
>
>  void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
>                                 const DeclarationNameInfo &DirName,
> -                               Scope *CurScope) {
> -  DSAStack->push(DKind, DirName, CurScope);
> +                               Scope *CurScope, SourceLocation Loc) {
> +  DSAStack->push(DKind, DirName, CurScope, Loc);
>    PushExpressionEvaluationContext(PotentiallyEvaluated);
>  }
>
> @@ -776,8 +795,9 @@ static void ReportOriginalDSA(Sema &Sema
>      PDSA_LoopIterVarLastprivate,
>      PDSA_ConstVarShared,
>      PDSA_GlobalVarShared,
> -    PDSA_LocalVarPrivate
> -  } Reason;
> +    PDSA_LocalVarPrivate,
> +    PDSA_Implicit
> +  } Reason = PDSA_Implicit;
>    bool ReportHint = false;
>    if (IsLoopIterVar) {
>      if (DVar.CKind == OMPC_private)
> @@ -794,14 +814,18 @@ static void ReportOriginalDSA(Sema &Sema
>      Reason = PDSA_GlobalVarShared;
>    else if (VD->getType().isConstant(SemaRef.getASTContext()))
>      Reason = PDSA_ConstVarShared;
> -  else {
> +  else if (VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
>      ReportHint = true;
>      Reason = PDSA_LocalVarPrivate;
>    }
> -
> -  SemaRef.Diag(VD->getLocation(), diag::note_omp_predetermined_dsa)
> -      << Reason << ReportHint
> -      << getOpenMPDirectiveName(Stack->getCurrentDirective());
> +  if (Reason != PDSA_Implicit) {
> +    SemaRef.Diag(VD->getLocation(), diag::note_omp_predetermined_dsa)
> +        << Reason << ReportHint
> +        << getOpenMPDirectiveName(Stack->getCurrentDirective());
> +  } else if (DVar.ImplicitDSALoc.isValid()) {
> +    SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
> +        << getOpenMPClauseName(DVar.CKind);
> +  }
>  }
>
>  namespace {
> @@ -882,8 +906,7 @@ public:
>  };
>  } // namespace
>
> -void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind,
> SourceLocation Loc,
> -                                  Scope *CurScope) {
> +void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope
> *CurScope) {
>    switch (DKind) {
>    case OMPD_parallel: {
>      QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
> @@ -893,42 +916,48 @@ void Sema::ActOnOpenMPRegionStart(OpenMP
>          std::make_pair(".bound_tid.", KmpInt32PtrTy),
>          std::make_pair(StringRef(), QualType()) // __context with shared
> vars
>      };
> -    ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, Params);
> +    ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
> CR_OpenMP,
> +                             Params);
>      break;
>    }
>    case OMPD_simd: {
>      Sema::CapturedParamNameType Params[] = {
>          std::make_pair(StringRef(), QualType()) // __context with shared
> vars
>      };
> -    ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, Params);
> +    ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
> CR_OpenMP,
> +                             Params);
>      break;
>    }
>    case OMPD_for: {
>      Sema::CapturedParamNameType Params[] = {
>          std::make_pair(StringRef(), QualType()) // __context with shared
> vars
>      };
> -    ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, Params);
> +    ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
> CR_OpenMP,
> +                             Params);
>      break;
>    }
>    case OMPD_sections: {
>      Sema::CapturedParamNameType Params[] = {
>          std::make_pair(StringRef(), QualType()) // __context with shared
> vars
>      };
> -    ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, Params);
> +    ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
> CR_OpenMP,
> +                             Params);
>      break;
>    }
>    case OMPD_section: {
>      Sema::CapturedParamNameType Params[] = {
>          std::make_pair(StringRef(), QualType()) // __context with shared
> vars
>      };
> -    ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, Params);
> +    ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
> CR_OpenMP,
> +                             Params);
>      break;
>    }
>    case OMPD_single: {
>      Sema::CapturedParamNameType Params[] = {
>          std::make_pair(StringRef(), QualType()) // __context with shared
> vars
>      };
> -    ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, Params);
> +    ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
> CR_OpenMP,
> +                             Params);
>      break;
>    }
>    case OMPD_threadprivate:
> @@ -1695,6 +1724,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprCl
>    case OMPC_linear:
>    case OMPC_aligned:
>    case OMPC_copyin:
> +  case OMPC_copyprivate:
>    case OMPC_ordered:
>    case OMPC_nowait:
>    case OMPC_threadprivate:
> @@ -1874,6 +1904,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause
>    case OMPC_linear:
>    case OMPC_aligned:
>    case OMPC_copyin:
> +  case OMPC_copyprivate:
>    case OMPC_ordered:
>    case OMPC_nowait:
>    case OMPC_threadprivate:
> @@ -1914,10 +1945,10 @@ OMPClause *Sema::ActOnOpenMPDefaultClaus
>    }
>    switch (Kind) {
>    case OMPC_DEFAULT_none:
> -    DSAStack->setDefaultDSANone();
> +    DSAStack->setDefaultDSANone(KindKwLoc);
>      break;
>    case OMPC_DEFAULT_shared:
> -    DSAStack->setDefaultDSAShared();
> +    DSAStack->setDefaultDSAShared(KindKwLoc);
>      break;
>    case OMPC_DEFAULT_unknown:
>      llvm_unreachable("Clause kind is not allowed.");
> @@ -1984,6 +2015,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWi
>    case OMPC_linear:
>    case OMPC_aligned:
>    case OMPC_copyin:
> +  case OMPC_copyprivate:
>    case OMPC_ordered:
>    case OMPC_nowait:
>    case OMPC_threadprivate:
> @@ -2073,6 +2105,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenM
>    case OMPC_linear:
>    case OMPC_aligned:
>    case OMPC_copyin:
> +  case OMPC_copyprivate:
>    case OMPC_default:
>    case OMPC_proc_bind:
>    case OMPC_threadprivate:
> @@ -2126,6 +2159,9 @@ OMPClause *Sema::ActOnOpenMPVarListClaus
>    case OMPC_copyin:
>      Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
>      break;
> +  case OMPC_copyprivate:
> +    Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc,
> EndLoc);
> +    break;
>    case OMPC_if:
>    case OMPC_num_threads:
>    case OMPC_safelen:
> @@ -3281,4 +3317,108 @@ OMPClause *Sema::ActOnOpenMPCopyinClause
>    return OMPCopyinClause::Create(Context, StartLoc, LParenLoc, EndLoc,
> Vars);
>  }
>
> +OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
> +                                              SourceLocation StartLoc,
> +                                              SourceLocation LParenLoc,
> +                                              SourceLocation EndLoc) {
> +  SmallVector<Expr *, 8> Vars;
> +  for (auto &RefExpr : VarList) {
> +    assert(RefExpr && "NULL expr in OpenMP copyprivate clause.");
> +    if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
> +      // It will be analyzed later.
> +      Vars.push_back(RefExpr);
> +      continue;
> +    }
> +
> +    SourceLocation ELoc = RefExpr->getExprLoc();
> +    // OpenMP [2.1, C/C++]
> +    //  A list item is a variable name.
> +    // OpenMP  [2.14.4.1, Restrictions, p.1]
> +    //  A list item that appears in a copyin clause must be threadprivate.
> +    DeclRefExpr *DE = dyn_cast<DeclRefExpr>(RefExpr);
> +    if (!DE || !isa<VarDecl>(DE->getDecl())) {
> +      Diag(ELoc, diag::err_omp_expected_var_name) <<
> RefExpr->getSourceRange();
> +      continue;
> +    }
> +
> +    Decl *D = DE->getDecl();
> +    VarDecl *VD = cast<VarDecl>(D);
> +
> +    QualType Type = VD->getType();
> +    if (Type->isDependentType() || Type->isInstantiationDependentType()) {
> +      // It will be analyzed later.
> +      Vars.push_back(DE);
> +      continue;
> +    }
> +
> +    // OpenMP [2.14.4.2, Restrictions, p.2]
> +    //  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);
> +      if (DVar.CKind != OMPC_copyprivate && DVar.CKind != OMPC_unknown &&
> +          !(DVar.CKind == OMPC_private && !DVar.RefExpr)) {
> +        Diag(ELoc, diag::err_omp_wrong_dsa)
> +            << getOpenMPClauseName(DVar.CKind)
> +            << getOpenMPClauseName(OMPC_copyprivate);
> +        ReportOriginalDSA(*this, DSAStack, VD, DVar);
> +        continue;
> +      }
> +
> +      // OpenMP [2.11.4.2, Restrictions, p.1]
> +      //  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);
> +        if (DVar.CKind == OMPC_shared) {
> +          Diag(ELoc, diag::err_omp_required_access)
> +              << getOpenMPClauseName(OMPC_copyprivate)
> +              << "threadprivate or private in the enclosing context";
> +          ReportOriginalDSA(*this, DSAStack, VD, DVar);
> +          continue;
> +        }
> +      }
> +    }
> +
> +    // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
> +    //  A variable of class type (or array thereof) that appears in a
> +    //  copyin clause requires an accessible, unambiguous copy assignment
> +    //  operator for the class type.
> +    Type = Context.getBaseElementType(Type);
> +    CXXRecordDecl *RD =
> +        getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr;
> +    // FIXME This code must be replaced by actual assignment of the
> +    // threadprivate variable.
> +    if (RD) {
> +      CXXMethodDecl *MD = LookupCopyingAssignment(RD, 0, false, 0);
> +      DeclAccessPair FoundDecl = DeclAccessPair::make(MD,
> MD->getAccess());
> +      if (MD) {
> +        if (CheckMemberAccess(ELoc, RD, FoundDecl) == AR_inaccessible ||
> +            MD->isDeleted()) {
> +          Diag(ELoc, diag::err_omp_required_method)
> +              << getOpenMPClauseName(OMPC_copyprivate) << 2;
> +          bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
> +                        VarDecl::DeclarationOnly;
> +          Diag(VD->getLocation(),
> +               IsDecl ? diag::note_previous_decl :
> diag::note_defined_here)
> +              << VD;
> +          Diag(RD->getLocation(), diag::note_previous_decl) << RD;
> +          continue;
> +        }
> +        MarkFunctionReferenced(ELoc, MD);
> +        DiagnoseUseOfDecl(MD, ELoc);
> +      }
> +    }
> +
> +    // No need to mark vars as copyprivate, they are already
> threadprivate or
> +    // implicitly private.
> +    Vars.push_back(DE);
> +  }
> +
> +  if (Vars.empty())
> +    return nullptr;
> +
> +  return OMPCopyprivateClause::Create(Context, StartLoc, LParenLoc,
> EndLoc, Vars);
> +}
> +
>  #undef DSAStack
>
> Modified: cfe/trunk/lib/Sema/TreeTransform.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=211886&r1=211885&r2=211886&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/TreeTransform.h (original)
> +++ cfe/trunk/lib/Sema/TreeTransform.h Fri Jun 27 05:37:06 2014
> @@ -1494,6 +1494,18 @@ public:
>                                               EndLoc);
>    }
>
> +  /// \brief Build a new OpenMP 'copyprivate' clause.
> +  ///
> +  /// By default, performs semantic analysis to build the new OpenMP
> clause.
> +  /// Subclasses may override this routine to provide different behavior.
> +  OMPClause *RebuildOMPCopyprivateClause(ArrayRef<Expr *> VarList,
> +                                         SourceLocation StartLoc,
> +                                         SourceLocation LParenLoc,
> +                                         SourceLocation EndLoc) {
> +    return getSema().ActOnOpenMPCopyprivateClause(VarList, StartLoc,
> LParenLoc,
> +                                                  EndLoc);
> +  }
> +
>    /// \brief Rebuild the operand to an Objective-C \@synchronized
> statement.
>    ///
>    /// By default, performs semantic analysis to build the new statement.
> @@ -6403,7 +6415,8 @@ template <typename Derived>
>  StmtResult
>  TreeTransform<Derived>::TransformOMPParallelDirective(OMPParallelDirective
> *D) {
>    DeclarationNameInfo DirName;
> -  getDerived().getSema().StartOpenMPDSABlock(OMPD_parallel, DirName,
> nullptr);
> +  getDerived().getSema().StartOpenMPDSABlock(OMPD_parallel, DirName,
> nullptr,
> +                                             D->getLocStart());
>    StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
>    getDerived().getSema().EndOpenMPDSABlock(Res.get());
>    return Res;
> @@ -6413,7 +6426,8 @@ template <typename Derived>
>  StmtResult
>  TreeTransform<Derived>::TransformOMPSimdDirective(OMPSimdDirective *D) {
>    DeclarationNameInfo DirName;
> -  getDerived().getSema().StartOpenMPDSABlock(OMPD_simd, DirName, nullptr);
> +  getDerived().getSema().StartOpenMPDSABlock(OMPD_simd, DirName, nullptr,
> +                                             D->getLocStart());
>    StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
>    getDerived().getSema().EndOpenMPDSABlock(Res.get());
>    return Res;
> @@ -6423,7 +6437,8 @@ template <typename Derived>
>  StmtResult
>  TreeTransform<Derived>::TransformOMPForDirective(OMPForDirective *D) {
>    DeclarationNameInfo DirName;
> -  getDerived().getSema().StartOpenMPDSABlock(OMPD_for, DirName, nullptr);
> +  getDerived().getSema().StartOpenMPDSABlock(OMPD_for, DirName, nullptr,
> +                                             D->getLocStart());
>    StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
>    getDerived().getSema().EndOpenMPDSABlock(Res.get());
>    return Res;
> @@ -6433,7 +6448,8 @@ template <typename Derived>
>  StmtResult
>  TreeTransform<Derived>::TransformOMPSectionsDirective(OMPSectionsDirective
> *D) {
>    DeclarationNameInfo DirName;
> -  getDerived().getSema().StartOpenMPDSABlock(OMPD_sections, DirName,
> nullptr);
> +  getDerived().getSema().StartOpenMPDSABlock(OMPD_sections, DirName,
> nullptr,
> +                                             D->getLocStart());
>    StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
>    getDerived().getSema().EndOpenMPDSABlock(Res.get());
>    return Res;
> @@ -6443,7 +6459,8 @@ template <typename Derived>
>  StmtResult
>  TreeTransform<Derived>::TransformOMPSectionDirective(OMPSectionDirective
> *D) {
>    DeclarationNameInfo DirName;
> -  getDerived().getSema().StartOpenMPDSABlock(OMPD_section, DirName,
> nullptr);
> +  getDerived().getSema().StartOpenMPDSABlock(OMPD_section, DirName,
> nullptr,
> +                                             D->getLocStart());
>    StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
>    getDerived().getSema().EndOpenMPDSABlock(Res.get());
>    return Res;
> @@ -6453,7 +6470,8 @@ template <typename Derived>
>  StmtResult
>  TreeTransform<Derived>::TransformOMPSingleDirective(OMPSingleDirective
> *D) {
>    DeclarationNameInfo DirName;
> -  getDerived().getSema().StartOpenMPDSABlock(OMPD_single, DirName,
> nullptr);
> +  getDerived().getSema().StartOpenMPDSABlock(OMPD_single, DirName,
> nullptr,
> +                                             D->getLocStart());
>    StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
>    getDerived().getSema().EndOpenMPDSABlock(Res.get());
>    return Res;
> @@ -6680,6 +6698,21 @@ TreeTransform<Derived>::TransformOMPCopy
>                                               C->getLParenLoc(),
> C->getLocEnd());
>  }
>
> +template <typename Derived>
> +OMPClause *
> +TreeTransform<Derived>::TransformOMPCopyprivateClause(OMPCopyprivateClause
> *C) {
> +  llvm::SmallVector<Expr *, 16> Vars;
> +  Vars.reserve(C->varlist_size());
> +  for (auto *VE : C->varlists()) {
> +    ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
> +    if (EVar.isInvalid())
> +      return nullptr;
> +    Vars.push_back(EVar.get());
> +  }
> +  return getDerived().RebuildOMPCopyprivateClause(
> +      Vars, C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
> +}
> +
>
>  //===----------------------------------------------------------------------===//
>  // Expression transformation
>
>  //===----------------------------------------------------------------------===//
>
> Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=211886&r1=211885&r2=211886&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Fri Jun 27 05:37:06 2014
> @@ -1724,6 +1724,9 @@ OMPClause *OMPClauseReader::readClause()
>    case OMPC_copyin:
>      C = OMPCopyinClause::CreateEmpty(Context, Record[Idx++]);
>      break;
> +  case OMPC_copyprivate:
> +    C = OMPCopyprivateClause::CreateEmpty(Context, Record[Idx++]);
> +    break;
>    }
>    Visit(C);
>    C->setLocStart(Reader->ReadSourceLocation(Record, Idx));
> @@ -1865,6 +1868,16 @@ void OMPClauseReader::VisitOMPCopyinClau
>    C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
>    unsigned NumVars = C->varlist_size();
>    SmallVector<Expr *, 16> Vars;
> +  Vars.reserve(NumVars);
> +  for (unsigned i = 0; i != NumVars; ++i)
> +    Vars.push_back(Reader->Reader.ReadSubExpr());
> +  C->setVarRefs(Vars);
> +}
> +
> +void OMPClauseReader::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) {
> +  C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
> +  unsigned NumVars = C->varlist_size();
> +  SmallVector<Expr *, 16> Vars;
>    Vars.reserve(NumVars);
>    for (unsigned i = 0; i != NumVars; ++i)
>      Vars.push_back(Reader->Reader.ReadSubExpr());
>
> Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=211886&r1=211885&r2=211886&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Fri Jun 27 05:37:06 2014
> @@ -1782,6 +1782,13 @@ void OMPClauseWriter::VisitOMPCopyinClau
>      Writer->Writer.AddStmt(VE);
>  }
>
> +void OMPClauseWriter::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) {
> +  Record.push_back(C->varlist_size());
> +  Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
> +  for (auto *VE : C->varlists())
> +    Writer->Writer.AddStmt(VE);
> +}
> +
>
>  //===----------------------------------------------------------------------===//
>  // OpenMP Directives.
>
>  //===----------------------------------------------------------------------===//
>
> Modified: cfe/trunk/test/OpenMP/single_ast_print.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/single_ast_print.cpp?rev=211886&r1=211885&r2=211886&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/OpenMP/single_ast_print.cpp (original)
> +++ cfe/trunk/test/OpenMP/single_ast_print.cpp Fri Jun 27 05:37:06 2014
> @@ -13,11 +13,11 @@ T tmain(T argc) {
>    T b = argc, c, d, e, f, g;
>    static T a;
>  // CHECK: static T a;
> -#pragma omp parallel
> -#pragma omp single private(argc, b), firstprivate(c, d), nowait
> +#pragma omp parallel private(g)
> +#pragma omp single private(argc, b), firstprivate(c, d), nowait
> copyprivate(g)
>    foo();
> -  // CHECK-NEXT: #pragma omp parallel
> -  // CHECK-NEXT: #pragma omp single private(argc,b) firstprivate(c,d)
> nowait
> +  // CHECK-NEXT: #pragma omp parallel private(g)
> +  // CHECK-NEXT: #pragma omp single private(argc,b) firstprivate(c,d)
> nowait copyprivate(g)
>    // CHECK-NEXT: foo();
>    return T();
>  }
> @@ -26,11 +26,11 @@ int main(int argc, char **argv) {
>    int b = argc, c, d, e, f, g;
>    static int a;
>  // CHECK: static int a;
> -#pragma omp parallel
> -#pragma omp single private(argc, b), firstprivate(argv, c), nowait
> +#pragma omp parallel private(g)
> +#pragma omp single private(argc, b), firstprivate(argv, c), nowait
> copyprivate(g)
>    foo();
> -  // CHECK-NEXT: #pragma omp parallel
> -  // CHECK-NEXT: #pragma omp single private(argc,b) firstprivate(argv,c)
> nowait
> +  // CHECK-NEXT: #pragma omp parallel private(g)
> +  // CHECK-NEXT: #pragma omp single private(argc,b) firstprivate(argv,c)
> nowait copyprivate(g)
>    // CHECK-NEXT: foo();
>    return (tmain<int, 5>(argc) + tmain<char, 1>(argv[0][0]));
>  }
>
> Added: cfe/trunk/test/OpenMP/single_copyprivate_messages.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/single_copyprivate_messages.cpp?rev=211886&view=auto
>
> ==============================================================================
> --- cfe/trunk/test/OpenMP/single_copyprivate_messages.cpp (added)
> +++ cfe/trunk/test/OpenMP/single_copyprivate_messages.cpp Fri Jun 27
> 05:37:06 2014
> @@ -0,0 +1,157 @@
> +// RUN: %clang_cc1 -verify -fopenmp=libiomp5 %s
> +
> +void foo() {
> +}
> +
> +struct S1; // expected-note 2 {{declared here}}
> +class S2 {
> +  mutable int a;
> +
> +public:
> +  S2() : a(0) {}
> +  S2 &operator=(S2 &s2) { return *this; }
> +};
> +class S3 {
> +  int a;
> +
> +public:
> +  S3() : a(0) {}
> +  S3 &operator=(S3 &s3) { return *this; }
> +};
> +class S4 { // expected-note 2 {{'S4' declared here}}
> +  int a;
> +  S4();
> +  S4 &operator=(const S4 &s4);
> +
> +public:
> +  S4(int v) : a(v) {}
> +};
> +class S5 { // expected-note 2 {{'S5' declared here}}
> +  int a;
> +  S5() : a(0) {}
> +  S5 &operator=(const S5 &s5) { return *this; }
> +
> +public:
> +  S5(int v) : a(v) {}
> +};
> +
> +S2 k;
> +S3 h;
> +S4 l(3); // expected-note 2 {{'l' defined here}}
> +S5 m(4); // expected-note 2 {{'m' defined here}}
> +#pragma omp threadprivate(h, k, l, m)
> +
> +template <class T, class C>
> +T tmain(T argc, C **argv) {
> +  T i;
> +#pragma omp parallel
> +#pragma omp single copyprivate // expected-error {{expected '(' after
> 'copyprivate'}}
> +#pragma omp parallel
> +#pragma omp single copyprivate( // expected-error {{expected expression}}
> expected-error {{expected ')'}} expected-note {{to match this '('}}
> +#pragma omp parallel
> +#pragma omp single copyprivate() // expected-error {{expected expression}}
> +#pragma omp parallel
> +#pragma omp single copyprivate(k // expected-error {{expected ')'}}
> expected-note {{to match this '('}}
> +#pragma omp parallel
> +#pragma omp single copyprivate(h, // expected-error {{expected
> expression}} expected-error {{expected ')'}} expected-note {{to match this
> '('}}
> +#pragma omp parallel
> +#pragma omp single copyprivate(argc > 0 ? argv[1] : argv[2]) //
> expected-error {{expected variable name}}
> +#pragma omp parallel
> +#pragma omp single copyprivate(l) // expected-error {{copyprivate
> variable must have an accessible, unambiguous copy assignment operator}}
> +#pragma omp parallel
> +#pragma omp single copyprivate(S1) // expected-error {{'S1' does not
> refer to a value}}
> +#pragma omp parallel
> +#pragma omp single copyprivate(argv[1]) // expected-error {{expected
> variable name}}
> +#pragma omp parallel // expected-note {{implicitly determined as shared}}
> +#pragma omp single copyprivate(i) // expected-error {{copyprivate
> variable must be threadprivate or private in the enclosing context}}
> +#pragma omp parallel
> +#pragma omp single copyprivate(m) // expected-error {{copyprivate
> variable must have an accessible, unambiguous copy assignment operator}}
> +  foo();
> +#pragma omp parallel private(i)
> +  {
> +#pragma omp single copyprivate(i)
> +    foo();
> +  }
> +#pragma omp parallel shared(i) // expected-note {{defined as shared}}
> +  {
> +#pragma omp single copyprivate(i) // expected-error {{copyprivate
> variable must be threadprivate or private in the enclosing context}}
> +    foo();
> +  }
> +#pragma omp parallel private(i)
> +#pragma omp parallel default(shared) // expected-note {{implicitly
> determined as shared}}
> +  {
> +#pragma omp single copyprivate(i) // expected-error {{copyprivate
> variable must be threadprivate or private in the enclosing context}}
> +    foo();
> +  }
> +#pragma omp parallel private(i)
> +#pragma omp parallel // expected-note {{implicitly determined as shared}}
> +  {
> +#pragma omp single copyprivate(i) // expected-error {{copyprivate
> variable must be threadprivate or private in the enclosing context}}
> +    foo();
> +  }
> +#pragma omp parallel
> +#pragma omp single private(i) copyprivate(i) // expected-error {{private
> variable cannot be copyprivate}} expected-note {{defined as private}}
> +  foo();
> +#pragma omp parallel
> +#pragma omp single firstprivate(i) copyprivate(i) // expected-error
> {{firstprivate variable cannot be copyprivate}} expected-note {{defined as
> firstprivate}}
> +  foo();
> +
> +  return T();
> +}
> +
> +int main(int argc, char **argv) {
> +  int i;
> +#pragma omp parallel
> +#pragma omp single copyprivate // expected-error {{expected '(' after
> 'copyprivate'}}
> +#pragma omp parallel
> +#pragma omp single copyprivate( // expected-error {{expected expression}}
> expected-error {{expected ')'}} expected-note {{to match this '('}}
> +#pragma omp parallel
> +#pragma omp single copyprivate() // expected-error {{expected expression}}
> +#pragma omp parallel
> +#pragma omp single copyprivate(k // expected-error {{expected ')'}}
> expected-note {{to match this '('}}
> +#pragma omp parallel
> +#pragma omp single copyprivate(h, // expected-error {{expected
> expression}} expected-error {{expected ')'}} expected-note {{to match this
> '('}}
> +#pragma omp parallel
> +#pragma omp single copyprivate(argc > 0 ? argv[1] : argv[2]) //
> expected-error {{expected variable name}}
> +#pragma omp parallel
> +#pragma omp single copyprivate(l) // expected-error {{copyprivate
> variable must have an accessible, unambiguous copy assignment operator}}
> +#pragma omp parallel
> +#pragma omp single copyprivate(S1) // expected-error {{'S1' does not
> refer to a value}}
> +#pragma omp parallel
> +#pragma omp single copyprivate(argv[1]) // expected-error {{expected
> variable name}}
> +#pragma omp parallel // expected-note {{implicitly determined as shared}}
> +#pragma omp single copyprivate(i) // expected-error {{copyprivate
> variable must be threadprivate or private in the enclosing context}}
> +#pragma omp parallel
> +#pragma omp single copyprivate(m) // expected-error {{copyprivate
> variable must have an accessible, unambiguous copy assignment operator}}
> +  foo();
> +#pragma omp parallel private(i)
> +  {
> +#pragma omp single copyprivate(i)
> +    foo();
> +  }
> +#pragma omp parallel shared(i) // expected-note {{defined as shared}}
> +  {
> +#pragma omp single copyprivate(i) // expected-error {{copyprivate
> variable must be threadprivate or private in the enclosing context}}
> +    foo();
> +  }
> +#pragma omp parallel private(i)
> +#pragma omp parallel default(shared) // expected-note {{implicitly
> determined as shared}}
> +  {
> +#pragma omp single copyprivate(i) // expected-error {{copyprivate
> variable must be threadprivate or private in the enclosing context}}
> +    foo();
> +  }
> +#pragma omp parallel private(i)
> +#pragma omp parallel // expected-note {{implicitly determined as shared}}
> +  {
> +#pragma omp single copyprivate(i) // expected-error {{copyprivate
> variable must be threadprivate or private in the enclosing context}}
> +    foo();
> +  }
> +#pragma omp parallel
> +#pragma omp single private(i) copyprivate(i) // expected-error {{private
> variable cannot be copyprivate}} expected-note {{defined as private}}
> +  foo();
> +#pragma omp parallel
> +#pragma omp single firstprivate(i) copyprivate(i) // expected-error
> {{firstprivate variable cannot be copyprivate}} expected-note {{defined as
> firstprivate}}
> +  foo();
> +
> +  return tmain(argc, argv); // expected-note {{in instantiation of
> function template specialization 'tmain<int, char>' requested here}}
> +}
>
> Propchange: cfe/trunk/test/OpenMP/single_copyprivate_messages.cpp
>
> ------------------------------------------------------------------------------
>     svn:eol-style = native
>
> Propchange: cfe/trunk/test/OpenMP/single_copyprivate_messages.cpp
>
> ------------------------------------------------------------------------------
>     svn:keywords = Author Date Id Rev URL
>
> Propchange: cfe/trunk/test/OpenMP/single_copyprivate_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=211886&r1=211885&r2=211886&view=diff
>
> ==============================================================================
> --- cfe/trunk/tools/libclang/CIndex.cpp (original)
> +++ cfe/trunk/tools/libclang/CIndex.cpp Fri Jun 27 05:37:06 2014
> @@ -1989,6 +1989,10 @@ void OMPClauseEnqueue::VisitOMPAlignedCl
>  void OMPClauseEnqueue::VisitOMPCopyinClause(const OMPCopyinClause *C) {
>    VisitOMPClauseList(C);
>  }
> +void
> +OMPClauseEnqueue::VisitOMPCopyprivateClause(const OMPCopyprivateClause
> *C) {
> +  VisitOMPClauseList(C);
> +}
>  }
>
>  void EnqueueVisitor::EnqueueChildren(const OMPClause *S) {
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140721/9f26872e/attachment.html>


More information about the cfe-commits mailing list