[OPENMP 4.5] Codegen for data members in 'reduction' clause.

OpenMP 4.5 allows to privatize non-static data members of current class
in non-static member functions. Patch supports codegen for non-static
data members in 'reduction' clauses.

llvm-svn: 262460
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index e115a2f..86ad66f 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -1705,7 +1705,7 @@
 }
 
 static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
-                                             Expr *CaptureExpr) {
+                                             Expr *CaptureExpr, bool WithInit) {
   ASTContext &C = S.getASTContext();
   Expr *Init = CaptureExpr->IgnoreImpCasts();
   QualType Ty = Init->getType();
@@ -1720,27 +1720,33 @@
         return nullptr;
       Init = Res.get();
     }
+    WithInit = true;
   }
   auto *CED = OMPCapturedExprDecl::Create(C, S.CurContext, Id, Ty);
   S.CurContext->addHiddenDecl(CED);
-  S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false,
-                         /*TypeMayContainAuto=*/true);
+  if (WithInit)
+    S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false,
+                           /*TypeMayContainAuto=*/true);
+  else
+    S.ActOnUninitializedDecl(CED, /*TypeMayContainAuto=*/true);
   return CED;
 }
 
-static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr) {
+static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
+                                 bool WithInit) {
   OMPCapturedExprDecl *CD;
   if (auto *VD = S.IsOpenMPCapturedDecl(D))
     CD = cast<OMPCapturedExprDecl>(VD);
   else
-    CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr);
+    CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit);
   return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
                           SourceLocation());
 }
 
 static DeclRefExpr *buildCapture(Sema &S, Expr *CaptureExpr) {
-  auto *CD = buildCaptureDecl(
-      S, &S.getASTContext().Idents.get(".capture_expr."), CaptureExpr);
+  auto *CD =
+      buildCaptureDecl(S, &S.getASTContext().Idents.get(".capture_expr."),
+                       CaptureExpr, /*WithInit=*/true);
   return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
                           SourceLocation());
 }
@@ -7077,8 +7083,7 @@
 }
 
 ExprResult Sema::getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
-                                       ExprObjectKind OK) {
-  SourceLocation Loc = Capture->getInit()->getExprLoc();
+                                       ExprObjectKind OK, SourceLocation Loc) {
   ExprResult Res = BuildDeclRefExpr(
       Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
   if (!Res.isUsable())
@@ -7236,7 +7241,7 @@
 
     DeclRefExpr *Ref = nullptr;
     if (!VD)
-      Ref = buildCapture(*this, D, SimpleRefExpr);
+      Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
     DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
     Vars.push_back(VD ? RefExpr->IgnoreParens() : Ref);
     PrivateCopies.push_back(VDPrivateRefExpr);
@@ -7520,7 +7525,7 @@
       if (TopDVar.CKind == OMPC_lastprivate)
         Ref = TopDVar.PrivateCopy;
       else {
-        Ref = buildCapture(*this, D, SimpleRefExpr);
+        Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
         if (!IsOpenMPCapturedDecl(D))
           ExprCaptures.push_back(Ref->getDecl());
       }
@@ -7665,13 +7670,13 @@
       if (TopDVar.CKind == OMPC_firstprivate)
         Ref = TopDVar.PrivateCopy;
       else {
-        Ref = buildCapture(*this, D, SimpleRefExpr);
+        Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
         if (!IsOpenMPCapturedDecl(D))
           ExprCaptures.push_back(Ref->getDecl());
       }
       if (TopDVar.CKind == OMPC_firstprivate ||
           (!IsOpenMPCapturedDecl(D) &&
-           !Ref->getDecl()->getType()->isReferenceType())) {
+           !cast<OMPCapturedExprDecl>(Ref->getDecl())->getInit())) {
         ExprResult RefRes = DefaultLvalueConversion(Ref);
         if (!RefRes.isUsable())
           continue;
@@ -7754,7 +7759,7 @@
 
     DeclRefExpr *Ref = nullptr;
     if (!VD)
-      Ref = buildCapture(*this, D, SimpleRefExpr);
+      Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
     DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
     Vars.push_back(VD ? RefExpr->IgnoreParens() : Ref);
   }
@@ -7811,7 +7816,7 @@
   ExprResult TransformMemberExpr(MemberExpr *E) {
     if (isa<CXXThisExpr>(E->getBase()->IgnoreParenImpCasts()) &&
         E->getMemberDecl() == Field) {
-      CapturedExpr = buildCapture(SemaRef, Field, E);
+      CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
       return CapturedExpr;
     }
     return BaseTransform::TransformMemberExpr(E);
@@ -7929,6 +7934,8 @@
   SmallVector<Expr *, 8> LHSs;
   SmallVector<Expr *, 8> RHSs;
   SmallVector<Expr *, 8> ReductionOps;
+  SmallVector<Decl *, 4> ExprCaptures;
+  SmallVector<Expr *, 4> ExprPostUpdates;
   for (auto RefExpr : VarList) {
     assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
     // OpenMP [2.1, C/C++]
@@ -8265,8 +8272,24 @@
         VarsExpr =
             RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
         Ref = RebuildToCapture.getCapturedExpr();
-      } else
-        VarsExpr = Ref = buildCapture(*this, D, SimpleRefExpr);
+      } else {
+        VarsExpr = Ref =
+            buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
+        if (!IsOpenMPCapturedDecl(D)) {
+          ExprCaptures.push_back(Ref->getDecl());
+          if (!cast<OMPCapturedExprDecl>(Ref->getDecl())->getInit()) {
+            ExprResult RefRes = DefaultLvalueConversion(Ref);
+            if (!RefRes.isUsable())
+              continue;
+            ExprResult PostUpdateRes =
+                BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
+                           SimpleRefExpr, RefRes.get());
+            if (!PostUpdateRes.isUsable())
+              continue;
+            ExprPostUpdates.push_back(PostUpdateRes.get());
+          }
+        }
+      }
     }
     DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref);
     Vars.push_back(VarsExpr);
@@ -8278,11 +8301,29 @@
 
   if (Vars.empty())
     return nullptr;
+  Stmt *PreInit = nullptr;
+  if (!ExprCaptures.empty()) {
+    PreInit = new (Context)
+        DeclStmt(DeclGroupRef::Create(Context, ExprCaptures.begin(),
+                                      ExprCaptures.size()),
+                 SourceLocation(), SourceLocation());
+  }
+  Expr *PostUpdate = nullptr;
+  if (!ExprPostUpdates.empty()) {
+    for (auto *E : ExprPostUpdates) {
+      ExprResult PostUpdateRes =
+          PostUpdate
+              ? CreateBuiltinBinOp(SourceLocation(), BO_Comma, PostUpdate, E)
+              : E;
+      PostUpdate = PostUpdateRes.get();
+    }
+  }
+
 
   return OMPReductionClause::Create(
       Context, StartLoc, LParenLoc, ColonLoc, EndLoc, Vars,
       ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId, Privates,
-      LHSs, RHSs, ReductionOps);
+      LHSs, RHSs, ReductionOps, PreInit, PostUpdate);
 }
 
 OMPClause *Sema::ActOnOpenMPLinearClause(