r258299 - [OPENMP 4.5] Allow to use non-static data members in non-static member functions in 'private' clause.

Alexey Bataev via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 20 01:07:55 PST 2016


Author: abataev
Date: Wed Jan 20 03:07:54 2016
New Revision: 258299

URL: http://llvm.org/viewvc/llvm-project?rev=258299&view=rev
Log:
[OPENMP 4.5] Allow to use non-static data members in non-static member functions in 'private' clause.
OpenMP 4.5 allows to use non-static members of current class in non-static member functions in 'private' clause. Patch adds initial support for privatizing data members.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaOpenMP.cpp
    cfe/trunk/test/OpenMP/distribute_ast_print.cpp
    cfe/trunk/test/OpenMP/for_ast_print.cpp
    cfe/trunk/test/OpenMP/for_private_messages.cpp
    cfe/trunk/test/OpenMP/for_simd_ast_print.cpp
    cfe/trunk/test/OpenMP/for_simd_private_messages.cpp
    cfe/trunk/test/OpenMP/parallel_ast_print.cpp
    cfe/trunk/test/OpenMP/parallel_for_ast_print.cpp
    cfe/trunk/test/OpenMP/parallel_for_private_messages.cpp
    cfe/trunk/test/OpenMP/parallel_for_simd_ast_print.cpp
    cfe/trunk/test/OpenMP/parallel_for_simd_private_messages.cpp
    cfe/trunk/test/OpenMP/parallel_sections_private_messages.cpp
    cfe/trunk/test/OpenMP/sections_private_messages.cpp
    cfe/trunk/test/OpenMP/simd_private_messages.cpp
    cfe/trunk/test/OpenMP/single_private_messages.cpp
    cfe/trunk/test/OpenMP/target_private_messages.cpp
    cfe/trunk/test/OpenMP/task_ast_print.cpp
    cfe/trunk/test/OpenMP/taskloop_private_messages.cpp
    cfe/trunk/test/OpenMP/taskloop_simd_private_messages.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=258299&r1=258298&r2=258299&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Jan 20 03:07:54 2016
@@ -7710,10 +7710,10 @@ def err_omp_reduction_incomplete_type :
   "a reduction list item with incomplete type %0">;
 def err_omp_unexpected_clause_value : Error<
   "expected %0 in OpenMP clause '%1'">;
-def err_omp_expected_var_name : Error<
-  "expected variable name">;
-def err_omp_expected_var_name_or_array_item : Error<
-  "expected variable name, array element or array section">;
+def err_omp_expected_var_name_member_expr : Error<
+  "expected variable name%select{| or data member of current class}0">;
+def err_omp_expected_var_name_member_expr_or_array_item : Error<
+  "expected variable name%select{|, data member of current class}0, array element or array section">;
 def note_omp_task_predetermined_firstprivate_here : Note<
   "predetermined as a firstprivate in a task construct here">;
 def err_omp_threadprivate_incomplete_type : Error<

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=258299&r1=258298&r2=258299&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Jan 20 03:07:54 2016
@@ -7778,23 +7778,23 @@ public:
   /// \brief Return true if the provided declaration \a VD should be captured by
   /// reference in the provided scope \a RSI. This will take into account the
   /// semantics of the directive and associated clauses.
-  bool IsOpenMPCapturedByRef(VarDecl *VD,
+  bool IsOpenMPCapturedByRef(ValueDecl *D,
                              const sema::CapturedRegionScopeInfo *RSI);
 
   /// \brief Check if the specified variable is used in one of the private
   /// clauses (private, firstprivate, lastprivate, reduction etc.) in OpenMP
   /// constructs.
-  bool IsOpenMPCapturedVar(VarDecl *VD);
+  bool IsOpenMPCapturedDecl(ValueDecl *D);
 
   /// \brief Check if the specified variable is used in 'private' clause.
   /// \param Level Relative level of nested OpenMP construct for that the check
   /// is performed.
-  bool isOpenMPPrivateVar(VarDecl *VD, unsigned Level);
+  bool isOpenMPPrivateDecl(ValueDecl *D, unsigned Level);
 
   /// \brief Check if the specified variable is captured  by 'target' directive.
   /// \param Level Relative level of nested OpenMP construct for that the check
   /// is performed.
-  bool isOpenMPTargetCapturedVar(VarDecl *VD, unsigned Level);
+  bool isOpenMPTargetCapturedDecl(ValueDecl *D, unsigned Level);
 
   ExprResult PerformOpenMPImplicitIntegerConversion(SourceLocation OpLoc,
                                                     Expr *Op);
@@ -7854,19 +7854,19 @@ public:
   StmtResult ActOnOpenMPSimdDirective(
       ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
       SourceLocation EndLoc,
-      llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA);
+      llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
   /// \brief Called on well-formed '\#pragma omp for' after parsing
   /// of the associated statement.
   StmtResult ActOnOpenMPForDirective(
       ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
       SourceLocation EndLoc,
-      llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA);
+      llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
   /// \brief Called on well-formed '\#pragma omp for simd' after parsing
   /// of the associated statement.
   StmtResult ActOnOpenMPForSimdDirective(
       ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
       SourceLocation EndLoc,
-      llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA);
+      llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
   /// \brief Called on well-formed '\#pragma omp sections' after parsing
   /// of the associated statement.
   StmtResult ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
@@ -7896,13 +7896,13 @@ public:
   StmtResult ActOnOpenMPParallelForDirective(
       ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
       SourceLocation EndLoc,
-      llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA);
+      llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
   /// \brief Called on well-formed '\#pragma omp parallel for simd' after
   /// parsing of the  associated statement.
   StmtResult ActOnOpenMPParallelForSimdDirective(
       ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
       SourceLocation EndLoc,
-      llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA);
+      llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
   /// \brief Called on well-formed '\#pragma omp parallel sections' after
   /// parsing of the  associated statement.
   StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
@@ -7980,19 +7980,19 @@ public:
   StmtResult ActOnOpenMPTaskLoopDirective(
       ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
       SourceLocation EndLoc,
-      llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA);
+      llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
   /// \brief Called on well-formed '\#pragma omp taskloop simd' after parsing of
   /// the associated statement.
   StmtResult ActOnOpenMPTaskLoopSimdDirective(
       ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
       SourceLocation EndLoc,
-      llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA);
+      llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
   /// \brief Called on well-formed '\#pragma omp distribute' after parsing
   /// of the associated statement.
   StmtResult ActOnOpenMPDistributeDirective(
       ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
       SourceLocation EndLoc,
-      llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA);
+      llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA);
 
   OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
                                          Expr *Expr,

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=258299&r1=258298&r2=258299&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Jan 20 03:07:54 2016
@@ -12894,7 +12894,7 @@ static bool captureInCapturedRegion(Capt
   // Using an LValue reference type is consistent with Lambdas (see below).
   if (S.getLangOpts().OpenMP) {
     ByRef = S.IsOpenMPCapturedByRef(Var, RSI);
-    if (S.IsOpenMPCapturedVar(Var))
+    if (S.IsOpenMPCapturedDecl(Var))
       DeclRefType = DeclRefType.getUnqualifiedType();
   }
 
@@ -13085,7 +13085,7 @@ bool Sema::tryCaptureVariable(
   // Capture global variables if it is required to use private copy of this
   // variable.
   bool IsGlobal = !Var->hasLocalStorage();
-  if (IsGlobal && !(LangOpts.OpenMP && IsOpenMPCapturedVar(Var)))
+  if (IsGlobal && !(LangOpts.OpenMP && IsOpenMPCapturedDecl(Var)))
     return true;
 
   // Walk up the stack to determine whether we can capture the variable,
@@ -13280,14 +13280,14 @@ bool Sema::tryCaptureVariable(
         // just break here. Similarly, global variables that are captured in a
         // target region should not be captured outside the scope of the region.
         if (RSI->CapRegionKind == CR_OpenMP) {
-          auto isTargetCap = isOpenMPTargetCapturedVar(Var, OpenMPLevel);
+          auto isTargetCap = isOpenMPTargetCapturedDecl(Var, OpenMPLevel);
           // When we detect target captures we are looking from inside the
           // target region, therefore we need to propagate the capture from the
           // enclosing region. Therefore, the capture is not initially nested.
           if (isTargetCap)
             FunctionScopesIndex--;
 
-          if (isTargetCap || isOpenMPPrivateVar(Var, OpenMPLevel)) {
+          if (isTargetCap || isOpenMPPrivateDecl(Var, OpenMPLevel)) {
             Nested = !isTargetCap;
             DeclRefType = DeclRefType.getUnqualifiedType();
             CaptureType = Context.getLValueReferenceType(DeclRefType);

Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=258299&r1=258298&r2=258299&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Wed Jan 20 03:07:54 2016
@@ -70,7 +70,7 @@ public:
   struct DSAVarData {
     OpenMPDirectiveKind DKind;
     OpenMPClauseKind CKind;
-    DeclRefExpr *RefExpr;
+    Expr *RefExpr;
     SourceLocation ImplicitDSALoc;
     DSAVarData()
         : DKind(OMPD_unknown), CKind(OMPC_unknown), RefExpr(nullptr),
@@ -85,12 +85,12 @@ public:
 private:
   struct DSAInfo {
     OpenMPClauseKind Attributes;
-    DeclRefExpr *RefExpr;
+    Expr *RefExpr;
   };
-  typedef llvm::SmallDenseMap<VarDecl *, DSAInfo, 64> DeclSAMapTy;
-  typedef llvm::SmallDenseMap<VarDecl *, DeclRefExpr *, 64> AlignedMapTy;
-  typedef llvm::DenseMap<VarDecl *, unsigned> LoopControlVariablesMapTy;
-  typedef llvm::SmallDenseMap<VarDecl *, MapInfo, 64> MappedDeclsTy;
+  typedef llvm::SmallDenseMap<ValueDecl *, DSAInfo, 64> DeclSAMapTy;
+  typedef llvm::SmallDenseMap<ValueDecl *, Expr *, 64> AlignedMapTy;
+  typedef llvm::DenseMap<ValueDecl *, unsigned> LoopControlVariablesMapTy;
+  typedef llvm::SmallDenseMap<ValueDecl *, MapInfo, 64> MappedDeclsTy;
   typedef llvm::StringMap<std::pair<OMPCriticalDirective *, llvm::APSInt>>
       CriticalsWithHintsTy;
 
@@ -139,7 +139,7 @@ private:
 
   typedef SmallVector<SharingMapTy, 8>::reverse_iterator reverse_iterator;
 
-  DSAVarData getDSA(StackTy::reverse_iterator Iter, VarDecl *D);
+  DSAVarData getDSA(StackTy::reverse_iterator Iter, ValueDecl *D);
 
   /// \brief Checks if the variable is a local for OpenMP region.
   bool isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter);
@@ -179,49 +179,48 @@ public:
   /// \brief If 'aligned' declaration for given variable \a D was not seen yet,
   /// add it and return NULL; otherwise return previous occurrence's expression
   /// for diagnostics.
-  DeclRefExpr *addUniqueAligned(VarDecl *D, DeclRefExpr *NewDE);
+  Expr *addUniqueAligned(ValueDecl *D, Expr *NewDE);
 
   /// \brief Register specified variable as loop control variable.
-  void addLoopControlVariable(VarDecl *D);
+  void addLoopControlVariable(ValueDecl *D);
   /// \brief Check if the specified variable is a loop control variable for
   /// current region.
   /// \return The index of the loop control variable in the list of associated
   /// for-loops (from outer to inner).
-  unsigned isLoopControlVariable(VarDecl *D);
+  unsigned isLoopControlVariable(ValueDecl *D);
   /// \brief Check if the specified variable is a loop control variable for
   /// parent region.
   /// \return The index of the loop control variable in the list of associated
   /// for-loops (from outer to inner).
-  unsigned isParentLoopControlVariable(VarDecl *D);
+  unsigned isParentLoopControlVariable(ValueDecl *D);
   /// \brief Get the loop control variable for the I-th loop (or nullptr) in
   /// parent directive.
-  VarDecl *getParentLoopControlVariable(unsigned I);
+  ValueDecl *getParentLoopControlVariable(unsigned I);
 
   /// \brief Adds explicit data sharing attribute to the specified declaration.
-  void addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A);
+  void addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A);
 
   /// \brief Returns data sharing attributes from top of the stack for the
   /// specified declaration.
-  DSAVarData getTopDSA(VarDecl *D, bool FromParent);
+  DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
   /// \brief Returns data-sharing attributes for the specified declaration.
-  DSAVarData getImplicitDSA(VarDecl *D, bool FromParent);
+  DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent);
   /// \brief Checks if the specified variables has data-sharing attributes which
   /// match specified \a CPred predicate in any directive which matches \a DPred
   /// predicate.
   template <class ClausesPredicate, class DirectivesPredicate>
-  DSAVarData hasDSA(VarDecl *D, ClausesPredicate CPred,
+  DSAVarData hasDSA(ValueDecl *D, ClausesPredicate CPred,
                     DirectivesPredicate DPred, bool FromParent);
   /// \brief Checks if the specified variables has data-sharing attributes which
   /// match specified \a CPred predicate in any innermost directive which
   /// matches \a DPred predicate.
   template <class ClausesPredicate, class DirectivesPredicate>
-  DSAVarData hasInnermostDSA(VarDecl *D, ClausesPredicate CPred,
-                             DirectivesPredicate DPred,
-                             bool FromParent);
+  DSAVarData hasInnermostDSA(ValueDecl *D, ClausesPredicate CPred,
+                             DirectivesPredicate DPred, bool FromParent);
   /// \brief Checks if the specified variables has explicit data-sharing
   /// attributes which match specified \a CPred predicate at the specified
   /// OpenMP region.
-  bool hasExplicitDSA(VarDecl *D,
+  bool hasExplicitDSA(ValueDecl *D,
                       const llvm::function_ref<bool(OpenMPClauseKind)> &CPred,
                       unsigned Level);
 
@@ -338,7 +337,7 @@ public:
   Scope *getCurScope() { return Stack.back().CurScope; }
   SourceLocation getConstructLoc() { return Stack.back().ConstructLoc; }
 
-  MapInfo getMapInfoForVar(VarDecl *VD) {
+  MapInfo getMapInfoForVar(ValueDecl *VD) {
     MapInfo VarMI = {0};
     for (auto Cnt = Stack.size() - 1; Cnt > 0; --Cnt) {
       if (Stack[Cnt].MappedDecls.count(VD)) {
@@ -349,13 +348,13 @@ public:
     return VarMI;
   }
 
-  void addMapInfoForVar(VarDecl *VD, MapInfo MI) {
+  void addMapInfoForVar(ValueDecl *VD, MapInfo MI) {
     if (Stack.size() > 1) {
       Stack.back().MappedDecls[VD] = MI;
     }
   }
 
-  MapInfo IsMappedInCurrentRegion(VarDecl *VD) {
+  MapInfo IsMappedInCurrentRegion(ValueDecl *VD) {
     assert(Stack.size() > 1 && "Target level is 0");
     MapInfo VarMI = {0};
     if (Stack.size() > 1 && Stack.back().MappedDecls.count(VD)) {
@@ -371,9 +370,25 @@ bool isParallelOrTaskRegion(OpenMPDirect
 }
 } // namespace
 
+static ValueDecl *getCanonicalDecl(ValueDecl *D) {
+  auto *VD = dyn_cast<VarDecl>(D);
+  auto *FD = dyn_cast<FieldDecl>(D);
+  if (VD  != nullptr) {
+    VD = VD->getCanonicalDecl();
+    D = VD;
+  } else {
+    assert(FD);
+    FD = FD->getCanonicalDecl();
+    D = FD;
+  }
+  return D;
+}
+
 DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter,
-                                          VarDecl *D) {
-  D = D->getCanonicalDecl();
+                                          ValueDecl *D) {
+  D = getCanonicalDecl(D);
+  auto *VD = dyn_cast<VarDecl>(D);
+  auto *FD = dyn_cast<FieldDecl>(D);
   DSAVarData DVar;
   if (Iter == std::prev(Stack.rend())) {
     // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
@@ -381,14 +396,18 @@ DSAStackTy::DSAVarData DSAStackTy::getDS
     //  File-scope or namespace-scope variables referenced in called routines
     //  in the region are shared unless they appear in a threadprivate
     //  directive.
-    if (!D->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(D))
+    if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(D))
       DVar.CKind = OMPC_shared;
 
     // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
     // in a region but not in construct]
     //  Variables with static storage duration that are declared in called
     //  routines in the region are shared.
-    if (D->hasGlobalStorage())
+    if (VD && VD->hasGlobalStorage())
+      DVar.CKind = OMPC_shared;
+
+    // Non-static data members are shared by default.
+    if (FD)
       DVar.CKind = OMPC_shared;
 
     return DVar;
@@ -399,8 +418,8 @@ DSAStackTy::DSAVarData DSAStackTy::getDS
   // in a Construct, C/C++, predetermined, p.1]
   // Variables with automatic storage duration that are declared in a scope
   // inside the construct are private.
-  if (isOpenMPLocal(D, Iter) && D->isLocalVarDecl() &&
-      (D->getStorageClass() == SC_Auto || D->getStorageClass() == SC_None)) {
+  if (VD && isOpenMPLocal(VD, Iter) && VD->isLocalVarDecl() &&
+      (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
     DVar.CKind = OMPC_private;
     return DVar;
   }
@@ -476,9 +495,9 @@ DSAStackTy::DSAVarData DSAStackTy::getDS
   return getDSA(std::next(Iter), D);
 }
 
-DeclRefExpr *DSAStackTy::addUniqueAligned(VarDecl *D, DeclRefExpr *NewDE) {
+Expr *DSAStackTy::addUniqueAligned(ValueDecl *D, Expr *NewDE) {
   assert(Stack.size() > 1 && "Data sharing attributes stack is empty");
-  D = D->getCanonicalDecl();
+  D = getCanonicalDecl(D);
   auto It = Stack.back().AlignedMap.find(D);
   if (It == Stack.back().AlignedMap.end()) {
     assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
@@ -491,27 +510,27 @@ DeclRefExpr *DSAStackTy::addUniqueAligne
   return nullptr;
 }
 
-void DSAStackTy::addLoopControlVariable(VarDecl *D) {
+void DSAStackTy::addLoopControlVariable(ValueDecl *D) {
   assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");
-  D = D->getCanonicalDecl();
+  D = getCanonicalDecl(D);
   Stack.back().LCVMap.insert(std::make_pair(D, Stack.back().LCVMap.size() + 1));
 }
 
-unsigned DSAStackTy::isLoopControlVariable(VarDecl *D) {
+unsigned DSAStackTy::isLoopControlVariable(ValueDecl *D) {
   assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");
-  D = D->getCanonicalDecl();
+  D = getCanonicalDecl(D);
   return Stack.back().LCVMap.count(D) > 0 ? Stack.back().LCVMap[D] : 0;
 }
 
-unsigned DSAStackTy::isParentLoopControlVariable(VarDecl *D) {
+unsigned DSAStackTy::isParentLoopControlVariable(ValueDecl *D) {
   assert(Stack.size() > 2 && "Data-sharing attributes stack is empty");
-  D = D->getCanonicalDecl();
+  D = getCanonicalDecl(D);
   return Stack[Stack.size() - 2].LCVMap.count(D) > 0
              ? Stack[Stack.size() - 2].LCVMap[D]
              : 0;
 }
 
-VarDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) {
+ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) {
   assert(Stack.size() > 2 && "Data-sharing attributes stack is empty");
   if (Stack[Stack.size() - 2].LCVMap.size() < I)
     return nullptr;
@@ -522,8 +541,8 @@ VarDecl *DSAStackTy::getParentLoopContro
   return nullptr;
 }
 
-void DSAStackTy::addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A) {
-  D = D->getCanonicalDecl();
+void DSAStackTy::addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A) {
+  D = getCanonicalDecl(D);
   if (A == OMPC_threadprivate) {
     Stack[0].SharingMap[D].Attributes = A;
     Stack[0].SharingMap[D].RefExpr = E;
@@ -581,20 +600,21 @@ static DeclRefExpr *buildDeclRefExpr(Sem
                              VK_LValue);
 }
 
-DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) {
-  D = D->getCanonicalDecl();
+DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, bool FromParent) {
+  D = getCanonicalDecl(D);
   DSAVarData DVar;
 
   // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
   // in a Construct, C/C++, predetermined, p.1]
   //  Variables appearing in threadprivate directives are threadprivate.
-  if ((D->getTLSKind() != VarDecl::TLS_None &&
-       !(D->hasAttr<OMPThreadPrivateDeclAttr>() &&
+  auto *VD = dyn_cast<VarDecl>(D);
+  if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
+       !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
          SemaRef.getLangOpts().OpenMPUseTLS &&
          SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
-      (D->getStorageClass() == SC_Register && D->hasAttr<AsmLabelAttr>() &&
-       !D->isLocalVarDecl())) {
-    addDSA(D, buildDeclRefExpr(SemaRef, D, D->getType().getNonReferenceType(),
+      (VD && VD->getStorageClass() == SC_Register &&
+       VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
+    addDSA(D, buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
                                D->getLocation()),
            OMPC_threadprivate);
   }
@@ -611,7 +631,7 @@ DSAStackTy::DSAVarData DSAStackTy::getTo
   // in a Construct, C/C++, predetermined, p.7]
   //  Variables with static storage duration that are declared in a scope
   //  inside the construct are shared.
-  if (D->isStaticDataMember()) {
+  if (VD && VD->isStaticDataMember()) {
     DSAVarData DVarTemp =
         hasDSA(D, isOpenMPPrivate, MatchesAlways(), FromParent);
     if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
@@ -663,8 +683,9 @@ DSAStackTy::DSAVarData DSAStackTy::getTo
   return DVar;
 }
 
-DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(VarDecl *D, bool FromParent) {
-  D = D->getCanonicalDecl();
+DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
+                                                  bool FromParent) {
+  D = getCanonicalDecl(D);
   auto StartI = Stack.rbegin();
   auto EndI = std::prev(Stack.rend());
   if (FromParent && StartI != EndI) {
@@ -674,10 +695,10 @@ DSAStackTy::DSAVarData DSAStackTy::getIm
 }
 
 template <class ClausesPredicate, class DirectivesPredicate>
-DSAStackTy::DSAVarData DSAStackTy::hasDSA(VarDecl *D, ClausesPredicate CPred,
+DSAStackTy::DSAVarData DSAStackTy::hasDSA(ValueDecl *D, ClausesPredicate CPred,
                                           DirectivesPredicate DPred,
                                           bool FromParent) {
-  D = D->getCanonicalDecl();
+  D = getCanonicalDecl(D);
   auto StartI = std::next(Stack.rbegin());
   auto EndI = std::prev(Stack.rend());
   if (FromParent && StartI != EndI) {
@@ -695,9 +716,9 @@ DSAStackTy::DSAVarData DSAStackTy::hasDS
 
 template <class ClausesPredicate, class DirectivesPredicate>
 DSAStackTy::DSAVarData
-DSAStackTy::hasInnermostDSA(VarDecl *D, ClausesPredicate CPred,
+DSAStackTy::hasInnermostDSA(ValueDecl *D, ClausesPredicate CPred,
                             DirectivesPredicate DPred, bool FromParent) {
-  D = D->getCanonicalDecl();
+  D = getCanonicalDecl(D);
   auto StartI = std::next(Stack.rbegin());
   auto EndI = std::prev(Stack.rend());
   if (FromParent && StartI != EndI) {
@@ -715,13 +736,13 @@ DSAStackTy::hasInnermostDSA(VarDecl *D,
 }
 
 bool DSAStackTy::hasExplicitDSA(
-    VarDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> &CPred,
+    ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> &CPred,
     unsigned Level) {
   if (CPred(ClauseKindMode))
     return true;
   if (isClauseParsingMode())
     ++Level;
-  D = D->getCanonicalDecl();
+  D = getCanonicalDecl(D);
   auto StartI = Stack.rbegin();
   auto EndI = std::prev(Stack.rend());
   if (std::distance(StartI, EndI) <= (int)Level)
@@ -771,7 +792,7 @@ void Sema::InitDataSharingAttributesStac
 
 #define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
 
-bool Sema::IsOpenMPCapturedByRef(VarDecl *VD,
+bool Sema::IsOpenMPCapturedByRef(ValueDecl *D,
                                  const CapturedRegionScopeInfo *RSI) {
   assert(LangOpts.OpenMP && "OpenMP is not allowed");
 
@@ -780,7 +801,7 @@ bool Sema::IsOpenMPCapturedByRef(VarDecl
 
   // Find the directive that is associated with the provided scope.
   auto DKind = DSAStack->getDirectiveForScope(RSI->TheScope);
-  auto Ty = VD->getType();
+  auto Ty = D->getType();
 
   if (isOpenMPTargetDirective(DKind)) {
     // This table summarizes how a given variable should be passed to the device
@@ -853,15 +874,15 @@ bool Sema::IsOpenMPCapturedByRef(VarDecl
   if (!IsByRef &&
       (Ctx.getTypeSizeInChars(Ty) >
            Ctx.getTypeSizeInChars(Ctx.getUIntPtrType()) ||
-       Ctx.getDeclAlign(VD) > Ctx.getTypeAlignInChars(Ctx.getUIntPtrType())))
+       Ctx.getDeclAlign(D) > Ctx.getTypeAlignInChars(Ctx.getUIntPtrType())))
     IsByRef = true;
 
   return IsByRef;
 }
 
-bool Sema::IsOpenMPCapturedVar(VarDecl *VD) {
+bool Sema::IsOpenMPCapturedDecl(ValueDecl *D) {
   assert(LangOpts.OpenMP && "OpenMP is not allowed");
-  VD = VD->getCanonicalDecl();
+  D = getCanonicalDecl(D);
 
   // If we are attempting to capture a global variable in a directive with
   // 'target' we return true so that this global is also mapped to the device.
@@ -870,7 +891,8 @@ bool Sema::IsOpenMPCapturedVar(VarDecl *
   // then it should not be captured. Therefore, an extra check has to be
   // inserted here once support for 'declare target' is added.
   //
-  if (!VD->hasLocalStorage()) {
+  auto *VD = dyn_cast<VarDecl>(D);
+  if (VD && !VD->hasLocalStorage()) {
     if (DSAStack->getCurrentDirective() == OMPD_target &&
         !DSAStack->isClauseParsingMode()) {
       return true;
@@ -889,32 +911,33 @@ bool Sema::IsOpenMPCapturedVar(VarDecl *
   if (DSAStack->getCurrentDirective() != OMPD_unknown &&
       (!DSAStack->isClauseParsingMode() ||
        DSAStack->getParentDirective() != OMPD_unknown)) {
-    if (DSAStack->isLoopControlVariable(VD) ||
-        (VD->hasLocalStorage() &&
+    if (DSAStack->isLoopControlVariable(D) ||
+        (VD && VD->hasLocalStorage() &&
          isParallelOrTaskRegion(DSAStack->getCurrentDirective())) ||
-        DSAStack->isForceVarCapturing())
+        (VD && DSAStack->isForceVarCapturing()))
       return true;
-    auto DVarPrivate = DSAStack->getTopDSA(VD, DSAStack->isClauseParsingMode());
+    auto DVarPrivate = DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
     if (DVarPrivate.CKind != OMPC_unknown && isOpenMPPrivate(DVarPrivate.CKind))
       return true;
-    DVarPrivate = DSAStack->hasDSA(VD, isOpenMPPrivate, MatchesAlways(),
+    DVarPrivate = DSAStack->hasDSA(D, isOpenMPPrivate, MatchesAlways(),
                                    DSAStack->isClauseParsingMode());
     return DVarPrivate.CKind != OMPC_unknown;
   }
   return false;
 }
 
-bool Sema::isOpenMPPrivateVar(VarDecl *VD, unsigned Level) {
+bool Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level) {
   assert(LangOpts.OpenMP && "OpenMP is not allowed");
   return DSAStack->hasExplicitDSA(
-      VD, [](OpenMPClauseKind K) -> bool { return K == OMPC_private; }, Level);
+      D, [](OpenMPClauseKind K) -> bool { return K == OMPC_private; }, Level);
 }
 
-bool Sema::isOpenMPTargetCapturedVar(VarDecl *VD, unsigned Level) {
+bool Sema::isOpenMPTargetCapturedDecl(ValueDecl *D, unsigned Level) {
   assert(LangOpts.OpenMP && "OpenMP is not allowed");
   // Return true if the current level is no longer enclosed in a target region.
 
-  return !VD->hasLocalStorage() &&
+  auto *VD = dyn_cast<VarDecl>(D);
+  return VD && !VD->hasLocalStorage() &&
          DSAStack->hasExplicitDirective(isOpenMPTargetDirective, Level);
 }
 
@@ -950,9 +973,20 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDi
             PrivateCopies.push_back(nullptr);
             continue;
           }
-          auto *VD = cast<VarDecl>(cast<DeclRefExpr>(DE)->getDecl());
-          QualType Type = VD->getType().getNonReferenceType();
-          auto DVar = DSAStack->getTopDSA(VD, false);
+          DE = DE->IgnoreParens();
+          VarDecl *VD = nullptr;
+          FieldDecl *FD = nullptr;
+          ValueDecl *D;
+          if (auto *DRE = dyn_cast<DeclRefExpr>(DE)) {
+            VD = cast<VarDecl>(DRE->getDecl());
+            D = VD;
+          } else {
+            assert(isa<MemberExpr>(DE));
+            FD = cast<FieldDecl>(cast<MemberExpr>(DE)->getMemberDecl());
+            D = FD;
+          }
+          QualType Type = D->getType().getNonReferenceType();
+          auto DVar = DSAStack->getTopDSA(D, false);
           if (DVar.CKind == OMPC_lastprivate) {
             // Generate helper private variable and initialize it with the
             // default value. The address of the original variable is replaced
@@ -961,7 +995,7 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDi
             // region uses original variable for proper diagnostics.
             auto *VDPrivate = buildVarDecl(
                 *this, DE->getExprLoc(), Type.getUnqualifiedType(),
-                VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr);
+                D->getName(), D->hasAttrs() ? &D->getAttrs() : nullptr);
             ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto=*/false);
             if (VDPrivate->isInvalidDecl())
               continue;
@@ -974,9 +1008,8 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDi
           }
         }
         // Set initializers to private copies if no errors were found.
-        if (PrivateCopies.size() == Clause->varlist_size()) {
+        if (PrivateCopies.size() == Clause->varlist_size())
           Clause->setPrivateCopies(PrivateCopies);
-        }
       }
     }
   }
@@ -1251,7 +1284,7 @@ Sema::CheckOMPThreadPrivateDecl(SourceLo
 }
 
 static void ReportOriginalDSA(Sema &SemaRef, DSAStackTy *Stack,
-                              const VarDecl *VD, DSAStackTy::DSAVarData DVar,
+                              const ValueDecl *D, DSAStackTy::DSAVarData DVar,
                               bool IsLoopIterVar = false) {
   if (DVar.RefExpr) {
     SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
@@ -1271,7 +1304,8 @@ static void ReportOriginalDSA(Sema &Sema
     PDSA_Implicit
   } Reason = PDSA_Implicit;
   bool ReportHint = false;
-  auto ReportLoc = VD->getLocation();
+  auto ReportLoc = D->getLocation();
+  auto *VD = dyn_cast<VarDecl>(D);
   if (IsLoopIterVar) {
     if (DVar.CKind == OMPC_private)
       Reason = PDSA_LoopIterVarPrivate;
@@ -1282,15 +1316,15 @@ static void ReportOriginalDSA(Sema &Sema
   } else if (DVar.DKind == OMPD_task && DVar.CKind == OMPC_firstprivate) {
     Reason = PDSA_TaskVarFirstprivate;
     ReportLoc = DVar.ImplicitDSALoc;
-  } else if (VD->isStaticLocal())
+  } else if (VD && VD->isStaticLocal())
     Reason = PDSA_StaticLocalVarShared;
-  else if (VD->isStaticDataMember())
+  else if (VD && VD->isStaticDataMember())
     Reason = PDSA_StaticMemberShared;
-  else if (VD->isFileVarDecl())
+  else if (VD && VD->isFileVarDecl())
     Reason = PDSA_GlobalVarShared;
-  else if (VD->getType().isConstant(SemaRef.getASTContext()))
+  else if (D->getType().isConstant(SemaRef.getASTContext()))
     Reason = PDSA_ConstVarShared;
-  else if (VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
+  else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
     ReportHint = true;
     Reason = PDSA_LocalVarPrivate;
   }
@@ -1311,7 +1345,7 @@ class DSAAttrChecker : public StmtVisito
   bool ErrorFound;
   CapturedStmt *CS;
   llvm::SmallVector<Expr *, 8> ImplicitFirstprivate;
-  llvm::DenseMap<VarDecl *, Expr *> VarsWithInheritedDSA;
+  llvm::DenseMap<ValueDecl *, Expr *> VarsWithInheritedDSA;
 
 public:
   void VisitDeclRefExpr(DeclRefExpr *E) {
@@ -1361,6 +1395,44 @@ public:
         ImplicitFirstprivate.push_back(E);
     }
   }
+  void VisitMemberExpr(MemberExpr *E) {
+    if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
+      if (auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl())) {
+        auto DVar = Stack->getTopDSA(FD, false);
+        // Check if the variable has explicit DSA set and stop analysis if it
+        // so.
+        if (DVar.RefExpr)
+          return;
+
+        auto ELoc = E->getExprLoc();
+        auto DKind = Stack->getCurrentDirective();
+        // OpenMP [2.9.3.6, Restrictions, p.2]
+        //  A list item that appears in a reduction clause of the innermost
+        //  enclosing worksharing or parallel construct may not be accessed in
+        //  an
+        //  explicit task.
+        DVar =
+            Stack->hasInnermostDSA(FD, MatchesAnyClause(OMPC_reduction),
+                                   [](OpenMPDirectiveKind K) -> bool {
+                                     return isOpenMPParallelDirective(K) ||
+                                            isOpenMPWorksharingDirective(K) ||
+                                            isOpenMPTeamsDirective(K);
+                                   },
+                                   false);
+        if (DKind == OMPD_task && DVar.CKind == OMPC_reduction) {
+          ErrorFound = true;
+          SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
+          ReportOriginalDSA(SemaRef, Stack, FD, DVar);
+          return;
+        }
+
+        // Define implicit data-sharing attributes for task.
+        DVar = Stack->getImplicitDSA(FD, false);
+        if (DKind == OMPD_task && DVar.CKind != OMPC_shared)
+          ImplicitFirstprivate.push_back(E);
+      }
+    }
+  }
   void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
     for (auto *C : S->clauses()) {
       // Skip analysis of arguments of implicitly defined firstprivate clause
@@ -1381,7 +1453,7 @@ public:
 
   bool isErrorFound() { return ErrorFound; }
   ArrayRef<Expr *> getImplicitFirstprivate() { return ImplicitFirstprivate; }
-  llvm::DenseMap<VarDecl *, Expr *> &getVarsWithInheritedDSA() {
+  llvm::DenseMap<ValueDecl *, Expr *> &getVarsWithInheritedDSA() {
     return VarsWithInheritedDSA;
   }
 
@@ -2625,7 +2697,7 @@ StmtResult Sema::ActOnOpenMPExecutableDi
     return StmtError();
 
   llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
-  llvm::DenseMap<VarDecl *, Expr *> VarsWithInheritedDSA;
+  llvm::DenseMap<ValueDecl *, Expr *> VarsWithInheritedDSA;
   bool ErrorFound = false;
   ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
   if (AStmt) {
@@ -3546,7 +3618,7 @@ static bool CheckOpenMPIterationSpace(
     OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
     unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
     Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr,
-    llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA,
+    llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA,
     LoopIterationSpace &ResultIterSpace) {
   // OpenMP [2.6, Canonical Loop Form]
   //   for (init-expr; test-expr; incr-expr) structured-block
@@ -3799,7 +3871,7 @@ static unsigned
 CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
                 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
                 DSAStackTy &DSA,
-                llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA,
+                llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA,
                 OMPLoopDirective::HelperExprs &Built) {
   unsigned NestedLoopCount = 1;
   if (CollapseLoopCountExpr) {
@@ -4239,7 +4311,7 @@ static bool checkSimdlenSafelenValues(Se
 StmtResult Sema::ActOnOpenMPSimdDirective(
     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
     SourceLocation EndLoc,
-    llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+    llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
   if (!AStmt)
     return StmtError();
 
@@ -4292,7 +4364,7 @@ StmtResult Sema::ActOnOpenMPSimdDirectiv
 StmtResult Sema::ActOnOpenMPForDirective(
     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
     SourceLocation EndLoc,
-    llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+    llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
   if (!AStmt)
     return StmtError();
 
@@ -4327,7 +4399,7 @@ StmtResult Sema::ActOnOpenMPForDirective
 StmtResult Sema::ActOnOpenMPForSimdDirective(
     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
     SourceLocation EndLoc,
-    llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+    llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
   if (!AStmt)
     return StmtError();
 
@@ -4536,7 +4608,7 @@ StmtResult Sema::ActOnOpenMPCriticalDire
 StmtResult Sema::ActOnOpenMPParallelForDirective(
     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
     SourceLocation EndLoc,
-    llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+    llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
   if (!AStmt)
     return StmtError();
 
@@ -4580,7 +4652,7 @@ StmtResult Sema::ActOnOpenMPParallelForD
 StmtResult Sema::ActOnOpenMPParallelForSimdDirective(
     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
     SourceLocation EndLoc,
-    llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+    llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
   if (!AStmt)
     return StmtError();
 
@@ -5674,7 +5746,7 @@ static bool checkGrainsizeNumTasksClause
 StmtResult Sema::ActOnOpenMPTaskLoopDirective(
     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
     SourceLocation EndLoc,
-    llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+    llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
   if (!AStmt)
     return StmtError();
 
@@ -5706,7 +5778,7 @@ StmtResult Sema::ActOnOpenMPTaskLoopDire
 StmtResult Sema::ActOnOpenMPTaskLoopSimdDirective(
     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
     SourceLocation EndLoc,
-    llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+    llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
   if (!AStmt)
     return StmtError();
 
@@ -5738,7 +5810,7 @@ StmtResult Sema::ActOnOpenMPTaskLoopSimd
 StmtResult Sema::ActOnOpenMPDistributeDirective(
     ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
     SourceLocation EndLoc,
-    llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+    llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
   if (!AStmt)
     return StmtError();
 
@@ -6604,7 +6676,8 @@ OMPClause *Sema::ActOnOpenMPPrivateClaus
   SmallVector<Expr *, 8> PrivateCopies;
   for (auto &RefExpr : VarList) {
     assert(RefExpr && "NULL expr in OpenMP private clause.");
-    if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
+    if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
+        RefExpr->containsUnexpandedParameterPack()) {
       // It will be analyzed later.
       Vars.push_back(RefExpr);
       PrivateCopies.push_back(nullptr);
@@ -6617,29 +6690,26 @@ OMPClause *Sema::ActOnOpenMPPrivateClaus
     // OpenMP  [2.9.3.3, Restrictions, p.1]
     //  A variable that is part of another variable (as an array or
     //  structure element) cannot appear in a private clause.
-    DeclRefExpr *DE = dyn_cast_or_null<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);
-      PrivateCopies.push_back(nullptr);
+    auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr->IgnoreParens());
+    auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr->IgnoreParens());
+    if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
+        (getCurrentThisType().isNull() || !ME ||
+         !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
+         !isa<FieldDecl>(ME->getMemberDecl()))) {
+      Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
+          << (getCurrentThisType().isNull() ? 0 : 1)
+          << RefExpr->getSourceRange();
       continue;
     }
+    ValueDecl *D = DE ? DE->getDecl() : ME->getMemberDecl();
+    QualType Type = D->getType();
+    auto *VD = dyn_cast<VarDecl>(D);
 
     // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
     //  A variable that appears in a private clause must not have an incomplete
     //  type or a reference type.
-    if (RequireCompleteType(ELoc, Type,
-                            diag::err_omp_private_incomplete_type)) {
+    if (RequireCompleteType(ELoc, Type, diag::err_omp_private_incomplete_type))
       continue;
-    }
     Type = Type.getNonReferenceType();
 
     // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
@@ -6649,11 +6719,11 @@ OMPClause *Sema::ActOnOpenMPPrivateClaus
     //  listed below. For these exceptions only, listing a predetermined
     //  variable in a data-sharing attribute clause is allowed and overrides
     //  the variable's predetermined data-sharing attributes.
-    DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false);
+    DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, false);
     if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
       Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
                                           << getOpenMPClauseName(OMPC_private);
-      ReportOriginalDSA(*this, DSAStack, VD, DVar);
+      ReportOriginalDSA(*this, DSAStack, D, DVar);
       continue;
     }
 
@@ -6664,10 +6734,11 @@ OMPClause *Sema::ActOnOpenMPPrivateClaus
           << getOpenMPClauseName(OMPC_private) << Type
           << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
       bool IsDecl =
+          !VD ||
           VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
-      Diag(VD->getLocation(),
+      Diag(D->getLocation(),
            IsDecl ? diag::note_previous_decl : diag::note_defined_here)
-          << VD;
+          << D;
       continue;
     }
 
@@ -6681,16 +6752,16 @@ OMPClause *Sema::ActOnOpenMPPrivateClaus
     // IdResolver, so the code in the OpenMP region uses original variable for
     // proper diagnostics.
     Type = Type.getUnqualifiedType();
-    auto VDPrivate = buildVarDecl(*this, DE->getExprLoc(), Type, VD->getName(),
-                                  VD->hasAttrs() ? &VD->getAttrs() : nullptr);
+    auto VDPrivate = buildVarDecl(*this, ELoc, Type, D->getName(),
+                                  D->hasAttrs() ? &D->getAttrs() : nullptr);
     ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto=*/false);
     if (VDPrivate->isInvalidDecl())
       continue;
     auto VDPrivateRefExpr = buildDeclRefExpr(
-        *this, VDPrivate, DE->getType().getUnqualifiedType(), DE->getExprLoc());
+        *this, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
 
-    DSAStack->addDSA(VD, DE, OMPC_private);
-    Vars.push_back(DE);
+    DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private);
+    Vars.push_back(RefExpr->IgnoreParens());
     PrivateCopies.push_back(VDPrivateRefExpr);
   }
 
@@ -6754,7 +6825,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivate
     //  structure element) cannot appear in a private clause.
     DeclRefExpr *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
     if (!DE || !isa<VarDecl>(DE->getDecl())) {
-      Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange();
+      Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
+          << 0 << RefExpr->getSourceRange();
       continue;
     }
     Decl *D = DE->getDecl();
@@ -7017,7 +7089,8 @@ OMPClause *Sema::ActOnOpenMPLastprivateC
     //  element) cannot appear in a lastprivate clause.
     DeclRefExpr *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
     if (!DE || !isa<VarDecl>(DE->getDecl())) {
-      Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange();
+      Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
+          << 0 << RefExpr->getSourceRange();
       continue;
     }
     Decl *D = DE->getDecl();
@@ -7156,7 +7229,8 @@ OMPClause *Sema::ActOnOpenMPSharedClause
     //  of a C++ class.
     DeclRefExpr *DE = dyn_cast<DeclRefExpr>(RefExpr);
     if (!DE || !isa<VarDecl>(DE->getDecl())) {
-      Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange();
+      Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
+          << 0 << RefExpr->getSourceRange();
       continue;
     }
     Decl *D = DE->getDecl();
@@ -7372,7 +7446,8 @@ OMPClause *Sema::ActOnOpenMPReductionCla
     auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr);
     auto *OASE = dyn_cast<OMPArraySectionExpr>(RefExpr);
     if (!ASE && !OASE && (!DE || !isa<VarDecl>(DE->getDecl()))) {
-      Diag(ELoc, diag::err_omp_expected_var_name_or_array_item) << ERange;
+      Diag(ELoc, diag::err_omp_expected_var_name_member_expr_or_array_item)
+          << 0 << ERange;
       continue;
     }
     QualType Type;
@@ -7766,7 +7841,8 @@ OMPClause *Sema::ActOnOpenMPLinearClause
     //  structure element) cannot appear in a private clause.
     DeclRefExpr *DE = dyn_cast<DeclRefExpr>(RefExpr);
     if (!DE || !isa<VarDecl>(DE->getDecl())) {
-      Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange();
+      Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
+          << 0 << RefExpr->getSourceRange();
       continue;
     }
 
@@ -7974,7 +8050,8 @@ OMPClause *Sema::ActOnOpenMPAlignedClaus
     //  A list item is a variable name.
     DeclRefExpr *DE = dyn_cast<DeclRefExpr>(RefExpr);
     if (!DE || !isa<VarDecl>(DE->getDecl())) {
-      Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange();
+      Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
+          << 0 << RefExpr->getSourceRange();
       continue;
     }
 
@@ -8000,7 +8077,7 @@ OMPClause *Sema::ActOnOpenMPAlignedClaus
 
     // OpenMP  [2.8.1, simd construct, Restrictions]
     // A list-item cannot appear in more than one aligned clause.
-    if (DeclRefExpr *PrevRef = DSAStack->addUniqueAligned(VD, DE)) {
+    if (Expr *PrevRef = DSAStack->addUniqueAligned(VD, DE)) {
       Diag(ELoc, diag::err_omp_aligned_twice) << RefExpr->getSourceRange();
       Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
           << getOpenMPClauseName(OMPC_aligned);
@@ -8055,7 +8132,8 @@ OMPClause *Sema::ActOnOpenMPCopyinClause
     //  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();
+      Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
+          << 0 << RefExpr->getSourceRange();
       continue;
     }
 
@@ -8147,7 +8225,8 @@ OMPClause *Sema::ActOnOpenMPCopyprivateC
     //  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();
+      Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
+          << 0 << RefExpr->getSourceRange();
       continue;
     }
 
@@ -8380,8 +8459,8 @@ Sema::ActOnOpenMPDependClause(OpenMPDepe
             (!ASE && !DE && !OASE) || (DE && !isa<VarDecl>(DE->getDecl())) ||
             (ASE && !ASE->getBase()->getType()->isAnyPointerType() &&
              !ASE->getBase()->getType()->isArrayType())) {
-          Diag(ELoc, diag::err_omp_expected_var_name_or_array_item)
-              << RefExpr->getSourceRange();
+          Diag(ELoc, diag::err_omp_expected_var_name_member_expr_or_array_item)
+              << 0 << RefExpr->getSourceRange();
           continue;
         }
       }
@@ -8517,8 +8596,8 @@ Sema::ActOnOpenMPMapClause(OpenMPMapClau
         (DE && !isa<VarDecl>(DE->getDecl())) ||
         (ASE && !ASE->getBase()->getType()->isAnyPointerType() &&
          !ASE->getBase()->getType()->isArrayType())) {
-      Diag(ELoc, diag::err_omp_expected_var_name_or_array_item)
-        << RE->getSourceRange();
+      Diag(ELoc, diag::err_omp_expected_var_name_member_expr_or_array_item)
+          << 0 << RE->getSourceRange();
       continue;
     }
 

Modified: cfe/trunk/test/OpenMP/distribute_ast_print.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/distribute_ast_print.cpp?rev=258299&r1=258298&r2=258299&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/distribute_ast_print.cpp (original)
+++ cfe/trunk/test/OpenMP/distribute_ast_print.cpp Wed Jan 20 03:07:54 2016
@@ -8,6 +8,75 @@
 
 void foo() {}
 
+struct S {
+  S(): a(0) {}
+  S(int v) : a(v) {}
+  int a;
+  typedef int type;
+};
+
+template <typename T>
+class S7 : public T {
+protected:
+  T a;
+  S7() : a(0) {}
+
+public:
+  S7(typename T::type v) : a(v) {
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute private(a) private(this->a) private(T::a)
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
+  }
+  S7 &operator=(S7 &s) {
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute private(a) private(this->a)
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
+    return *this;
+  }
+};
+
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams
+// CHECK-NEXT: #pragma omp distribute private(this->a) private(this->a) private(this->S::a)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams
+// CHECK-NEXT: #pragma omp distribute private(this->a) private(this->a) private(T::a)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams
+// CHECK-NEXT: #pragma omp distribute private(this->a) private(this->a)
+
+class S8 : public S7<S> {
+  S8() {}
+
+public:
+  S8(int v) : S7<S>(v){
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute private(a) private(this->a) private(S7<S>::a) 
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
+  }
+  S8 &operator=(S8 &s) {
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute private(a) private(this->a)
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
+    return *this;
+  }
+};
+
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams
+// CHECK-NEXT: #pragma omp distribute private(this->a) private(this->a) private(this->S7<S>::a)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams
+// CHECK-NEXT: #pragma omp distribute private(this->a) private(this->a)
+
 template <class T, int N>
 T tmain(T argc) {
   T b = argc, c, d, e, f, g;

Modified: cfe/trunk/test/OpenMP/for_ast_print.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_ast_print.cpp?rev=258299&r1=258298&r2=258299&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/for_ast_print.cpp (original)
+++ cfe/trunk/test/OpenMP/for_ast_print.cpp Wed Jan 20 03:07:54 2016
@@ -8,6 +8,57 @@
 
 void foo() {}
 
+struct S {
+  S(): a(0) {}
+  S(int v) : a(v) {}
+  int a;
+  typedef int type;
+};
+
+template <typename T>
+class S7 : public T {
+protected:
+  T a;
+  S7() : a(0) {}
+
+public:
+  S7(typename T::type v) : a(v) {
+#pragma omp for private(a) private(this->a) private(T::a)
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
+  }
+  S7 &operator=(S7 &s) {
+#pragma omp for private(a) private(this->a)
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
+    return *this;
+  }
+};
+
+// CHECK: #pragma omp for private(this->a) private(this->a) private(this->S::a)
+// CHECK: #pragma omp for private(this->a) private(this->a) private(T::a)
+// CHECK: #pragma omp for private(this->a) private(this->a)
+
+class S8 : public S7<S> {
+  S8() {}
+
+public:
+  S8(int v) : S7<S>(v){
+#pragma omp for private(a) private(this->a) private(S7<S>::a) 
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
+  }
+  S8 &operator=(S8 &s) {
+#pragma omp for private(a) private(this->a)
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
+    return *this;
+  }
+};
+
+// CHECK: #pragma omp for private(this->a) private(this->a) private(this->S7<S>::a)
+// CHECK: #pragma omp for private(this->a) private(this->a)
+
 template <class T, int N>
 T tmain(T argc) {
   T b = argc, c, d, e, f, g;

Modified: cfe/trunk/test/OpenMP/for_private_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_private_messages.cpp?rev=258299&r1=258298&r2=258299&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/for_private_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/for_private_messages.cpp Wed Jan 20 03:07:54 2016
@@ -29,7 +29,11 @@ class S4 {
   S4(); // expected-note {{implicitly declared private here}}
 
 public:
-  S4(int v) : a(v) {}
+  S4(int v) : a(v) {
+#pragma omp for private(a) private(this->a)
+    for (int k = 0; k < v; ++k)
+      ++this->a;
+  }
 };
 class S5 {
   int a;
@@ -37,6 +41,50 @@ class S5 {
 
 public:
   S5(int v) : a(v) {}
+  S5 &operator=(S5 &s) {
+#pragma omp for private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a; ++k)
+      ++s.a;
+    return *this;
+  }
+};
+
+template <typename T>
+class S6 {
+public:
+  T a;
+
+  S6() : a(0) {}
+  S6(T v) : a(v) {
+#pragma omp for private(a) private(this->a)
+    for (int k = 0; k < v; ++k)
+      ++this->a;
+  }
+  S6 &operator=(S6 &s) {
+#pragma omp for private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a; ++k)
+      ++s.a;
+    return *this;
+  }
+};
+
+template <typename T>
+class S7 : public T {
+  T a;
+  S7() : a(0) {}
+
+public:
+  S7(T v) : a(v) {
+#pragma omp for private(a) private(this->a) private(T::a)
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
+  }
+  S7 &operator=(S7 &s) {
+#pragma omp for private(a) private(this->a) private(s.a) private(s.T::a) // expected-error 2 {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
+    return *this;
+  }
 };
 
 S3 h;
@@ -126,6 +174,8 @@ using A::x;
 int main(int argc, char **argv) {
   S4 e(4);
   S5 g(5);
+  S6<float> s6(0.0) , s6_0(1.0);
+  S7<S6<float> > s7(0.0) , s7_0(1.0);
   int i;
   int &j = i;
 #pragma omp for private // expected-error {{expected '(' after 'private'}}
@@ -190,6 +240,8 @@ int main(int argc, char **argv) {
   for(int k = 0; k < argc; ++k)
     si = k + 1;
 
-  return 0;
+  s6 = s6_0; // expected-note {{in instantiation of member function 'S6<float>::operator=' requested here}}
+  s7 = s7_0; // expected-note {{in instantiation of member function 'S7<S6<float> >::operator=' requested here}}
+  return foomain(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
 }
 

Modified: cfe/trunk/test/OpenMP/for_simd_ast_print.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_simd_ast_print.cpp?rev=258299&r1=258298&r2=258299&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/for_simd_ast_print.cpp (original)
+++ cfe/trunk/test/OpenMP/for_simd_ast_print.cpp Wed Jan 20 03:07:54 2016
@@ -6,6 +6,57 @@
 #ifndef HEADER
 #define HEADER
 
+struct S1 {
+  S1(): a(0) {}
+  S1(int v) : a(v) {}
+  int a;
+  typedef int type;
+};
+
+template <typename T>
+class S7 : public T {
+protected:
+  T a;
+  S7() : a(0) {}
+
+public:
+  S7(typename T::type v) : a(v) {
+#pragma omp for simd private(a) private(this->a) private(T::a)
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
+  }
+  S7 &operator=(S7 &s) {
+#pragma omp for simd private(a) private(this->a)
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
+    return *this;
+  }
+};
+
+// CHECK: #pragma omp for simd private(this->a) private(this->a) private(this->S1::a)
+// CHECK: #pragma omp for simd private(this->a) private(this->a) private(T::a)
+// CHECK: #pragma omp for simd private(this->a) private(this->a)
+
+class S8 : public S7<S1> {
+  S8() {}
+
+public:
+  S8(int v) : S7<S1>(v){
+#pragma omp for simd private(a) private(this->a) private(S7<S1>::a) 
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
+  }
+  S8 &operator=(S8 &s) {
+#pragma omp for simd private(a) private(this->a)
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
+    return *this;
+  }
+};
+
+// CHECK: #pragma omp for simd private(this->a) private(this->a) private(this->S7<S1>::a)
+// CHECK: #pragma omp for simd private(this->a) private(this->a)
+
 void foo() {}
 int g_ind = 1;
 template<class T, class N> T reduct(T* arr, N num) {

Modified: cfe/trunk/test/OpenMP/for_simd_private_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_simd_private_messages.cpp?rev=258299&r1=258298&r2=258299&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/for_simd_private_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/for_simd_private_messages.cpp Wed Jan 20 03:07:54 2016
@@ -29,7 +29,11 @@ class S4 {
   S4(); // expected-note {{implicitly declared private here}}
 
 public:
-  S4(int v) : a(v) {}
+  S4(int v) : a(v) {
+#pragma omp for simd private(a) private(this->a)
+    for (int k = 0; k < v; ++k)
+      ++this->a;
+  }
 };
 class S5 {
   int a;
@@ -37,6 +41,50 @@ class S5 {
 
 public:
   S5(int v) : a(v) {}
+  S5 &operator=(S5 &s) {
+#pragma omp for simd private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a; ++k)
+      ++s.a;
+    return *this;
+  }
+};
+
+template <typename T>
+class S6 {
+public:
+  T a;
+
+  S6() : a(0) {}
+  S6(T v) : a(v) {
+#pragma omp for simd private(a) private(this->a)
+    for (int k = 0; k < v; ++k)
+      ++this->a;
+  }
+  S6 &operator=(S6 &s) {
+#pragma omp for simd private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a; ++k)
+      ++s.a;
+    return *this;
+  }
+};
+
+template <typename T>
+class S7 : public T {
+  T a;
+  S7() : a(0) {}
+
+public:
+  S7(T v) : a(v) {
+#pragma omp for simd private(a) private(this->a) private(T::a)
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
+  }
+  S7 &operator=(S7 &s) {
+#pragma omp for simd private(a) private(this->a) private(s.a) private(s.T::a) // expected-error 2 {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
+    return *this;
+  }
 };
 
 S3 h;
@@ -119,6 +167,8 @@ using A::x;
 int main(int argc, char **argv) {
   S4 e(4);
   S5 g(5);
+  S6<float> s6(0.0) , s6_0(1.0);
+  S7<S6<float> > s7(0.0) , s7_0(1.0);
   int i;
   int &j = i;
 #pragma omp for simd private // expected-error {{expected '(' after 'private'}}
@@ -180,6 +230,8 @@ int main(int argc, char **argv) {
   for (int k = 0; k < argc; ++k)
     m = k + 2;
 
-  return 0;
+  s6 = s6_0; // expected-note {{in instantiation of member function 'S6<float>::operator=' requested here}}
+  s7 = s7_0; // expected-note {{in instantiation of member function 'S7<S6<float> >::operator=' requested here}}
+  return foomain(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
 }
 

Modified: cfe/trunk/test/OpenMP/parallel_ast_print.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_ast_print.cpp?rev=258299&r1=258298&r2=258299&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/parallel_ast_print.cpp (original)
+++ cfe/trunk/test/OpenMP/parallel_ast_print.cpp Wed Jan 20 03:07:54 2016
@@ -8,6 +8,57 @@
 
 void foo() {}
 
+struct S1 {
+  S1(): a(0) {}
+  S1(int v) : a(v) {}
+  int a;
+  typedef int type;
+};
+
+template <typename T>
+class S7 : public T {
+protected:
+  T a;
+  S7() : a(0) {}
+
+public:
+  S7(typename T::type v) : a(v) {
+#pragma omp parallel private(a) private(this->a) private(T::a)
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
+  }
+  S7 &operator=(S7 &s) {
+#pragma omp parallel private(a) private(this->a)
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
+    return *this;
+  }
+};
+
+// CHECK: #pragma omp parallel private(this->a) private(this->a) private(this->S1::a)
+// CHECK: #pragma omp parallel private(this->a) private(this->a) private(T::a)
+// CHECK: #pragma omp parallel private(this->a) private(this->a)
+
+class S8 : public S7<S1> {
+  S8() {}
+
+public:
+  S8(int v) : S7<S1>(v){
+#pragma omp parallel private(a) private(this->a) private(S7<S1>::a) 
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
+  }
+  S8 &operator=(S8 &s) {
+#pragma omp parallel private(a) private(this->a)
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
+    return *this;
+  }
+};
+
+// CHECK: #pragma omp parallel private(this->a) private(this->a) private(this->S7<S1>::a)
+// CHECK: #pragma omp parallel private(this->a) private(this->a)
+
 template <class T>
 struct S {
   operator T() {return T();}

Modified: cfe/trunk/test/OpenMP/parallel_for_ast_print.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_for_ast_print.cpp?rev=258299&r1=258298&r2=258299&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/parallel_for_ast_print.cpp (original)
+++ cfe/trunk/test/OpenMP/parallel_for_ast_print.cpp Wed Jan 20 03:07:54 2016
@@ -8,6 +8,57 @@
 
 void foo() {}
 
+struct S {
+  S(): a(0) {}
+  S(int v) : a(v) {}
+  int a;
+  typedef int type;
+};
+
+template <typename T>
+class S7 : public T {
+protected:
+  T a;
+  S7() : a(0) {}
+
+public:
+  S7(typename T::type v) : a(v) {
+#pragma omp parallel for private(a) private(this->a) private(T::a)
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
+  }
+  S7 &operator=(S7 &s) {
+#pragma omp parallel for private(a) private(this->a)
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
+    return *this;
+  }
+};
+
+// CHECK: #pragma omp parallel for private(this->a) private(this->a) private(this->S::a)
+// CHECK: #pragma omp parallel for private(this->a) private(this->a) private(T::a)
+// CHECK: #pragma omp parallel for private(this->a) private(this->a)
+
+class S8 : public S7<S> {
+  S8() {}
+
+public:
+  S8(int v) : S7<S>(v){
+#pragma omp parallel for private(a) private(this->a) private(S7<S>::a)
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
+  }
+  S8 &operator=(S8 &s) {
+#pragma omp parallel for private(a) private(this->a)
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
+    return *this;
+  }
+};
+
+// CHECK: #pragma omp parallel for private(this->a) private(this->a) private(this->S7<S>::a)
+// CHECK: #pragma omp parallel for private(this->a) private(this->a)
+
 template <class T, int N>
 T tmain(T argc) {
   T b = argc, c, d, e, f, h;

Modified: cfe/trunk/test/OpenMP/parallel_for_private_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_for_private_messages.cpp?rev=258299&r1=258298&r2=258299&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/parallel_for_private_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/parallel_for_private_messages.cpp Wed Jan 20 03:07:54 2016
@@ -29,7 +29,11 @@ class S4 {
   S4(); // expected-note {{implicitly declared private here}}
 
 public:
-  S4(int v) : a(v) {}
+  S4(int v) : a(v) {
+#pragma omp parallel for private(a) private(this->a)
+    for (int k = 0; k < v; ++k)
+      ++this->a;
+  }
 };
 class S5 {
   int a;
@@ -37,6 +41,50 @@ class S5 {
 
 public:
   S5(int v) : a(v) {}
+  S5 &operator=(S5 &s) {
+#pragma omp parallel for private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a; ++k)
+      ++s.a;
+    return *this;
+  }
+};
+
+template <typename T>
+class S6 {
+public:
+  T a;
+
+  S6() : a(0) {}
+  S6(T v) : a(v) {
+#pragma omp parallel for private(a) private(this->a)
+    for (int k = 0; k < v; ++k)
+      ++this->a;
+  }
+  S6 &operator=(S6 &s) {
+#pragma omp parallel for private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a; ++k)
+      ++s.a;
+    return *this;
+  }
+};
+
+template <typename T>
+class S7 : public T {
+  T a;
+  S7() : a(0) {}
+
+public:
+  S7(T v) : a(v) {
+#pragma omp parallel for private(a) private(this->a) private(T::a)
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
+  }
+  S7 &operator=(S7 &s) {
+#pragma omp parallel for private(a) private(this->a) private(s.a) private(s.T::a) // expected-error 2 {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
+    return *this;
+  }
 };
 
 S3 h;
@@ -119,6 +167,8 @@ using A::x;
 int main(int argc, char **argv) {
   S4 e(4);
   S5 g(5);
+  S6<float> s6(0.0) , s6_0(1.0);
+  S7<S6<float> > s7(0.0) , s7_0(1.0);
   int i;
   int &j = i;
 #pragma omp parallel for private // expected-error {{expected '(' after 'private'}}
@@ -180,6 +230,8 @@ int main(int argc, char **argv) {
   for (int k = 0; k < argc; ++k)
     m = k + 2;
 
-  return 0;
+  s6 = s6_0; // expected-note {{in instantiation of member function 'S6<float>::operator=' requested here}}
+  s7 = s7_0; // expected-note {{in instantiation of member function 'S7<S6<float> >::operator=' requested here}}
+  return foomain(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
 }
 

Modified: cfe/trunk/test/OpenMP/parallel_for_simd_ast_print.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_for_simd_ast_print.cpp?rev=258299&r1=258298&r2=258299&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/parallel_for_simd_ast_print.cpp (original)
+++ cfe/trunk/test/OpenMP/parallel_for_simd_ast_print.cpp Wed Jan 20 03:07:54 2016
@@ -7,6 +7,58 @@
 #define HEADER
 
 void foo() {}
+
+struct S1 {
+  S1() : a(0) {}
+  S1(int v) : a(v) {}
+  int a;
+  typedef int type;
+};
+
+template <typename T>
+class S7 : public T {
+protected:
+  T a;
+  S7() : a(0) {}
+
+public:
+  S7(typename T::type v) : a(v) {
+#pragma omp parallel for simd private(a) private(this->a) private(T::a)
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
+  }
+  S7 &operator=(S7 &s) {
+#pragma omp parallel for simd private(a) private(this->a)
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
+    return *this;
+  }
+};
+
+// CHECK: #pragma omp parallel for simd private(this->a) private(this->a) private(this->S1::a)
+// CHECK: #pragma omp parallel for simd private(this->a) private(this->a) private(T::a)
+// CHECK: #pragma omp parallel for simd private(this->a) private(this->a)
+
+class S8 : public S7<S1> {
+  S8() {}
+
+public:
+  S8(int v) : S7<S1>(v){
+#pragma omp parallel for simd private(a) private(this->a) private(S7<S1>::a) 
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
+  }
+  S8 &operator=(S8 &s) {
+#pragma omp parallel for simd private(a) private(this->a)
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
+    return *this;
+  }
+};
+
+// CHECK: #pragma omp parallel for simd private(this->a) private(this->a) private(this->S7<S1>::a)
+// CHECK: #pragma omp parallel for simd private(this->a) private(this->a)
+
 int g_ind = 1;
 template<class T, class N> T reduct(T* arr, N num) {
   N i;

Modified: cfe/trunk/test/OpenMP/parallel_for_simd_private_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_for_simd_private_messages.cpp?rev=258299&r1=258298&r2=258299&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/parallel_for_simd_private_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/parallel_for_simd_private_messages.cpp Wed Jan 20 03:07:54 2016
@@ -29,7 +29,11 @@ class S4 {
   S4(); // expected-note {{implicitly declared private here}}
 
 public:
-  S4(int v) : a(v) {}
+  S4(int v) : a(v) {
+#pragma omp parallel for simd private(a) private(this->a)
+    for (int k = 0; k < v; ++k)
+      ++this->a;
+  }
 };
 class S5 {
   int a;
@@ -37,6 +41,50 @@ class S5 {
 
 public:
   S5(int v) : a(v) {}
+  S5 &operator=(S5 &s) {
+#pragma omp parallel for simd private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a; ++k)
+      ++s.a;
+    return *this;
+  }
+};
+
+template <typename T>
+class S6 {
+public:
+  T a;
+
+  S6() : a(0) {}
+  S6(T v) : a(v) {
+#pragma omp parallel for simd private(a) private(this->a)
+    for (int k = 0; k < v; ++k)
+      ++this->a;
+  }
+  S6 &operator=(S6 &s) {
+#pragma omp parallel for simd private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a; ++k)
+      ++s.a;
+    return *this;
+  }
+};
+
+template <typename T>
+class S7 : public T {
+  T a;
+  S7() : a(0) {}
+
+public:
+  S7(T v) : a(v) {
+#pragma omp parallel for simd private(a) private(this->a) private(T::a)
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
+  }
+  S7 &operator=(S7 &s) {
+#pragma omp parallel for simd private(a) private(this->a) private(s.a) private(s.T::a) // expected-error 2 {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
+    return *this;
+  }
 };
 
 S3 h;
@@ -119,6 +167,8 @@ using A::x;
 int main(int argc, char **argv) {
   S4 e(4);
   S5 g(5);
+  S6<float> s6(0.0) , s6_0(1.0);
+  S7<S6<float> > s7(0.0) , s7_0(1.0);
   int i;
   int &j = i;
 #pragma omp parallel for simd private // expected-error {{expected '(' after 'private'}}
@@ -180,6 +230,8 @@ int main(int argc, char **argv) {
   for (int k = 0; k < argc; ++k)
     m = k + 3;
 
-  return 0;
+  s6 = s6_0; // expected-note {{in instantiation of member function 'S6<float>::operator=' requested here}}
+  s7 = s7_0; // expected-note {{in instantiation of member function 'S7<S6<float> >::operator=' requested here}}
+  return foomain(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
 }
 

Modified: cfe/trunk/test/OpenMP/parallel_sections_private_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_sections_private_messages.cpp?rev=258299&r1=258298&r2=258299&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/parallel_sections_private_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/parallel_sections_private_messages.cpp Wed Jan 20 03:07:54 2016
@@ -29,7 +29,13 @@ class S4 {
   S4(); // expected-note {{implicitly declared private here}}
 
 public:
-  S4(int v) : a(v) {}
+  S4(int v) : a(v) {
+#pragma omp parallel sections private(a) private(this->a)
+    {
+      for (int k = 0; k < v; ++k)
+        ++this->a;
+    }
+  }
 };
 class S5 {
   int a;
@@ -37,6 +43,60 @@ class S5 {
 
 public:
   S5(int v) : a(v) {}
+  S5 &operator=(S5 &s) {
+#pragma omp parallel sections private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
+    {
+      for (int k = 0; k < s.a; ++k)
+        ++s.a;
+    }
+    return *this;
+  }
+};
+
+template <typename T>
+class S6 {
+public:
+  T a;
+
+  S6() : a(0) {}
+  S6(T v) : a(v) {
+#pragma omp parallel sections private(a) private(this->a)
+    {
+      for (int k = 0; k < v; ++k)
+        ++this->a;
+    }
+  }
+  S6 &operator=(S6 &s) {
+#pragma omp parallel sections private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
+    {
+      for (int k = 0; k < s.a; ++k)
+        ++s.a;
+    }
+    return *this;
+  }
+};
+
+template <typename T>
+class S7 : public T {
+  T a;
+  S7() : a(0) {}
+
+public:
+  S7(T v) : a(v) {
+#pragma omp parallel sections private(a) private(this->a) private(T::a)
+    {
+      for (int k = 0; k < a.a; ++k)
+        ++this->a.a;
+    }
+  }
+  S7 &operator=(S7 &s) {
+#pragma omp parallel sections private(a) private(this->a) private(s.a) private(s.T::a) // expected-error 2 {{expected variable name or data member of current class}}
+    {
+      for (int k = 0; k < s.a.a; ++k)
+        ++s.a.a;
+    }
+    return *this;
+  }
 };
 
 S3 h;
@@ -134,6 +194,8 @@ using A::x;
 int main(int argc, char **argv) {
   S4 e(4);
   S5 g(5);
+  S6<float> s6(0.0) , s6_0(1.0);
+  S7<S6<float> > s7(0.0) , s7_0(1.0);
   int i;
   int &j = i;
 #pragma omp parallel sections private // expected-error {{expected '(' after 'private'}}
@@ -212,6 +274,8 @@ int main(int argc, char **argv) {
     foo();
   }
 
-  return 0;
+  s6 = s6_0; // expected-note {{in instantiation of member function 'S6<float>::operator=' requested here}}
+  s7 = s7_0; // expected-note {{in instantiation of member function 'S7<S6<float> >::operator=' requested here}}
+  return foomain(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
 }
 

Modified: cfe/trunk/test/OpenMP/sections_private_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/sections_private_messages.cpp?rev=258299&r1=258298&r2=258299&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/sections_private_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/sections_private_messages.cpp Wed Jan 20 03:07:54 2016
@@ -29,7 +29,13 @@ class S4 {
   S4(); // expected-note {{implicitly declared private here}}
 
 public:
-  S4(int v) : a(v) {}
+  S4(int v) : a(v) {
+#pragma omp sections private(a) private(this->a)
+    {
+      for (int k = 0; k < v; ++k)
+        ++this->a;
+    }
+  }
 };
 class S5 {
   int a;
@@ -37,6 +43,60 @@ class S5 {
 
 public:
   S5(int v) : a(v) {}
+  S5 &operator=(S5 &s) {
+#pragma omp sections private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
+    {
+      for (int k = 0; k < s.a; ++k)
+        ++s.a;
+    }
+    return *this;
+  }
+};
+
+template <typename T>
+class S6 {
+public:
+  T a;
+
+  S6() : a(0) {}
+  S6(T v) : a(v) {
+#pragma omp sections private(a) private(this->a)
+    {
+      for (int k = 0; k < v; ++k)
+        ++this->a;
+    }
+  }
+  S6 &operator=(S6 &s) {
+#pragma omp sections private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
+    {
+      for (int k = 0; k < s.a; ++k)
+        ++s.a;
+    }
+    return *this;
+  }
+};
+
+template <typename T>
+class S7 : public T {
+  T a;
+  S7() : a(0) {}
+
+public:
+  S7(T v) : a(v) {
+#pragma omp sections private(a) private(this->a) private(T::a)
+    {
+      for (int k = 0; k < a.a; ++k)
+        ++this->a.a;
+    }
+  }
+  S7 &operator=(S7 &s) {
+#pragma omp sections private(a) private(this->a) private(s.a) private(s.T::a) // expected-error 2 {{expected variable name or data member of current class}}
+    {
+      for (int k = 0; k < s.a.a; ++k)
+        ++s.a.a;
+    }
+    return *this;
+  }
 };
 
 S3 h;
@@ -134,6 +194,8 @@ using A::x;
 int main(int argc, char **argv) {
   S4 e(4);
   S5 g(5);
+  S6<float> s6(0.0) , s6_0(1.0);
+  S7<S6<float> > s7(0.0) , s7_0(1.0);
   int i;
   int &j = i;
 #pragma omp sections private // expected-error {{expected '(' after 'private'}}
@@ -212,6 +274,8 @@ int main(int argc, char **argv) {
     foo();
   }
 
-  return 0;
+  s6 = s6_0; // expected-note {{in instantiation of member function 'S6<float>::operator=' requested here}}
+  s7 = s7_0; // expected-note {{in instantiation of member function 'S7<S6<float> >::operator=' requested here}}
+  return foomain(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
 }
 

Modified: cfe/trunk/test/OpenMP/simd_private_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/simd_private_messages.cpp?rev=258299&r1=258298&r2=258299&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/simd_private_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/simd_private_messages.cpp Wed Jan 20 03:07:54 2016
@@ -26,13 +26,61 @@ class S4 {
   int a;
   S4(); // expected-note {{implicitly declared private here}}
 public:
-  S4(int v):a(v) { }
+  S4(int v) : a(v) {
+#pragma omp simd private(a) private(this->a)
+    for (int k = 0; k < v; ++k)
+      ++this->a;
+  }
 };
 class S5 {
   int a;
   S5():a(0) {} // expected-note {{implicitly declared private here}}
 public:
   S5(int v):a(v) { }
+  S5 &operator=(S5 &s) {
+#pragma omp simd private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a; ++k)
+      ++s.a;
+    return *this;
+  }
+};
+
+template <typename T>
+class S6 {
+public:
+  T a;
+
+  S6() : a(0) {}
+  S6(T v) : a(v) {
+#pragma omp simd private(a) private(this->a)
+    for (int k = 0; k < v; ++k)
+      ++this->a;
+  }
+  S6 &operator=(S6 &s) {
+#pragma omp simd private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a; ++k)
+      ++s.a;
+    return *this;
+  }
+};
+
+template <typename T>
+class S7 : public T {
+  T a;
+  S7() : a(0) {}
+
+public:
+  S7(T v) : a(v) {
+#pragma omp simd private(a) private(this->a) private(T::a)
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
+  }
+  S7 &operator=(S7 &s) {
+#pragma omp simd private(a) private(this->a) private(s.a) private(s.T::a) // expected-error 2 {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
+    return *this;
+  }
 };
 
 S3 h;
@@ -96,6 +144,8 @@ using A::x;
 int main(int argc, char **argv) {
   S4 e(4);
   S5 g(5);
+  S6<float> s6(0.0) , s6_0(1.0);
+  S7<S6<float> > s7(0.0) , s7_0(1.0);
   int i;
   int &j = i;
   #pragma omp simd private // expected-error {{expected '(' after 'private'}}
@@ -137,6 +187,8 @@ int main(int argc, char **argv) {
   #pragma omp simd private(i)
   for (int k = 0; k < argc; ++k) ++k;
 
-  return 0;
+  s6 = s6_0; // expected-note {{in instantiation of member function 'S6<float>::operator=' requested here}}
+  s7 = s7_0; // expected-note {{in instantiation of member function 'S7<S6<float> >::operator=' requested here}}
+  return foomain(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
 }
 

Modified: cfe/trunk/test/OpenMP/single_private_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/single_private_messages.cpp?rev=258299&r1=258298&r2=258299&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/single_private_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/single_private_messages.cpp Wed Jan 20 03:07:54 2016
@@ -29,7 +29,11 @@ class S4 {
   S4(); // expected-note {{implicitly declared private here}}
 
 public:
-  S4(int v) : a(v) {}
+  S4(int v) : a(v) {
+#pragma omp single private(a) private(this->a)
+    for (int k = 0; k < v; ++k)
+      ++this->a;
+  }
 };
 class S5 {
   int a;
@@ -37,6 +41,50 @@ class S5 {
 
 public:
   S5(int v) : a(v) {}
+  S5 &operator=(S5 &s) {
+#pragma omp single private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a; ++k)
+      ++s.a;
+    return *this;
+  }
+};
+
+template <typename T>
+class S6 {
+public:
+  T a;
+
+  S6() : a(0) {}
+  S6(T v) : a(v) {
+#pragma omp single private(a) private(this->a)
+    for (int k = 0; k < v; ++k)
+      ++this->a;
+  }
+  S6 &operator=(S6 &s) {
+#pragma omp single private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a; ++k)
+      ++s.a;
+    return *this;
+  }
+};
+
+template <typename T>
+class S7 : public T {
+  T a;
+  S7() : a(0) {}
+
+public:
+  S7(T v) : a(v) {
+#pragma omp single private(a) private(this->a) private(T::a)
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
+  }
+  S7 &operator=(S7 &s) {
+#pragma omp single private(a) private(this->a) private(s.a) private(s.T::a) // expected-error 2 {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
+    return *this;
+  }
 };
 
 S3 h;
@@ -102,6 +150,8 @@ using A::x;
 int main(int argc, char **argv) {
   S4 e(4);
   S5 g(5);
+  S6<float> s6(0.0) , s6_0(1.0);
+  S7<S6<float> > s7(0.0) , s7_0(1.0);
   int i;
   int &j = i;
 #pragma omp single private // expected-error {{expected '(' after 'private'}}
@@ -146,6 +196,8 @@ int main(int argc, char **argv) {
 #pragma omp single private(m) // OK
   foo();
 
-  return 0;
+  s6 = s6_0; // expected-note {{in instantiation of member function 'S6<float>::operator=' requested here}}
+  s7 = s7_0; // expected-note {{in instantiation of member function 'S7<S6<float> >::operator=' requested here}}
+  return foomain(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
 }
 

Modified: cfe/trunk/test/OpenMP/target_private_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/target_private_messages.cpp?rev=258299&r1=258298&r2=258299&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/target_private_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/target_private_messages.cpp Wed Jan 20 03:07:54 2016
@@ -22,7 +22,11 @@ class S4 {
   S4(); // expected-note {{implicitly declared private here}}
 
 public:
-  S4(int v) : a(v) {}
+  S4(int v) : a(v) {
+#pragma omp target private(a) private(this->a)
+    for (int k = 0; k < v; ++k)
+      ++this->a;
+  }
 };
 class S5 {
   int a;
@@ -30,6 +34,50 @@ class S5 {
 
 public:
   S5(int v) : a(v) {}
+  S5 &operator=(S5 &s) {
+#pragma omp target private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a; ++k)
+      ++s.a;
+    return *this;
+  }
+};
+
+template <typename T>
+class S6 {
+public:
+  T a;
+
+  S6() : a(0) {}
+  S6(T v) : a(v) {
+#pragma omp target private(a) private(this->a)
+    for (int k = 0; k < v; ++k)
+      ++this->a;
+  }
+  S6 &operator=(S6 &s) {
+#pragma omp target private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a; ++k)
+      ++s.a;
+    return *this;
+  }
+};
+
+template <typename T>
+class S7 : public T {
+  T a;
+  S7() : a(0) {}
+
+public:
+  S7(T v) : a(v) {
+#pragma omp target private(a) private(this->a) private(T::a)
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
+  }
+  S7 &operator=(S7 &s) {
+#pragma omp target private(a) private(this->a) private(s.a) private(s.T::a) // expected-error 2 {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
+    return *this;
+  }
 };
 
 S3 h;
@@ -86,6 +134,8 @@ using A::x;
 int main(int argc, char **argv) {
   S4 e(4);
   S5 g(5);
+  S6<float> s6(0.0) , s6_0(1.0);
+  S7<S6<float> > s7(0.0) , s7_0(1.0);
   int i;
   int &j = i;
 #pragma omp target private // expected-error {{expected '(' after 'private'}}
@@ -116,6 +166,8 @@ int main(int argc, char **argv) {
   static int si;
 #pragma omp target private(si) // OK
   {}
-  return 0;
+  s6 = s6_0; // expected-note {{in instantiation of member function 'S6<float>::operator=' requested here}}
+  s7 = s7_0; // expected-note {{in instantiation of member function 'S7<S6<float> >::operator=' requested here}}
+  return foomain(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
 }
 

Modified: cfe/trunk/test/OpenMP/task_ast_print.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/task_ast_print.cpp?rev=258299&r1=258298&r2=258299&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/task_ast_print.cpp (original)
+++ cfe/trunk/test/OpenMP/task_ast_print.cpp Wed Jan 20 03:07:54 2016
@@ -8,6 +8,57 @@
 
 void foo() {}
 
+struct S1 {
+  S1(): a(0) {}
+  S1(int v) : a(v) {}
+  int a;
+  typedef int type;
+};
+
+template <typename T>
+class S7 : public T {
+protected:
+  T a;
+  S7() : a(0) {}
+
+public:
+  S7(typename T::type v) : a(v) {
+#pragma omp task private(a) private(this->a) private(T::a)
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
+  }
+  S7 &operator=(S7 &s) {
+#pragma omp task private(a) private(this->a)
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
+    return *this;
+  }
+};
+
+// CHECK: #pragma omp task private(this->a) private(this->a) private(this->S1::a)
+// CHECK: #pragma omp task private(this->a) private(this->a) private(T::a)
+// CHECK: #pragma omp task private(this->a) private(this->a)
+
+class S8 : public S7<S1> {
+  S8() {}
+
+public:
+  S8(int v) : S7<S1>(v){
+#pragma omp task private(a) private(this->a) private(S7<S1>::a)
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
+  }
+  S8 &operator=(S8 &s) {
+#pragma omp task private(a) private(this->a)
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
+    return *this;
+  }
+};
+
+// CHECK: #pragma omp task private(this->a) private(this->a) private(this->S7<S1>::a)
+// CHECK: #pragma omp task private(this->a) private(this->a)
+
 template <class T>
 struct S {
   operator T() { return T(); }

Modified: cfe/trunk/test/OpenMP/taskloop_private_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/taskloop_private_messages.cpp?rev=258299&r1=258298&r2=258299&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/taskloop_private_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/taskloop_private_messages.cpp Wed Jan 20 03:07:54 2016
@@ -29,7 +29,11 @@ class S4 {
   S4(); // expected-note {{implicitly declared private here}}
 
 public:
-  S4(int v) : a(v) {}
+  S4(int v) : a(v) {
+#pragma omp taskloop private(a) private(this->a)
+    for (int k = 0; k < v; ++k)
+      ++this->a;
+  }
 };
 class S5 {
   int a;
@@ -37,6 +41,50 @@ class S5 {
 
 public:
   S5(int v) : a(v) {}
+  S5 &operator=(S5 &s) {
+#pragma omp taskloop private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a; ++k)
+      ++s.a;
+    return *this;
+  }
+};
+
+template <typename T>
+class S6 {
+public:
+  T a;
+
+  S6() : a(0) {}
+  S6(T v) : a(v) {
+#pragma omp taskloop private(a) private(this->a)
+    for (int k = 0; k < v; ++k)
+      ++this->a;
+  }
+  S6 &operator=(S6 &s) {
+#pragma omp taskloop private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a; ++k)
+      ++s.a;
+    return *this;
+  }
+};
+
+template <typename T>
+class S7 : public T {
+  T a;
+  S7() : a(0) {}
+
+public:
+  S7(T v) : a(v) {
+#pragma omp taskloop private(a) private(this->a) private(T::a)
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
+  }
+  S7 &operator=(S7 &s) {
+#pragma omp taskloop private(a) private(this->a) private(s.a) private(s.T::a) // expected-error 2 {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
+    return *this;
+  }
 };
 
 S3 h;
@@ -126,6 +174,8 @@ using A::x;
 int main(int argc, char **argv) {
   S4 e(4);
   S5 g(5);
+  S6<float> s6(0.0) , s6_0(1.0);
+  S7<S6<float> > s7(0.0) , s7_0(1.0);
   int i;
   int &j = i;
 #pragma omp taskloop private // expected-error {{expected '(' after 'private'}}
@@ -190,6 +240,8 @@ int main(int argc, char **argv) {
   for(int k = 0; k < argc; ++k)
     si = k + 1;
 
-  return 0;
+  s6 = s6_0; // expected-note {{in instantiation of member function 'S6<float>::operator=' requested here}}
+  s7 = s7_0; // expected-note {{in instantiation of member function 'S7<S6<float> >::operator=' requested here}}
+  return foomain(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
 }
 

Modified: cfe/trunk/test/OpenMP/taskloop_simd_private_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/taskloop_simd_private_messages.cpp?rev=258299&r1=258298&r2=258299&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/taskloop_simd_private_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/taskloop_simd_private_messages.cpp Wed Jan 20 03:07:54 2016
@@ -29,7 +29,11 @@ class S4 {
   S4(); // expected-note {{implicitly declared private here}}
 
 public:
-  S4(int v) : a(v) {}
+  S4(int v) : a(v) {
+#pragma omp taskloop simd private(a) private(this->a)
+    for (int k = 0; k < v; ++k)
+      ++this->a;
+  }
 };
 class S5 {
   int a;
@@ -37,6 +41,50 @@ class S5 {
 
 public:
   S5(int v) : a(v) {}
+  S5 &operator=(S5 &s) {
+#pragma omp taskloop simd private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a; ++k)
+      ++s.a;
+    return *this;
+  }
+};
+
+template <typename T>
+class S6 {
+public:
+  T a;
+
+  S6() : a(0) {}
+  S6(T v) : a(v) {
+#pragma omp taskloop simd private(a) private(this->a)
+    for (int k = 0; k < v; ++k)
+      ++this->a;
+  }
+  S6 &operator=(S6 &s) {
+#pragma omp taskloop simd private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a; ++k)
+      ++s.a;
+    return *this;
+  }
+};
+
+template <typename T>
+class S7 : public T {
+  T a;
+  S7() : a(0) {}
+
+public:
+  S7(T v) : a(v) {
+#pragma omp taskloop simd private(a) private(this->a) private(T::a)
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
+  }
+  S7 &operator=(S7 &s) {
+#pragma omp taskloop simd private(a) private(this->a) private(s.a) private(s.T::a) // expected-error 2 {{expected variable name or data member of current class}}
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
+    return *this;
+  }
 };
 
 S3 h;
@@ -126,6 +174,8 @@ using A::x;
 int main(int argc, char **argv) {
   S4 e(4);
   S5 g(5);
+  S6<float> s6(0.0) , s6_0(1.0);
+  S7<S6<float> > s7(0.0) , s7_0(1.0);
   int i;
   int &j = i;
 #pragma omp taskloop simd private // expected-error {{expected '(' after 'private'}}
@@ -190,6 +240,8 @@ int main(int argc, char **argv) {
   for(int k = 0; k < argc; ++k)
     si = k + 1;
 
-  return 0;
+  s6 = s6_0; // expected-note {{in instantiation of member function 'S6<float>::operator=' requested here}}
+  s7 = s7_0; // expected-note {{in instantiation of member function 'S7<S6<float> >::operator=' requested here}}
+  return foomain(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
 }
 




More information about the cfe-commits mailing list