r265121 - [OPENMP 4.5] Allow data members as loop counters in loop-based

Alexey Bataev via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 1 02:23:34 PDT 2016


Author: abataev
Date: Fri Apr  1 04:23:34 2016
New Revision: 265121

URL: http://llvm.org/viewvc/llvm-project?rev=265121&view=rev
Log:
[OPENMP 4.5] Allow data members as loop counters in loop-based
directives.

OpenMP 4.5 allows privatization of non-static data members in non-static
member functions. Patch allows to use and implicit privatization of data
members used as counters in loop-based directives.

Modified:
    cfe/trunk/lib/Sema/SemaOpenMP.cpp
    cfe/trunk/test/OpenMP/for_lastprivate_codegen.cpp

Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=265121&r1=265120&r2=265121&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Fri Apr  1 04:23:34 2016
@@ -90,7 +90,8 @@ private:
   };
   typedef llvm::DenseMap<ValueDecl *, DSAInfo> DeclSAMapTy;
   typedef llvm::DenseMap<ValueDecl *, Expr *> AlignedMapTy;
-  typedef llvm::DenseMap<ValueDecl *, unsigned> LoopControlVariablesMapTy;
+  typedef std::pair<unsigned, VarDecl *> LCDeclInfo;
+  typedef llvm::DenseMap<ValueDecl *, LCDeclInfo> LoopControlVariablesMapTy;
   typedef llvm::DenseMap<ValueDecl *, MapInfo> MappedDeclsTy;
   typedef llvm::StringMap<std::pair<OMPCriticalDirective *, llvm::APSInt>>
       CriticalsWithHintsTy;
@@ -183,17 +184,17 @@ public:
   Expr *addUniqueAligned(ValueDecl *D, Expr *NewDE);
 
   /// \brief Register specified variable as loop control variable.
-  void addLoopControlVariable(ValueDecl *D);
+  void addLoopControlVariable(ValueDecl *D, VarDecl *Capture);
   /// \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(ValueDecl *D);
+  LCDeclInfo 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(ValueDecl *D);
+  LCDeclInfo isParentLoopControlVariable(ValueDecl *D);
   /// \brief Get the loop control variable for the I-th loop (or nullptr) in
   /// parent directive.
   ValueDecl *getParentLoopControlVariable(unsigned I);
@@ -522,24 +523,26 @@ Expr *DSAStackTy::addUniqueAligned(Value
   return nullptr;
 }
 
-void DSAStackTy::addLoopControlVariable(ValueDecl *D) {
+void DSAStackTy::addLoopControlVariable(ValueDecl *D, VarDecl *Capture) {
   assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");
   D = getCanonicalDecl(D);
-  Stack.back().LCVMap.insert(std::make_pair(D, Stack.back().LCVMap.size() + 1));
+  Stack.back().LCVMap.insert(
+      std::make_pair(D, LCDeclInfo(Stack.back().LCVMap.size() + 1, Capture)));
 }
 
-unsigned DSAStackTy::isLoopControlVariable(ValueDecl *D) {
+DSAStackTy::LCDeclInfo DSAStackTy::isLoopControlVariable(ValueDecl *D) {
   assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");
   D = getCanonicalDecl(D);
-  return Stack.back().LCVMap.count(D) > 0 ? Stack.back().LCVMap[D] : 0;
+  return Stack.back().LCVMap.count(D) > 0 ? Stack.back().LCVMap[D]
+                                          : LCDeclInfo(0, nullptr);
 }
 
-unsigned DSAStackTy::isParentLoopControlVariable(ValueDecl *D) {
+DSAStackTy::LCDeclInfo DSAStackTy::isParentLoopControlVariable(ValueDecl *D) {
   assert(Stack.size() > 2 && "Data-sharing attributes stack is empty");
   D = getCanonicalDecl(D);
   return Stack[Stack.size() - 2].LCVMap.count(D) > 0
              ? Stack[Stack.size() - 2].LCVMap[D]
-             : 0;
+             : LCDeclInfo(0, nullptr);
 }
 
 ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) {
@@ -547,7 +550,7 @@ ValueDecl *DSAStackTy::getParentLoopCont
   if (Stack[Stack.size() - 2].LCVMap.size() < I)
     return nullptr;
   for (auto &Pair : Stack[Stack.size() - 2].LCVMap) {
-    if (Pair.second == I)
+    if (Pair.second.first == I)
       return Pair.first;
   }
   return nullptr;
@@ -928,11 +931,12 @@ VarDecl *Sema::IsOpenMPCapturedDecl(Valu
   if (DSAStack->getCurrentDirective() != OMPD_unknown &&
       (!DSAStack->isClauseParsingMode() ||
        DSAStack->getParentDirective() != OMPD_unknown)) {
-    if (DSAStack->isLoopControlVariable(D) ||
+    auto &&Info = DSAStack->isLoopControlVariable(D);
+    if (Info.first ||
         (VD && VD->hasLocalStorage() &&
          isParallelOrTaskRegion(DSAStack->getCurrentDirective())) ||
         (VD && DSAStack->isForceVarCapturing()))
-      return VD;
+      return VD ? VD : Info.second;
     auto DVarPrivate = DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
     if (DVarPrivate.CKind != OMPC_unknown && isOpenMPPrivate(DVarPrivate.CKind))
       return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
@@ -3242,33 +3246,29 @@ class OpenMPIterationSpaceChecker {
   /// \brief A source location for referring to increment later.
   SourceRange IncrementSrcRange;
   /// \brief Loop variable.
-  VarDecl *Var;
+  ValueDecl *LCDecl = nullptr;
   /// \brief Reference to loop variable.
-  DeclRefExpr *VarRef;
+  Expr *LCRef = nullptr;
   /// \brief Lower bound (initializer for the var).
-  Expr *LB;
+  Expr *LB = nullptr;
   /// \brief Upper bound.
-  Expr *UB;
+  Expr *UB = nullptr;
   /// \brief Loop step (increment).
-  Expr *Step;
+  Expr *Step = nullptr;
   /// \brief This flag is true when condition is one of:
   ///   Var <  UB
   ///   Var <= UB
   ///   UB  >  Var
   ///   UB  >= Var
-  bool TestIsLessOp;
+  bool TestIsLessOp = false;
   /// \brief This flag is true when condition is strict ( < or > ).
-  bool TestIsStrictOp;
+  bool TestIsStrictOp = false;
   /// \brief This flag is true when step is subtracted on each iteration.
-  bool SubtractStep;
+  bool SubtractStep = false;
 
 public:
   OpenMPIterationSpaceChecker(Sema &SemaRef, SourceLocation DefaultLoc)
-      : SemaRef(SemaRef), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
-        InitSrcRange(SourceRange()), ConditionSrcRange(SourceRange()),
-        IncrementSrcRange(SourceRange()), Var(nullptr), VarRef(nullptr),
-        LB(nullptr), UB(nullptr), Step(nullptr), TestIsLessOp(false),
-        TestIsStrictOp(false), SubtractStep(false) {}
+      : SemaRef(SemaRef), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc) {}
   /// \brief Check init-expr for canonical loop form and save loop counter
   /// variable - #Var and its initialization value - #LB.
   bool CheckInit(Stmt *S, bool EmitDiags = true);
@@ -3279,9 +3279,9 @@ public:
   /// does not conform, otherwise save loop step (#Step).
   bool CheckInc(Expr *S);
   /// \brief Return the loop counter variable.
-  VarDecl *GetLoopVar() const { return Var; }
+  ValueDecl *GetLoopDecl() const { return LCDecl; }
   /// \brief Return the reference expression to loop counter variable.
-  DeclRefExpr *GetLoopVarRefExpr() const { return VarRef; }
+  Expr *GetLoopDeclRefExpr() const { return LCRef; }
   /// \brief Source range of the loop init.
   SourceRange GetInitSrcRange() const { return InitSrcRange; }
   /// \brief Source range of the loop condition.
@@ -3298,7 +3298,8 @@ public:
   Expr *BuildPreCond(Scope *S, Expr *Cond,
                      llvm::MapVector<Expr *, DeclRefExpr *> &Captures) const;
   /// \brief Build reference expression to the counter be used for codegen.
-  Expr *BuildCounterVar() const;
+  DeclRefExpr *
+  BuildCounterVar(llvm::MapVector<Expr *, DeclRefExpr *> &Captures) const;
   /// \brief Build reference expression to the private counter be used for
   /// codegen.
   Expr *BuildPrivateCounterVar() const;
@@ -3314,7 +3315,7 @@ private:
   /// expression.
   bool CheckIncRHS(Expr *RHS);
   /// \brief Helper to set loop counter variable and its initializer.
-  bool SetVarAndLB(VarDecl *NewVar, DeclRefExpr *NewVarRefExpr, Expr *NewLB);
+  bool SetLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB);
   /// \brief Helper to set upper bound.
   bool SetUB(Expr *NewUB, bool LessOp, bool StrictOp, SourceRange SR,
              SourceLocation SL);
@@ -3323,16 +3324,16 @@ private:
 };
 
 bool OpenMPIterationSpaceChecker::Dependent() const {
-  if (!Var) {
+  if (!LCDecl) {
     assert(!LB && !UB && !Step);
     return false;
   }
-  return Var->getType()->isDependentType() || (LB && LB->isValueDependent()) ||
-         (UB && UB->isValueDependent()) || (Step && Step->isValueDependent());
+  return LCDecl->getType()->isDependentType() ||
+         (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
+         (Step && Step->isValueDependent());
 }
 
-template <typename T>
-static T *getExprAsWritten(T *E) {
+static Expr *getExprAsWritten(Expr *E) {
   if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(E))
     E = ExprTemp->getSubExpr();
 
@@ -3347,16 +3348,16 @@ static T *getExprAsWritten(T *E) {
   return E->IgnoreParens();
 }
 
-bool OpenMPIterationSpaceChecker::SetVarAndLB(VarDecl *NewVar,
-                                              DeclRefExpr *NewVarRefExpr,
-                                              Expr *NewLB) {
+bool OpenMPIterationSpaceChecker::SetLCDeclAndLB(ValueDecl *NewLCDecl,
+                                                 Expr *NewLCRefExpr,
+                                                 Expr *NewLB) {
   // State consistency checking to ensure correct usage.
-  assert(Var == nullptr && LB == nullptr && VarRef == nullptr &&
+  assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
          UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
-  if (!NewVar || !NewLB)
+  if (!NewLCDecl || !NewLB)
     return true;
-  Var = NewVar;
-  VarRef = NewVarRefExpr;
+  LCDecl = getCanonicalDecl(NewLCDecl);
+  LCRef = NewLCRefExpr;
   if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
     if (const CXXConstructorDecl *Ctor = CE->getConstructor())
       if ((Ctor->isCopyOrMoveConstructor() ||
@@ -3370,8 +3371,8 @@ bool OpenMPIterationSpaceChecker::SetVar
 bool OpenMPIterationSpaceChecker::SetUB(Expr *NewUB, bool LessOp, bool StrictOp,
                                         SourceRange SR, SourceLocation SL) {
   // State consistency checking to ensure correct usage.
-  assert(Var != nullptr && LB != nullptr && UB == nullptr && Step == nullptr &&
-         !TestIsLessOp && !TestIsStrictOp);
+  assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
+         Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
   if (!NewUB)
     return true;
   UB = NewUB;
@@ -3384,7 +3385,7 @@ bool OpenMPIterationSpaceChecker::SetUB(
 
 bool OpenMPIterationSpaceChecker::SetStep(Expr *NewStep, bool Subtract) {
   // State consistency checking to ensure correct usage.
-  assert(Var != nullptr && LB != nullptr && Step == nullptr);
+  assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
   if (!NewStep)
     return true;
   if (!NewStep->isValueDependent()) {
@@ -3420,7 +3421,7 @@ bool OpenMPIterationSpaceChecker::SetSte
                              : (IsConstPos || (IsUnsigned && !Subtract))))) {
       SemaRef.Diag(NewStep->getExprLoc(),
                    diag::err_omp_loop_incr_not_compatible)
-          << Var << TestIsLessOp << NewStep->getSourceRange();
+          << LCDecl << TestIsLessOp << NewStep->getSourceRange();
       SemaRef.Diag(ConditionLoc,
                    diag::note_omp_loop_cond_requres_compatible_incr)
           << TestIsLessOp << ConditionSrcRange;
@@ -3457,10 +3458,20 @@ bool OpenMPIterationSpaceChecker::CheckI
   if (Expr *E = dyn_cast<Expr>(S))
     S = E->IgnoreParens();
   if (auto BO = dyn_cast<BinaryOperator>(S)) {
-    if (BO->getOpcode() == BO_Assign)
-      if (auto DRE = dyn_cast<DeclRefExpr>(BO->getLHS()->IgnoreParens()))
-        return SetVarAndLB(dyn_cast<VarDecl>(DRE->getDecl()), DRE,
-                           BO->getRHS());
+    if (BO->getOpcode() == BO_Assign) {
+      auto *LHS = BO->getLHS()->IgnoreParens();
+      if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
+        if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
+          if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
+            return SetLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS());
+        return SetLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS());
+      }
+      if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
+        if (ME->isArrow() &&
+            isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
+          return SetLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS());
+      }
+    }
   } else if (auto DS = dyn_cast<DeclStmt>(S)) {
     if (DS->isSingleDecl()) {
       if (auto Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
@@ -3470,16 +3481,29 @@ bool OpenMPIterationSpaceChecker::CheckI
             SemaRef.Diag(S->getLocStart(),
                          diag::ext_omp_loop_not_canonical_init)
                 << S->getSourceRange();
-          return SetVarAndLB(Var, nullptr, Var->getInit());
+          return SetLCDeclAndLB(Var, nullptr, Var->getInit());
         }
       }
     }
-  } else if (auto CE = dyn_cast<CXXOperatorCallExpr>(S))
-    if (CE->getOperator() == OO_Equal)
-      if (auto DRE = dyn_cast<DeclRefExpr>(CE->getArg(0)))
-        return SetVarAndLB(dyn_cast<VarDecl>(DRE->getDecl()), DRE,
-                           CE->getArg(1));
+  } else if (auto CE = dyn_cast<CXXOperatorCallExpr>(S)) {
+    if (CE->getOperator() == OO_Equal) {
+      auto *LHS = CE->getArg(0);
+      if (auto DRE = dyn_cast<DeclRefExpr>(LHS)) {
+        if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
+          if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
+            return SetLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS());
+        return SetLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1));
+      }
+      if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
+        if (ME->isArrow() &&
+            isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
+          return SetLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS());
+      }
+    }
+  }
 
+  if (Dependent() || SemaRef.CurContext->isDependentContext())
+    return false;
   if (EmitDiags) {
     SemaRef.Diag(S->getLocStart(), diag::err_omp_loop_not_canonical_init)
         << S->getSourceRange();
@@ -3489,7 +3513,7 @@ bool OpenMPIterationSpaceChecker::CheckI
 
 /// \brief Ignore parenthesizes, implicit casts, copy constructor and return the
 /// variable (which may be the loop variable) if possible.
-static const VarDecl *GetInitVarDecl(const Expr *E) {
+static const ValueDecl *GetInitLCDecl(Expr *E) {
   if (!E)
     return nullptr;
   E = getExprAsWritten(E);
@@ -3499,10 +3523,18 @@ static const VarDecl *GetInitVarDecl(con
            Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
           CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
         E = CE->getArg(0)->IgnoreParenImpCasts();
-  auto DRE = dyn_cast_or_null<DeclRefExpr>(E);
-  if (!DRE)
-    return nullptr;
-  return dyn_cast<VarDecl>(DRE->getDecl());
+  if (auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
+    if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
+      if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
+        if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
+          return getCanonicalDecl(ME->getMemberDecl());
+      return getCanonicalDecl(VD);
+    }
+  }
+  if (auto *ME = dyn_cast_or_null<MemberExpr>(E))
+    if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
+      return getCanonicalDecl(ME->getMemberDecl());
+  return nullptr;
 }
 
 bool OpenMPIterationSpaceChecker::CheckCond(Expr *S) {
@@ -3513,19 +3545,19 @@ bool OpenMPIterationSpaceChecker::CheckC
   //   b relational-op var
   //
   if (!S) {
-    SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond) << Var;
+    SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond) << LCDecl;
     return true;
   }
   S = getExprAsWritten(S);
   SourceLocation CondLoc = S->getLocStart();
   if (auto BO = dyn_cast<BinaryOperator>(S)) {
     if (BO->isRelationalOp()) {
-      if (GetInitVarDecl(BO->getLHS()) == Var)
+      if (GetInitLCDecl(BO->getLHS()) == LCDecl)
         return SetUB(BO->getRHS(),
                      (BO->getOpcode() == BO_LT || BO->getOpcode() == BO_LE),
                      (BO->getOpcode() == BO_LT || BO->getOpcode() == BO_GT),
                      BO->getSourceRange(), BO->getOperatorLoc());
-      if (GetInitVarDecl(BO->getRHS()) == Var)
+      if (GetInitLCDecl(BO->getRHS()) == LCDecl)
         return SetUB(BO->getLHS(),
                      (BO->getOpcode() == BO_GT || BO->getOpcode() == BO_GE),
                      (BO->getOpcode() == BO_LT || BO->getOpcode() == BO_GT),
@@ -3539,11 +3571,11 @@ bool OpenMPIterationSpaceChecker::CheckC
       case OO_GreaterEqual:
       case OO_Less:
       case OO_LessEqual:
-        if (GetInitVarDecl(CE->getArg(0)) == Var)
+        if (GetInitLCDecl(CE->getArg(0)) == LCDecl)
           return SetUB(CE->getArg(1), Op == OO_Less || Op == OO_LessEqual,
                        Op == OO_Less || Op == OO_Greater, CE->getSourceRange(),
                        CE->getOperatorLoc());
-        if (GetInitVarDecl(CE->getArg(1)) == Var)
+        if (GetInitLCDecl(CE->getArg(1)) == LCDecl)
           return SetUB(CE->getArg(0), Op == OO_Greater || Op == OO_GreaterEqual,
                        Op == OO_Less || Op == OO_Greater, CE->getSourceRange(),
                        CE->getOperatorLoc());
@@ -3553,8 +3585,10 @@ bool OpenMPIterationSpaceChecker::CheckC
       }
     }
   }
+  if (Dependent() || SemaRef.CurContext->isDependentContext())
+    return false;
   SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
-      << S->getSourceRange() << Var;
+      << S->getSourceRange() << LCDecl;
   return true;
 }
 
@@ -3568,22 +3602,24 @@ bool OpenMPIterationSpaceChecker::CheckI
   if (auto BO = dyn_cast<BinaryOperator>(RHS)) {
     if (BO->isAdditiveOp()) {
       bool IsAdd = BO->getOpcode() == BO_Add;
-      if (GetInitVarDecl(BO->getLHS()) == Var)
+      if (GetInitLCDecl(BO->getLHS()) == LCDecl)
         return SetStep(BO->getRHS(), !IsAdd);
-      if (IsAdd && GetInitVarDecl(BO->getRHS()) == Var)
+      if (IsAdd && GetInitLCDecl(BO->getRHS()) == LCDecl)
         return SetStep(BO->getLHS(), false);
     }
   } else if (auto CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
     bool IsAdd = CE->getOperator() == OO_Plus;
     if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
-      if (GetInitVarDecl(CE->getArg(0)) == Var)
+      if (GetInitLCDecl(CE->getArg(0)) == LCDecl)
         return SetStep(CE->getArg(1), !IsAdd);
-      if (IsAdd && GetInitVarDecl(CE->getArg(1)) == Var)
+      if (IsAdd && GetInitLCDecl(CE->getArg(1)) == LCDecl)
         return SetStep(CE->getArg(0), false);
     }
   }
+  if (Dependent() || SemaRef.CurContext->isDependentContext())
+    return false;
   SemaRef.Diag(RHS->getLocStart(), diag::err_omp_loop_not_canonical_incr)
-      << RHS->getSourceRange() << Var;
+      << RHS->getSourceRange() << LCDecl;
   return true;
 }
 
@@ -3602,13 +3638,14 @@ bool OpenMPIterationSpaceChecker::CheckI
   //   var = var - incr
   //
   if (!S) {
-    SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << Var;
+    SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
     return true;
   }
   IncrementSrcRange = S->getSourceRange();
   S = S->IgnoreParens();
   if (auto UO = dyn_cast<UnaryOperator>(S)) {
-    if (UO->isIncrementDecrementOp() && GetInitVarDecl(UO->getSubExpr()) == Var)
+    if (UO->isIncrementDecrementOp() &&
+        GetInitLCDecl(UO->getSubExpr()) == LCDecl)
       return SetStep(
           SemaRef.ActOnIntegerConstant(UO->getLocStart(),
                                        (UO->isDecrementOp() ? -1 : 1)).get(),
@@ -3617,11 +3654,11 @@ bool OpenMPIterationSpaceChecker::CheckI
     switch (BO->getOpcode()) {
     case BO_AddAssign:
     case BO_SubAssign:
-      if (GetInitVarDecl(BO->getLHS()) == Var)
+      if (GetInitLCDecl(BO->getLHS()) == LCDecl)
         return SetStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
       break;
     case BO_Assign:
-      if (GetInitVarDecl(BO->getLHS()) == Var)
+      if (GetInitLCDecl(BO->getLHS()) == LCDecl)
         return CheckIncRHS(BO->getRHS());
       break;
     default:
@@ -3631,7 +3668,7 @@ bool OpenMPIterationSpaceChecker::CheckI
     switch (CE->getOperator()) {
     case OO_PlusPlus:
     case OO_MinusMinus:
-      if (GetInitVarDecl(CE->getArg(0)) == Var)
+      if (GetInitLCDecl(CE->getArg(0)) == LCDecl)
         return SetStep(
             SemaRef.ActOnIntegerConstant(
                         CE->getLocStart(),
@@ -3640,19 +3677,21 @@ bool OpenMPIterationSpaceChecker::CheckI
       break;
     case OO_PlusEqual:
     case OO_MinusEqual:
-      if (GetInitVarDecl(CE->getArg(0)) == Var)
+      if (GetInitLCDecl(CE->getArg(0)) == LCDecl)
         return SetStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
       break;
     case OO_Equal:
-      if (GetInitVarDecl(CE->getArg(0)) == Var)
+      if (GetInitLCDecl(CE->getArg(0)) == LCDecl)
         return CheckIncRHS(CE->getArg(1));
       break;
     default:
       break;
     }
   }
+  if (Dependent() || SemaRef.CurContext->isDependentContext())
+    return false;
   SemaRef.Diag(S->getLocStart(), diag::err_omp_loop_not_canonical_incr)
-      << S->getSourceRange() << Var;
+      << S->getSourceRange() << LCDecl;
   return true;
 }
 
@@ -3677,7 +3716,7 @@ Expr *OpenMPIterationSpaceChecker::Build
     Scope *S, const bool LimitedType,
     llvm::MapVector<Expr *, DeclRefExpr *> &Captures) const {
   ExprResult Diff;
-  auto VarType = Var->getType().getNonReferenceType();
+  auto VarType = LCDecl->getType().getNonReferenceType();
   if (VarType->isIntegerType() || VarType->isPointerType() ||
       SemaRef.getLangOpts().CPlusPlus) {
     // Upper - Lower
@@ -3798,17 +3837,26 @@ Expr *OpenMPIterationSpaceChecker::Build
 }
 
 /// \brief Build reference expression to the counter be used for codegen.
-Expr *OpenMPIterationSpaceChecker::BuildCounterVar() const {
-  return buildDeclRefExpr(SemaRef, Var, Var->getType().getNonReferenceType(),
+DeclRefExpr *OpenMPIterationSpaceChecker::BuildCounterVar(
+    llvm::MapVector<Expr *, DeclRefExpr *> &Captures) const {
+  auto *VD = dyn_cast<VarDecl>(LCDecl);
+  if (!VD) {
+    VD = SemaRef.IsOpenMPCapturedDecl(LCDecl);
+    auto *Ref = buildDeclRefExpr(
+        SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
+    Captures.insert(std::make_pair(LCRef, Ref));
+    return Ref;
+  }
+  return buildDeclRefExpr(SemaRef, VD, VD->getType().getNonReferenceType(),
                           DefaultLoc);
 }
 
 Expr *OpenMPIterationSpaceChecker::BuildPrivateCounterVar() const {
-  if (Var && !Var->isInvalidDecl()) {
-    auto Type = Var->getType().getNonReferenceType();
+  if (LCDecl && !LCDecl->isInvalidDecl()) {
+    auto Type = LCDecl->getType().getNonReferenceType();
     auto *PrivateVar =
-        buildVarDecl(SemaRef, DefaultLoc, Type, Var->getName(),
-                     Var->hasAttrs() ? &Var->getAttrs() : nullptr);
+        buildVarDecl(SemaRef, DefaultLoc, Type, LCDecl->getName(),
+                     LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr);
     if (PrivateVar->isInvalidDecl())
       return nullptr;
     return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
@@ -3857,8 +3905,21 @@ void Sema::ActOnOpenMPLoopInitialization
   if (AssociatedLoops > 0 &&
       isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
     OpenMPIterationSpaceChecker ISC(*this, ForLoc);
-    if (!ISC.CheckInit(Init, /*EmitDiags=*/false))
-      DSAStack->addLoopControlVariable(ISC.GetLoopVar());
+    if (!ISC.CheckInit(Init, /*EmitDiags=*/false)) {
+      if (auto *D = ISC.GetLoopDecl()) {
+        auto *VD = dyn_cast<VarDecl>(D);
+        if (!VD) {
+          if (auto *Private = IsOpenMPCapturedDecl(D))
+            VD = Private;
+          else {
+            auto *Ref = buildCapture(*this, D, ISC.GetLoopDeclRefExpr(),
+                                     /*WithInit=*/false);
+            VD = cast<VarDecl>(Ref->getDecl());
+          }
+        }
+        DSAStack->addLoopControlVariable(D, VD);
+      }
+    }
     DSAStack->setAssociatedLoops(AssociatedLoops - 1);
   }
 }
@@ -3903,87 +3964,88 @@ static bool CheckOpenMPIterationSpace(
 
   // Check init.
   auto Init = For->getInit();
-  if (ISC.CheckInit(Init)) {
+  if (ISC.CheckInit(Init))
     return true;
-  }
 
   bool HasErrors = false;
 
   // Check loop variable's type.
-  auto Var = ISC.GetLoopVar();
+  if (auto *LCDecl = ISC.GetLoopDecl()) {
+    auto *LoopDeclRefExpr = ISC.GetLoopDeclRefExpr();
 
-  // OpenMP [2.6, Canonical Loop Form]
-  // Var is one of the following:
-  //   A variable of signed or unsigned integer type.
-  //   For C++, a variable of a random access iterator type.
-  //   For C, a variable of a pointer type.
-  auto VarType = Var->getType().getNonReferenceType();
-  if (!VarType->isDependentType() && !VarType->isIntegerType() &&
-      !VarType->isPointerType() &&
-      !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
-    SemaRef.Diag(Init->getLocStart(), diag::err_omp_loop_variable_type)
-        << SemaRef.getLangOpts().CPlusPlus;
-    HasErrors = true;
-  }
-
-  // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in a
-  // Construct
-  // The loop iteration variable(s) in the associated for-loop(s) of a for or
-  // parallel for construct is (are) private.
-  // The loop iteration variable in the associated for-loop of a simd construct
-  // with just one associated for-loop is linear with a constant-linear-step
-  // that is the increment of the associated for-loop.
-  // Exclude loop var from the list of variables with implicitly defined data
-  // sharing attributes.
-  VarsWithImplicitDSA.erase(Var);
-
-  // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced in
-  // a Construct, C/C++].
-  // The loop iteration variable in the associated for-loop of a simd construct
-  // with just one associated for-loop may be listed in a linear clause with a
-  // constant-linear-step that is the increment of the associated for-loop.
-  // The loop iteration variable(s) in the associated for-loop(s) of a for or
-  // parallel for construct may be listed in a private or lastprivate clause.
-  DSAStackTy::DSAVarData DVar = DSA.getTopDSA(Var, false);
-  auto LoopVarRefExpr = ISC.GetLoopVarRefExpr();
-  // If LoopVarRefExpr is nullptr it means the corresponding loop variable is
-  // declared in the loop and it is predetermined as a private.
-  auto PredeterminedCKind =
-      isOpenMPSimdDirective(DKind)
-          ? ((NestedLoopCount == 1) ? OMPC_linear : OMPC_lastprivate)
-          : OMPC_private;
-  if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
-        DVar.CKind != PredeterminedCKind) ||
-       ((isOpenMPWorksharingDirective(DKind) || DKind == OMPD_taskloop ||
-         isOpenMPDistributeDirective(DKind)) &&
-        !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
-        DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
-      (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
-    SemaRef.Diag(Init->getLocStart(), diag::err_omp_loop_var_dsa)
-        << getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind)
-        << getOpenMPClauseName(PredeterminedCKind);
-    if (DVar.RefExpr == nullptr)
-      DVar.CKind = PredeterminedCKind;
-    ReportOriginalDSA(SemaRef, &DSA, Var, DVar, /*IsLoopIterVar=*/true);
-    HasErrors = true;
-  } else if (LoopVarRefExpr != nullptr) {
-    // Make the loop iteration variable private (for worksharing constructs),
-    // linear (for simd directives with the only one associated loop) or
-    // lastprivate (for simd directives with several collapsed or ordered
-    // loops).
-    if (DVar.CKind == OMPC_unknown)
-      DVar = DSA.hasDSA(Var, isOpenMPPrivate, MatchesAlways(),
-                        /*FromParent=*/false);
-    DSA.addDSA(Var, LoopVarRefExpr, PredeterminedCKind);
-  }
+    // OpenMP [2.6, Canonical Loop Form]
+    // Var is one of the following:
+    //   A variable of signed or unsigned integer type.
+    //   For C++, a variable of a random access iterator type.
+    //   For C, a variable of a pointer type.
+    auto VarType = LCDecl->getType().getNonReferenceType();
+    if (!VarType->isDependentType() && !VarType->isIntegerType() &&
+        !VarType->isPointerType() &&
+        !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
+      SemaRef.Diag(Init->getLocStart(), diag::err_omp_loop_variable_type)
+          << SemaRef.getLangOpts().CPlusPlus;
+      HasErrors = true;
+    }
+
+    // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
+    // a Construct
+    // The loop iteration variable(s) in the associated for-loop(s) of a for or
+    // parallel for construct is (are) private.
+    // The loop iteration variable in the associated for-loop of a simd
+    // construct with just one associated for-loop is linear with a
+    // constant-linear-step that is the increment of the associated for-loop.
+    // Exclude loop var from the list of variables with implicitly defined data
+    // sharing attributes.
+    VarsWithImplicitDSA.erase(LCDecl);
+
+    // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
+    // in a Construct, C/C++].
+    // The loop iteration variable in the associated for-loop of a simd
+    // construct with just one associated for-loop may be listed in a linear
+    // clause with a constant-linear-step that is the increment of the
+    // associated for-loop.
+    // The loop iteration variable(s) in the associated for-loop(s) of a for or
+    // parallel for construct may be listed in a private or lastprivate clause.
+    DSAStackTy::DSAVarData DVar = DSA.getTopDSA(LCDecl, false);
+    // If LoopVarRefExpr is nullptr it means the corresponding loop variable is
+    // declared in the loop and it is predetermined as a private.
+    auto PredeterminedCKind =
+        isOpenMPSimdDirective(DKind)
+            ? ((NestedLoopCount == 1) ? OMPC_linear : OMPC_lastprivate)
+            : OMPC_private;
+    if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
+          DVar.CKind != PredeterminedCKind) ||
+         ((isOpenMPWorksharingDirective(DKind) || DKind == OMPD_taskloop ||
+           isOpenMPDistributeDirective(DKind)) &&
+          !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
+          DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
+        (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
+      SemaRef.Diag(Init->getLocStart(), diag::err_omp_loop_var_dsa)
+          << getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind)
+          << getOpenMPClauseName(PredeterminedCKind);
+      if (DVar.RefExpr == nullptr)
+        DVar.CKind = PredeterminedCKind;
+      ReportOriginalDSA(SemaRef, &DSA, LCDecl, DVar, /*IsLoopIterVar=*/true);
+      HasErrors = true;
+    } else if (LoopDeclRefExpr != nullptr) {
+      // Make the loop iteration variable private (for worksharing constructs),
+      // linear (for simd directives with the only one associated loop) or
+      // lastprivate (for simd directives with several collapsed or ordered
+      // loops).
+      if (DVar.CKind == OMPC_unknown)
+        DVar = DSA.hasDSA(LCDecl, isOpenMPPrivate, MatchesAlways(),
+                          /*FromParent=*/false);
+      DSA.addDSA(LCDecl, LoopDeclRefExpr, PredeterminedCKind);
+    }
 
-  assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
+    assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
 
-  // Check test-expr.
-  HasErrors |= ISC.CheckCond(For->getCond());
+    // Check test-expr.
+    HasErrors |= ISC.CheckCond(For->getCond());
 
-  // Check incr-expr.
-  HasErrors |= ISC.CheckInc(For->getInc());
+    // Check incr-expr.
+    HasErrors |= ISC.CheckInc(For->getInc());
+  }
 
   if (ISC.Dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
     return HasErrors;
@@ -3996,7 +4058,7 @@ static bool CheckOpenMPIterationSpace(
       (isOpenMPWorksharingDirective(DKind) ||
        isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind)),
       Captures);
-  ResultIterSpace.CounterVar = ISC.BuildCounterVar();
+  ResultIterSpace.CounterVar = ISC.BuildCounterVar(Captures);
   ResultIterSpace.PrivateCounterVar = ISC.BuildPrivateCounterVar();
   ResultIterSpace.CounterInit = ISC.BuildCounterInit();
   ResultIterSpace.CounterStep = ISC.BuildCounterStep();
@@ -9112,7 +9174,8 @@ Sema::ActOnOpenMPDependClause(OpenMPDepe
         auto *VD = dyn_cast<VarDecl>(DE->getDecl());
         if (!CurContext->isDependentContext() &&
             DSAStack->getParentOrderedRegionParam() &&
-            (!VD || DepCounter != DSAStack->isParentLoopControlVariable(VD))) {
+            (!VD ||
+             DepCounter != DSAStack->isParentLoopControlVariable(VD).first)) {
           Diag(DE->getExprLoc(),
                diag::err_omp_depend_sink_expected_loop_iteration)
               << DSAStack->getParentLoopControlVariable(

Modified: cfe/trunk/test/OpenMP/for_lastprivate_codegen.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_lastprivate_codegen.cpp?rev=265121&r1=265120&r2=265121&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/for_lastprivate_codegen.cpp (original)
+++ cfe/trunk/test/OpenMP/for_lastprivate_codegen.cpp Fri Apr  1 04:23:34 2016
@@ -37,6 +37,29 @@ struct SS {
 #else
       ++this->a, --b, c /= 1;
 #endif
+#pragma omp for
+    for (a = 0; a < 2; ++a)
+#ifdef LAMBDA
+      [&]() {
+        ++this->a, --b, (this)->c /= 1;
+#pragma omp parallel
+#pragma omp for lastprivate(b)
+        for (b = 0; b < 2; ++b)
+          ++(this)->a, --b, this->c /= 1;
+      }();
+#elif defined(BLOCKS)
+      ^{
+        ++a;
+        --this->b;
+        (this)->c /= 1;
+#pragma omp parallel
+#pragma omp for
+        for (c = 0; c < 2; ++c)
+          ++(this)->a, --b, this->c /= 1;
+      }();
+#else
+      ++this->a, --b, c /= 1;
+#endif
   }
 };
 
@@ -70,6 +93,27 @@ struct SST {
 #else
       ++(this)->a;
 #endif
+#pragma omp for
+    for (a = 0; a < 2; ++a)
+#ifdef LAMBDA
+      [&]() {
+        ++this->a;
+#pragma omp parallel
+#pragma omp for
+        for (a = 0; a < 2; ++(this)->a)
+          ++(this)->a;
+      }();
+#elif defined(BLOCKS)
+      ^{
+        ++a;
+#pragma omp parallel
+#pragma omp for
+        for (this->a = 0; a < 2; ++a)
+          ++(this)->a;
+      }();
+#else
+      ++(this)->a;
+#endif
   }
 };
 
@@ -144,6 +188,11 @@ int main() {
     // LAMBDA: store i8
     // LAMBDA: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 2
     // LAMBDA: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [[SS_TY]]*)* [[SS_MICROTASK:@.+]] to void
+    // LAMBDA: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 0
+    // LAMBDA: call void @__kmpc_for_static_init_4(
+    // LAMBDA-NOT: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 0
+    // LAMBDA: call void {{.+}} [[SS_LAMBDA:@[^ ]+]]
+    // LAMBDA: call void @__kmpc_for_static_fini(%
     // LAMBDA: ret
 
     // LAMBDA: define internal void [[SS_MICROTASK]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [[SS_TY]]* %{{.+}})
@@ -322,6 +371,11 @@ int main() {
 // BLOCKS: store i8
 // BLOCKS: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 2
 // BLOCKS: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [[SS_TY]]*)* [[SS_MICROTASK:@.+]] to void
+// BLOCKS: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 0
+// BLOCKS: call void @__kmpc_for_static_init_4(
+// BLOCKS-NOT: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 0
+// BLOCKS: call void
+// BLOCKS: call void @__kmpc_for_static_fini(%
 // BLOCKS: ret
 
 // BLOCKS: define internal void [[SS_MICROTASK]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [[SS_TY]]* %{{.+}})
@@ -596,6 +650,12 @@ int main() {
 // CHECK: store i8
 // CHECK: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 2
 // CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [[SS_TY]]*)* [[SS_MICROTASK:@.+]] to void
+// CHECK: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 0
+// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK-NOT: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 0
+// CHECK: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 1
+// CHECK: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 2
+// CHECK: call void @__kmpc_for_static_fini(%
 // CHECK: ret
 
 // CHECK: define internal void [[SS_MICROTASK]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [[SS_TY]]* %{{.+}})




More information about the cfe-commits mailing list