r262199 - [OPENMP 4.5] Initial support for data members in 'reduction' clauses.

Alexey Bataev via cfe-commits cfe-commits at lists.llvm.org
Sun Feb 28 21:54:21 PST 2016


Author: abataev
Date: Sun Feb 28 23:54:20 2016
New Revision: 262199

URL: http://llvm.org/viewvc/llvm-project?rev=262199&view=rev
Log:
[OPENMP 4.5] Initial support for data members in 'reduction' clauses.

OpenMP 4.5 allows to privatize non-static data members of current class
in non-static member functions. Patch adds initial parsing/semantic
analysis for data members support in 'reduction' clauses.

Modified:
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/lib/Sema/SemaOpenMP.cpp
    cfe/trunk/test/OpenMP/parallel_ast_print.cpp

Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=262199&r1=262198&r2=262199&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Sun Feb 28 23:54:20 2016
@@ -666,14 +666,7 @@ void OMPClausePrinter::VisitOMPScheduleC
   OS << getOpenMPSimpleClauseTypeName(OMPC_schedule, Node->getScheduleKind());
   if (auto *E = Node->getChunkSize()) {
     OS << ", ";
-    if (Node->getPreInitStmt()) {
-      cast<OMPCapturedExprDecl>(
-          cast<DeclRefExpr>(E->IgnoreImpCasts())->getDecl())
-          ->getInit()
-          ->IgnoreImpCasts()
-          ->printPretty(OS, nullptr, Policy);
-    } else
-      E->printPretty(OS, nullptr, Policy);
+    E->printPretty(OS, nullptr, Policy);
   }
   OS << ")";
 }
@@ -775,8 +768,8 @@ void OMPClausePrinter::VisitOMPClauseLis
     assert(*I && "Expected non-null Stmt");
     OS << (I == Node->varlist_begin() ? StartSym : ',');
     if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(*I)) {
-      if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
-        CED->getInit()->IgnoreImpCasts()->printPretty(OS, nullptr, Policy, 0);
+      if (isa<OMPCapturedExprDecl>(DRE->getDecl()))
+        DRE->printPretty(OS, nullptr, Policy, 0);
       else
         DRE->getDecl()->printQualifiedName(OS);
     } else
@@ -924,14 +917,7 @@ void OMPClausePrinter::VisitOMPDistSched
                            OMPC_dist_schedule, Node->getDistScheduleKind());
   if (auto *E = Node->getChunkSize()) {
     OS << ", ";
-    if (Node->getPreInitStmt()) {
-      cast<OMPCapturedExprDecl>(
-          cast<DeclRefExpr>(E->IgnoreImpCasts())->getDecl())
-          ->getInit()
-          ->IgnoreImpCasts()
-          ->printPretty(OS, nullptr, Policy);
-    } else
-      E->printPretty(OS, nullptr, Policy);
+    E->printPretty(OS, nullptr, Policy);
   }
   OS << ")";
 }
@@ -1150,6 +1136,10 @@ void StmtPrinter::VisitOMPDistributeDire
 //===----------------------------------------------------------------------===//
 
 void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
+  if (auto *OCED = dyn_cast<OMPCapturedExprDecl>(Node->getDecl())) {
+    OCED->getInit()->IgnoreImpCasts()->printPretty(OS, nullptr, Policy);
+    return;
+  }
   if (NestedNameSpecifier *Qualifier = Node->getQualifier())
     Qualifier->print(OS, Policy);
   if (Node->hasTemplateKeyword())

Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=262199&r1=262198&r2=262199&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Sun Feb 28 23:54:20 2016
@@ -7096,27 +7096,60 @@ ExprResult Sema::getOpenMPCapturedExpr(V
   return Res;
 }
 
-static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *RefExpr) {
+static std::pair<ValueDecl *, bool>
+getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
+               SourceRange &ERange, bool AllowArraySection = false) {
   if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
       RefExpr->containsUnexpandedParameterPack())
     return std::make_pair(nullptr, true);
 
-  SourceLocation ELoc = RefExpr->getExprLoc();
-  SourceRange SR = RefExpr->getSourceRange();
   // OpenMP [3.1, C/C++]
   //  A list item is a variable name.
   // 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.
   RefExpr = RefExpr->IgnoreParens();
+  enum {
+    NoArrayExpr = -1,
+    ArraySubscript = 0,
+    OMPArraySection = 1
+  } IsArrayExpr = NoArrayExpr;
+  if (AllowArraySection) {
+    if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
+      auto *Base = ASE->getBase()->IgnoreParenImpCasts();
+      while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
+        Base = TempASE->getBase()->IgnoreParenImpCasts();
+      RefExpr = Base;
+      IsArrayExpr = ArraySubscript;
+    } else if (auto *OASE = dyn_cast_or_null<OMPArraySectionExpr>(RefExpr)) {
+      auto *Base = OASE->getBase()->IgnoreParenImpCasts();
+      while (auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
+        Base = TempOASE->getBase()->IgnoreParenImpCasts();
+      while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
+        Base = TempASE->getBase()->IgnoreParenImpCasts();
+      RefExpr = Base;
+      IsArrayExpr = OMPArraySection;
+    }
+  }
+  ELoc = RefExpr->getExprLoc();
+  ERange = RefExpr->getSourceRange();
+  RefExpr = RefExpr->IgnoreParenImpCasts();
   auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
   auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
   if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
       (S.getCurrentThisType().isNull() || !ME ||
        !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
        !isa<FieldDecl>(ME->getMemberDecl()))) {
-    S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
-        << (S.getCurrentThisType().isNull() ? 0 : 1) << SR;
+    if (IsArrayExpr != NoArrayExpr)
+      S.Diag(ELoc, diag::err_omp_expected_base_var_name) << IsArrayExpr
+                                                         << ERange;
+    else {
+      S.Diag(ELoc,
+             AllowArraySection
+                 ? diag::err_omp_expected_var_name_member_expr_or_array_item
+                 : diag::err_omp_expected_var_name_member_expr)
+          << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
+    }
     return std::make_pair(nullptr, false);
   }
   return std::make_pair(DE ? DE->getDecl() : ME->getMemberDecl(), false);
@@ -7130,7 +7163,10 @@ OMPClause *Sema::ActOnOpenMPPrivateClaus
   SmallVector<Expr *, 8> PrivateCopies;
   for (auto &RefExpr : VarList) {
     assert(RefExpr && "NULL expr in OpenMP private clause.");
-    auto Res = getPrivateItem(*this, RefExpr);
+    SourceLocation ELoc;
+    SourceRange ERange;
+    Expr *SimpleRefExpr = RefExpr;
+    auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
     if (Res.second) {
       // It will be analyzed later.
       Vars.push_back(RefExpr);
@@ -7140,7 +7176,6 @@ OMPClause *Sema::ActOnOpenMPPrivateClaus
     if (!D)
       continue;
 
-    SourceLocation ELoc = RefExpr->getExprLoc();
     QualType Type = D->getType();
     auto *VD = dyn_cast<VarDecl>(D);
 
@@ -7201,7 +7236,7 @@ OMPClause *Sema::ActOnOpenMPPrivateClaus
 
     DeclRefExpr *Ref = nullptr;
     if (!VD)
-      Ref = buildCapture(*this, D, RefExpr);
+      Ref = buildCapture(*this, D, SimpleRefExpr);
     DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
     Vars.push_back(VD ? RefExpr->IgnoreParens() : Ref);
     PrivateCopies.push_back(VDPrivateRefExpr);
@@ -7251,7 +7286,10 @@ OMPClause *Sema::ActOnOpenMPFirstprivate
 
   for (auto &RefExpr : VarList) {
     assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
-    auto Res = getPrivateItem(*this, RefExpr);
+    SourceLocation ELoc;
+    SourceRange ERange;
+    Expr *SimpleRefExpr = RefExpr;
+    auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
     if (Res.second) {
       // It will be analyzed later.
       Vars.push_back(RefExpr);
@@ -7262,8 +7300,7 @@ OMPClause *Sema::ActOnOpenMPFirstprivate
     if (!D)
       continue;
 
-    SourceLocation ELoc =
-        IsImplicitClause ? ImplicitClauseLoc : RefExpr->getExprLoc();
+    ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
     QualType Type = D->getType();
     auto *VD = dyn_cast<VarDecl>(D);
 
@@ -7483,7 +7520,7 @@ OMPClause *Sema::ActOnOpenMPFirstprivate
       if (TopDVar.CKind == OMPC_lastprivate)
         Ref = TopDVar.PrivateCopy;
       else {
-        Ref = buildCapture(*this, D, RefExpr);
+        Ref = buildCapture(*this, D, SimpleRefExpr);
         if (!IsOpenMPCapturedDecl(D))
           ExprCaptures.push_back(Ref->getDecl());
       }
@@ -7520,7 +7557,10 @@ OMPClause *Sema::ActOnOpenMPLastprivateC
   SmallVector<Expr *, 4> ExprPostUpdates;
   for (auto &RefExpr : VarList) {
     assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
-    auto Res = getPrivateItem(*this, RefExpr);
+    SourceLocation ELoc;
+    SourceRange ERange;
+    Expr *SimpleRefExpr = RefExpr;
+    auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
     if (Res.second) {
       // It will be analyzed later.
       Vars.push_back(RefExpr);
@@ -7532,7 +7572,6 @@ OMPClause *Sema::ActOnOpenMPLastprivateC
     if (!D)
       continue;
 
-    SourceLocation ELoc = RefExpr->getExprLoc();
     QualType Type = D->getType();
     auto *VD = dyn_cast<VarDecl>(D);
 
@@ -7601,13 +7640,13 @@ OMPClause *Sema::ActOnOpenMPLastprivateC
     //  lastprivate clause requires an accessible, unambiguous copy assignment
     //  operator for the class type.
     Type = Context.getBaseElementType(Type).getNonReferenceType();
-    auto *SrcVD = buildVarDecl(*this, RefExpr->getLocStart(),
+    auto *SrcVD = buildVarDecl(*this, ERange.getBegin(),
                                Type.getUnqualifiedType(), ".lastprivate.src",
                                D->hasAttrs() ? &D->getAttrs() : nullptr);
     auto *PseudoSrcExpr =
         buildDeclRefExpr(*this, SrcVD, Type.getUnqualifiedType(), ELoc);
     auto *DstVD =
-        buildVarDecl(*this, RefExpr->getLocStart(), Type, ".lastprivate.dst",
+        buildVarDecl(*this, ERange.getBegin(), Type, ".lastprivate.dst",
                      D->hasAttrs() ? &D->getAttrs() : nullptr);
     auto *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc);
     // For arrays generate assignment operation for single element and replace
@@ -7626,7 +7665,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateC
       if (TopDVar.CKind == OMPC_firstprivate)
         Ref = TopDVar.PrivateCopy;
       else {
-        Ref = buildCapture(*this, D, RefExpr);
+        Ref = buildCapture(*this, D, SimpleRefExpr);
         if (!IsOpenMPCapturedDecl(D))
           ExprCaptures.push_back(Ref->getDecl());
       }
@@ -7637,8 +7676,8 @@ OMPClause *Sema::ActOnOpenMPLastprivateC
         if (!RefRes.isUsable())
           continue;
         ExprResult PostUpdateRes =
-            BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
-                       RefExpr->IgnoreParenLValueCasts(), RefRes.get());
+            BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
+                       RefRes.get());
         if (!PostUpdateRes.isUsable())
           continue;
         ExprPostUpdates.push_back(PostUpdateRes.get());
@@ -7684,7 +7723,10 @@ OMPClause *Sema::ActOnOpenMPSharedClause
   SmallVector<Expr *, 8> Vars;
   for (auto &RefExpr : VarList) {
     assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
-    auto Res = getPrivateItem(*this, RefExpr);
+    SourceLocation ELoc;
+    SourceRange ERange;
+    Expr *SimpleRefExpr = RefExpr;
+    auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
     if (Res.second) {
       // It will be analyzed later.
       Vars.push_back(RefExpr);
@@ -7693,7 +7735,6 @@ OMPClause *Sema::ActOnOpenMPSharedClause
     if (!D)
       continue;
 
-    SourceLocation ELoc = RefExpr->getExprLoc();
     auto *VD = dyn_cast<VarDecl>(D);
     // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
     // in a Construct]
@@ -7713,7 +7754,7 @@ OMPClause *Sema::ActOnOpenMPSharedClause
 
     DeclRefExpr *Ref = nullptr;
     if (!VD)
-      Ref = buildCapture(*this, D, RefExpr);
+      Ref = buildCapture(*this, D, SimpleRefExpr);
     DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
     Vars.push_back(VD ? RefExpr->IgnoreParens() : Ref);
   }
@@ -7755,6 +7796,30 @@ public:
 };
 } // namespace
 
+namespace {
+// Transform MemberExpression for specified FieldDecl of current class to
+// DeclRefExpr to specified OMPCapturedExprDecl.
+class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
+  typedef TreeTransform<TransformExprToCaptures> BaseTransform;
+  ValueDecl *Field;
+  DeclRefExpr *CapturedExpr;
+
+public:
+  TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
+      : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
+
+  ExprResult TransformMemberExpr(MemberExpr *E) {
+    if (isa<CXXThisExpr>(E->getBase()->IgnoreParenImpCasts()) &&
+        E->getMemberDecl() == Field) {
+      CapturedExpr = buildCapture(SemaRef, Field, E);
+      return CapturedExpr;
+    }
+    return BaseTransform::TransformMemberExpr(E);
+  }
+  DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
+};
+} // namespace
+
 OMPClause *Sema::ActOnOpenMPReductionClause(
     ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
     SourceLocation ColonLoc, SourceLocation EndLoc,
@@ -7866,85 +7931,45 @@ OMPClause *Sema::ActOnOpenMPReductionCla
   SmallVector<Expr *, 8> ReductionOps;
   for (auto RefExpr : VarList) {
     assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
-    if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
+    // OpenMP [2.1, C/C++]
+    //  A list item is a variable or array section, subject to the restrictions
+    //  specified in Section 2.4 on page 42 and in each of the sections
+    // describing clauses and directives for which a list appears.
+    // OpenMP  [2.14.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.
+    SourceLocation ELoc;
+    SourceRange ERange;
+    Expr *SimpleRefExpr = RefExpr;
+    auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
+                              /*AllowArraySection=*/true);
+    if (Res.second) {
       // It will be analyzed later.
       Vars.push_back(RefExpr);
       Privates.push_back(nullptr);
       LHSs.push_back(nullptr);
       RHSs.push_back(nullptr);
       ReductionOps.push_back(nullptr);
-      continue;
     }
-
-    if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
-        RefExpr->isInstantiationDependent() ||
-        RefExpr->containsUnexpandedParameterPack()) {
-      // It will be analyzed later.
-      Vars.push_back(RefExpr);
-      Privates.push_back(nullptr);
-      LHSs.push_back(nullptr);
-      RHSs.push_back(nullptr);
-      ReductionOps.push_back(nullptr);
+    ValueDecl *D = Res.first;
+    if (!D)
       continue;
-    }
 
-    auto ELoc = RefExpr->getExprLoc();
-    auto ERange = RefExpr->getSourceRange();
-    // OpenMP [2.1, C/C++]
-    //  A list item is a variable or array section, subject to the restrictions
-    //  specified in Section 2.4 on page 42 and in each of the sections
-    // describing clauses and directives for which a list appears.
-    // OpenMP  [2.14.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.
-    auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
-    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_member_expr_or_array_item)
-          << 0 << ERange;
-      continue;
-    }
     QualType Type;
-    VarDecl *VD = nullptr;
-    if (DE) {
-      auto D = DE->getDecl();
-      VD = cast<VarDecl>(D);
-      Type = Context.getBaseElementType(VD->getType().getNonReferenceType());
-    } else if (ASE) {
+    auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
+    auto *OASE = dyn_cast<OMPArraySectionExpr>(RefExpr->IgnoreParens());
+    if (ASE)
       Type = ASE->getType().getNonReferenceType();
-      auto *Base = ASE->getBase()->IgnoreParenImpCasts();
-      while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
-        Base = TempASE->getBase()->IgnoreParenImpCasts();
-      DE = dyn_cast<DeclRefExpr>(Base);
-      if (DE)
-        VD = dyn_cast<VarDecl>(DE->getDecl());
-      if (!VD) {
-        Diag(Base->getExprLoc(), diag::err_omp_expected_base_var_name)
-            << 0 << Base->getSourceRange();
-        continue;
-      }
-    } else if (OASE) {
+    else if (OASE) {
       auto BaseType = OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
       if (auto *ATy = BaseType->getAsArrayTypeUnsafe())
         Type = ATy->getElementType();
       else
         Type = BaseType->getPointeeType();
       Type = Type.getNonReferenceType();
-      auto *Base = OASE->getBase()->IgnoreParenImpCasts();
-      while (auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
-        Base = TempOASE->getBase()->IgnoreParenImpCasts();
-      while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
-        Base = TempASE->getBase()->IgnoreParenImpCasts();
-      DE = dyn_cast<DeclRefExpr>(Base);
-      if (DE)
-        VD = dyn_cast<VarDecl>(DE->getDecl());
-      if (!VD) {
-        Diag(Base->getExprLoc(), diag::err_omp_expected_base_var_name)
-            << 1 << Base->getSourceRange();
-        continue;
-      }
-    }
+    } else
+      Type = Context.getBaseElementType(D->getType().getNonReferenceType());
+    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
@@ -7959,18 +7984,19 @@ OMPClause *Sema::ActOnOpenMPReductionCla
       Diag(ELoc, diag::err_omp_const_reduction_list_item)
           << getOpenMPClauseName(OMPC_reduction) << Type << ERange;
       if (!ASE && !OASE) {
-        bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
-                      VarDecl::DeclarationOnly;
-        Diag(VD->getLocation(),
+        bool IsDecl = !VD ||
+                      VD->isThisDeclarationADefinition(Context) ==
+                          VarDecl::DeclarationOnly;
+        Diag(D->getLocation(),
              IsDecl ? diag::note_previous_decl : diag::note_defined_here)
-            << VD;
+            << D;
       }
       continue;
     }
     // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
     //  If a list-item is a reference type then it must bind to the same object
     //  for all threads of the team.
-    if (!ASE && !OASE) {
+    if (!ASE && !OASE && VD) {
       VarDecl *VDDef = VD->getDefinition();
       if (VD->getType()->isReferenceType() && VDDef) {
         DSARefChecker Check(DSAStack);
@@ -7995,11 +8021,12 @@ OMPClause *Sema::ActOnOpenMPReductionCla
       Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
           << getLangOpts().CPlusPlus;
       if (!ASE && !OASE) {
-        bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
-                      VarDecl::DeclarationOnly;
-        Diag(VD->getLocation(),
+        bool IsDecl = !VD ||
+                      VD->isThisDeclarationADefinition(Context) ==
+                          VarDecl::DeclarationOnly;
+        Diag(D->getLocation(),
              IsDecl ? diag::note_previous_decl : diag::note_defined_here)
-            << VD;
+            << D;
       }
       continue;
     }
@@ -8007,11 +8034,12 @@ OMPClause *Sema::ActOnOpenMPReductionCla
         !getLangOpts().CPlusPlus && Type->isFloatingType()) {
       Diag(ELoc, diag::err_omp_clause_floating_type_arg);
       if (!ASE && !OASE) {
-        bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
-                      VarDecl::DeclarationOnly;
-        Diag(VD->getLocation(),
+        bool IsDecl = !VD ||
+                      VD->isThisDeclarationADefinition(Context) ==
+                          VarDecl::DeclarationOnly;
+        Diag(D->getLocation(),
              IsDecl ? diag::note_previous_decl : diag::note_defined_here)
-            << VD;
+            << D;
       }
       continue;
     }
@@ -8027,18 +8055,17 @@ OMPClause *Sema::ActOnOpenMPReductionCla
     //  but a list item can appear only once in the reduction clauses for that
     //  directive.
     DSAStackTy::DSAVarData DVar;
-    DVar = DSAStack->getTopDSA(VD, false);
+    DVar = DSAStack->getTopDSA(D, false);
     if (DVar.CKind == OMPC_reduction) {
       Diag(ELoc, diag::err_omp_once_referenced)
           << getOpenMPClauseName(OMPC_reduction);
-      if (DVar.RefExpr) {
+      if (DVar.RefExpr)
         Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
-      }
     } else if (DVar.CKind != OMPC_unknown) {
       Diag(ELoc, diag::err_omp_wrong_dsa)
           << getOpenMPClauseName(DVar.CKind)
           << getOpenMPClauseName(OMPC_reduction);
-      ReportOriginalDSA(*this, DSAStack, VD, DVar);
+      ReportOriginalDSA(*this, DSAStack, D, DVar);
       continue;
     }
 
@@ -8049,24 +8076,25 @@ OMPClause *Sema::ActOnOpenMPReductionCla
     OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
     if (isOpenMPWorksharingDirective(CurrDir) &&
         !isOpenMPParallelDirective(CurrDir)) {
-      DVar = DSAStack->getImplicitDSA(VD, true);
+      DVar = DSAStack->getImplicitDSA(D, true);
       if (DVar.CKind != OMPC_shared) {
         Diag(ELoc, diag::err_omp_required_access)
             << getOpenMPClauseName(OMPC_reduction)
             << getOpenMPClauseName(OMPC_shared);
-        ReportOriginalDSA(*this, DSAStack, VD, DVar);
+        ReportOriginalDSA(*this, DSAStack, D, DVar);
         continue;
       }
     }
 
     Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
     auto *LHSVD = buildVarDecl(*this, ELoc, Type, ".reduction.lhs",
-                               VD->hasAttrs() ? &VD->getAttrs() : nullptr);
-    auto *RHSVD = buildVarDecl(*this, ELoc, Type, VD->getName(),
-                               VD->hasAttrs() ? &VD->getAttrs() : nullptr);
+                               D->hasAttrs() ? &D->getAttrs() : nullptr);
+    auto *RHSVD = buildVarDecl(*this, ELoc, Type, D->getName(),
+                               D->hasAttrs() ? &D->getAttrs() : nullptr);
     auto PrivateTy = Type;
     if (OASE ||
-        (DE && VD->getType().getNonReferenceType()->isVariablyModifiedType())) {
+        (!ASE &&
+         D->getType().getNonReferenceType()->isVariablyModifiedType())) {
       // For arays/array sections only:
       // Create pseudo array type for private copy. The size for this array will
       // be generated during codegen.
@@ -8076,12 +8104,12 @@ OMPClause *Sema::ActOnOpenMPReductionCla
           Type, new (Context) OpaqueValueExpr(SourceLocation(),
                                               Context.getSizeType(), VK_RValue),
           ArrayType::Normal, /*IndexTypeQuals=*/0, SourceRange());
-    } else if (DE &&
-               Context.getAsArrayType(VD->getType().getNonReferenceType()))
-      PrivateTy = VD->getType().getNonReferenceType();
+    } else if (!ASE && !OASE &&
+               Context.getAsArrayType(D->getType().getNonReferenceType()))
+      PrivateTy = D->getType().getNonReferenceType();
     // Private copy.
-    auto *PrivateVD = buildVarDecl(*this, ELoc, PrivateTy, VD->getName(),
-                                   VD->hasAttrs() ? &VD->getAttrs() : nullptr);
+    auto *PrivateVD = buildVarDecl(*this, ELoc, PrivateTy, D->getName(),
+                                   D->hasAttrs() ? &D->getAttrs() : nullptr);
     // Add initializer for private variable.
     Expr *Init = nullptr;
     switch (BOK) {
@@ -8090,9 +8118,8 @@ OMPClause *Sema::ActOnOpenMPReductionCla
     case BO_Or:
     case BO_LOr:
       // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
-      if (Type->isScalarType() || Type->isAnyComplexType()) {
+      if (Type->isScalarType() || Type->isAnyComplexType())
         Init = ActOnIntegerConstant(ELoc, /*Val=*/0).get();
-      }
       break;
     case BO_Mul:
     case BO_LAnd:
@@ -8104,9 +8131,8 @@ OMPClause *Sema::ActOnOpenMPReductionCla
     case BO_And: {
       // '&' reduction op - initializer is '~0'.
       QualType OrigType = Type;
-      if (auto *ComplexTy = OrigType->getAs<ComplexType>()) {
+      if (auto *ComplexTy = OrigType->getAs<ComplexType>())
         Type = ComplexTy->getElementType();
-      }
       if (Type->isRealFloatingType()) {
         llvm::APFloat InitValue =
             llvm::APFloat::getAllOnesValue(Context.getTypeSize(Type),
@@ -8195,13 +8221,12 @@ OMPClause *Sema::ActOnOpenMPReductionCla
     if (!RHSVD->hasInit()) {
       Diag(ELoc, diag::err_omp_reduction_id_not_compatible) << Type
                                                             << ReductionIdRange;
-      if (VD) {
-        bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
-                      VarDecl::DeclarationOnly;
-        Diag(VD->getLocation(),
-             IsDecl ? diag::note_previous_decl : diag::note_defined_here)
-            << VD;
-      }
+      bool IsDecl =
+          !VD ||
+          VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
+      Diag(D->getLocation(),
+           IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+          << D;
       continue;
     }
     // Store initializer for single element in private copy. Will be used during
@@ -8232,8 +8257,19 @@ OMPClause *Sema::ActOnOpenMPReductionCla
     if (ReductionOp.isInvalid())
       continue;
 
-    DSAStack->addDSA(VD, DE, OMPC_reduction);
-    Vars.push_back(RefExpr);
+    DeclRefExpr *Ref = nullptr;
+    Expr *VarsExpr = RefExpr->IgnoreParens();
+    if (!VD) {
+      if (ASE || OASE) {
+        TransformExprToCaptures RebuildToCapture(*this, D);
+        VarsExpr =
+            RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
+        Ref = RebuildToCapture.getCapturedExpr();
+      } else
+        VarsExpr = Ref = buildCapture(*this, D, SimpleRefExpr);
+    }
+    DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref);
+    Vars.push_back(VarsExpr);
     Privates.push_back(PrivateDRE);
     LHSs.push_back(LHSDRE);
     RHSs.push_back(RHSDRE);

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=262199&r1=262198&r2=262199&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/parallel_ast_print.cpp (original)
+++ cfe/trunk/test/OpenMP/parallel_ast_print.cpp Sun Feb 28 23:54:20 2016
@@ -13,12 +13,17 @@ struct S1 {
   S1(int v) : a(v) {}
   int a;
   typedef int type;
+  S1& operator +(const S1&);
+  S1& operator *(const S1&);
+  S1& operator &&(const S1&);
+  S1& operator ^(const S1&);
 };
 
 template <typename T>
 class S7 : public T {
 protected:
   T a;
+  T b[100];
   S7() : a(0) {}
 
 public:
@@ -32,6 +37,9 @@ public:
 #pragma omp parallel shared(a) shared(this->a) shared(T::a)
     for (int k = 0; k < a.a; ++k)
       ++this->a.a;
+#pragma omp parallel reduction(+ : a) reduction(*: b[:])
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
   }
   S7 &operator=(S7 &s) {
 #pragma omp parallel private(a) private(this->a)
@@ -43,6 +51,9 @@ public:
 #pragma omp parallel shared(a) shared(this->a)
     for (int k = 0; k < s.a.a; ++k)
       ++s.a.a;
+#pragma omp parallel reduction(&& : this->a) reduction(^: b[s.a.a])
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
     return *this;
   }
 };
@@ -50,12 +61,15 @@ public:
 // CHECK: #pragma omp parallel private(this->a) private(this->a) private(this->S1::a)
 // CHECK: #pragma omp parallel firstprivate(this->a) firstprivate(this->a) firstprivate(this->S1::a)
 // CHECK: #pragma omp parallel shared(this->a) shared(this->a) shared(this->S1::a)
+// CHECK: #pragma omp parallel reduction(+: this->a) reduction(*: this->b[:])
 // CHECK: #pragma omp parallel private(this->a) private(this->a) private(T::a)
 // CHECK: #pragma omp parallel firstprivate(this->a) firstprivate(this->a) firstprivate(T::a)
 // CHECK: #pragma omp parallel shared(this->a) shared(this->a) shared(T::a)
+// CHECK: #pragma omp parallel reduction(+: this->a) reduction(*: this->b[:])
 // CHECK: #pragma omp parallel private(this->a) private(this->a)
 // CHECK: #pragma omp parallel firstprivate(this->a) firstprivate(this->a)
 // CHECK: #pragma omp parallel shared(this->a) shared(this->a)
+// CHECK: #pragma omp parallel reduction(&&: this->a) reduction(^: this->b[s.a.a])
 
 class S8 : public S7<S1> {
   S8() {}
@@ -71,6 +85,9 @@ public:
 #pragma omp parallel shared(a) shared(this->a) shared(S7 < S1 > ::a)
     for (int k = 0; k < a.a; ++k)
       ++this->a.a;
+#pragma omp parallel reduction(^ : S7 < S1 > ::a) reduction(+ : S7 < S1 > ::b[ : S7 < S1 > ::a.a])
+    for (int k = 0; k < a.a; ++k)
+      ++this->a.a;
   }
   S8 &operator=(S8 &s) {
 #pragma omp parallel private(a) private(this->a)
@@ -82,6 +99,9 @@ public:
 #pragma omp parallel shared(a) shared(this->a)
     for (int k = 0; k < s.a.a; ++k)
       ++s.a.a;
+#pragma omp parallel reduction(* : this->a) reduction(&&:this->b[a.a:])
+    for (int k = 0; k < s.a.a; ++k)
+      ++s.a.a;
     return *this;
   }
 };
@@ -89,9 +109,11 @@ public:
 // CHECK: #pragma omp parallel private(this->a) private(this->a) private(this->S7<S1>::a)
 // CHECK: #pragma omp parallel firstprivate(this->a) firstprivate(this->a) firstprivate(this->S7<S1>::a)
 // CHECK: #pragma omp parallel shared(this->a) shared(this->a) shared(this->S7<S1>::a)
+// CHECK: #pragma omp parallel reduction(^: this->S7<S1>::a) reduction(+: this->S7<S1>::b[:this->S7<S1>::a.a])
 // CHECK: #pragma omp parallel private(this->a) private(this->a)
 // CHECK: #pragma omp parallel firstprivate(this->a) firstprivate(this->a)
 // CHECK: #pragma omp parallel shared(this->a) shared(this->a)
+// CHECK: #pragma omp parallel reduction(*: this->a) reduction(&&: this->b[this->a.a:])
 
 template <class T>
 struct S {




More information about the cfe-commits mailing list