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