diff options
author | Alexey Bataev <a.bataev@hotmail.com> | 2016-02-20 04:09:36 +0000 |
---|---|---|
committer | Alexey Bataev <a.bataev@hotmail.com> | 2016-02-20 04:09:36 +0000 |
commit | 74caaf27d8ea8f82f6020d51a2df7d92a3b558e7 (patch) | |
tree | 7238ff4c00afb051a9f5cd9a9755ee5e0e5e6a99 /clang/lib/Sema | |
parent | c1dc384b54ef69044244b791df8367bf583fb58f (diff) | |
download | bcm5719-llvm-74caaf27d8ea8f82f6020d51a2df7d92a3b558e7.tar.gz bcm5719-llvm-74caaf27d8ea8f82f6020d51a2df7d92a3b558e7.zip |
[OPENMP 4.5] Initial support for data members in 'lastprivate' clause.
OpenMP 4.5 allows to privatize non-static data members of current class
in non-static member functions. Patch adds initial support for data
members.
llvm-svn: 261412
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 107 |
1 files changed, 46 insertions, 61 deletions
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 7f000dc0bd0..31943fa676f 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -990,17 +990,18 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) { PrivateCopies.push_back(nullptr); continue; } - DE = DE->IgnoreParens(); VarDecl *VD = nullptr; FieldDecl *FD = nullptr; ValueDecl *D; - if (auto *DRE = dyn_cast<DeclRefExpr>(DE)) { + auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens()); + if (auto *OCE = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl())) { + FD = cast<FieldDecl>( + cast<MemberExpr>(OCE->getInit()->IgnoreImpCasts()) + ->getMemberDecl()); + D = FD; + } else { VD = cast<VarDecl>(DRE->getDecl()); D = VD; - } else { - assert(isa<MemberExpr>(DE)); - FD = cast<FieldDecl>(cast<MemberExpr>(DE)->getMemberDecl()); - D = FD; } QualType Type = D->getType().getNonReferenceType(); auto DVar = DSAStack->getTopDSA(D, false); @@ -7514,47 +7515,28 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, SmallVector<Expr *, 8> AssignmentOps; for (auto &RefExpr : VarList) { assert(RefExpr && "NULL expr in OpenMP lastprivate clause."); - if (isa<DependentScopeDeclRefExpr>(RefExpr)) { + auto Res = getPrivateItem(*this, RefExpr); + if (Res.second) { // It will be analyzed later. Vars.push_back(RefExpr); SrcExprs.push_back(nullptr); DstExprs.push_back(nullptr); AssignmentOps.push_back(nullptr); - continue; } - - SourceLocation ELoc = RefExpr->getExprLoc(); - // OpenMP [2.1, C/C++] - // A list item is a variable name. - // OpenMP [2.14.3.5, Restrictions, p.1] - // A variable that is part of another variable (as an array or structure - // element) cannot appear in a lastprivate clause. - DeclRefExpr *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr); - if (!DE || !isa<VarDecl>(DE->getDecl())) { - Diag(ELoc, diag::err_omp_expected_var_name_member_expr) - << 0 << RefExpr->getSourceRange(); + ValueDecl *D = Res.first; + if (!D) continue; - } - Decl *D = DE->getDecl(); - VarDecl *VD = cast<VarDecl>(D); - QualType Type = VD->getType(); - if (Type->isDependentType() || Type->isInstantiationDependentType()) { - // It will be analyzed later. - Vars.push_back(DE); - SrcExprs.push_back(nullptr); - DstExprs.push_back(nullptr); - AssignmentOps.push_back(nullptr); - continue; - } + SourceLocation ELoc = RefExpr->getExprLoc(); + QualType Type = D->getType(); + auto *VD = dyn_cast<VarDecl>(D); // OpenMP [2.14.3.5, Restrictions, C/C++, p.2] // A variable that appears in a lastprivate clause must not have an // incomplete type or a reference type. if (RequireCompleteType(ELoc, Type, - diag::err_omp_lastprivate_incomplete_type)) { + diag::err_omp_lastprivate_incomplete_type)) continue; - } Type = Type.getNonReferenceType(); // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced @@ -7562,14 +7544,14 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, // Variables with the predetermined data-sharing attributes may not be // listed in data-sharing attributes clauses, except for the cases // listed below. - DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false); + DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, false); if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_firstprivate && (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) { Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind) << getOpenMPClauseName(OMPC_lastprivate); - ReportOriginalDSA(*this, DSAStack, VD, DVar); + ReportOriginalDSA(*this, DSAStack, D, DVar); continue; } @@ -7583,15 +7565,28 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, DSAStackTy::DSAVarData TopDVar = DVar; 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_lastprivate) << getOpenMPClauseName(OMPC_shared); - ReportOriginalDSA(*this, DSAStack, VD, DVar); + ReportOriginalDSA(*this, DSAStack, D, DVar); + continue; + } + } + + // OpenMP 4.5 [2.10.8, Distribute Construct, p.3] + // A list item may appear in a firstprivate or lastprivate clause but not + // both. + if (CurrDir == OMPD_distribute) { + DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, false); + if (DVar.CKind == OMPC_firstprivate) { + Diag(ELoc, diag::err_omp_firstprivate_and_lastprivate_in_distribute); + ReportOriginalDSA(*this, DSAStack, D, DVar); continue; } } + // OpenMP [2.14.3.5, Restrictions, C++, p.1,2] // A variable of class type (or array thereof) that appears in a // lastprivate clause requires an accessible, unambiguous default @@ -7601,42 +7596,32 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, // lastprivate clause requires an accessible, unambiguous copy assignment // operator for the class type. Type = Context.getBaseElementType(Type).getNonReferenceType(); - auto *SrcVD = buildVarDecl(*this, DE->getLocStart(), + auto *SrcVD = buildVarDecl(*this, RefExpr->getLocStart(), Type.getUnqualifiedType(), ".lastprivate.src", - VD->hasAttrs() ? &VD->getAttrs() : nullptr); - auto *PseudoSrcExpr = buildDeclRefExpr( - *this, SrcVD, Type.getUnqualifiedType(), DE->getExprLoc()); + D->hasAttrs() ? &D->getAttrs() : nullptr); + auto *PseudoSrcExpr = + buildDeclRefExpr(*this, SrcVD, Type.getUnqualifiedType(), ELoc); auto *DstVD = - buildVarDecl(*this, DE->getLocStart(), Type, ".lastprivate.dst", - VD->hasAttrs() ? &VD->getAttrs() : nullptr); - auto *PseudoDstExpr = - buildDeclRefExpr(*this, DstVD, Type, DE->getExprLoc()); + buildVarDecl(*this, RefExpr->getLocStart(), 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 // it by the original array element in CodeGen. - auto AssignmentOp = BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign, + auto AssignmentOp = BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr); if (AssignmentOp.isInvalid()) continue; - AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(), + AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue=*/true); if (AssignmentOp.isInvalid()) continue; - // OpenMP 4.5 [2.10.8, Distribute Construct, p.3] - // A list item may appear in a firstprivate or lastprivate clause but not - // both. - if (CurrDir == OMPD_distribute) { - DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false); - if (DVar.CKind == OMPC_firstprivate) { - Diag(ELoc, diag::err_omp_firstprivate_and_lastprivate_in_distribute); - ReportOriginalDSA(*this, DSAStack, VD, DVar); - continue; - } - } - + DeclRefExpr *Ref = nullptr; + if (!VD) + Ref = buildCapture(*this, D->getIdentifier(), RefExpr); if (TopDVar.CKind != OMPC_firstprivate) - DSAStack->addDSA(VD, DE, OMPC_lastprivate); - Vars.push_back(DE); + DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref); + Vars.push_back(VD ? RefExpr->IgnoreParens() : Ref); SrcExprs.push_back(PseudoSrcExpr); DstExprs.push_back(PseudoDstExpr); AssignmentOps.push_back(AssignmentOp.get()); |