diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/Stmt.cpp | 38 | ||||
-rw-r--r-- | clang/lib/AST/StmtProfile.cpp | 9 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGOpenMPRuntime.cpp | 143 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGOpenMPRuntime.h | 10 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGStmtOpenMP.cpp | 31 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 60 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderStmt.cpp | 20 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterStmt.cpp | 6 |
9 files changed, 278 insertions, 44 deletions
diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index 5ea75ea4655..8c760095241 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -1388,17 +1388,41 @@ OMPCopyinClause *OMPCopyinClause::CreateEmpty(const ASTContext &C, return new (Mem) OMPCopyinClause(N); } -OMPCopyprivateClause *OMPCopyprivateClause::Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc, - ArrayRef<Expr *> VL) { +void OMPCopyprivateClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) { + assert(SrcExprs.size() == varlist_size() && "Number of source expressions is " + "not the same as the " + "preallocated buffer"); + std::copy(SrcExprs.begin(), SrcExprs.end(), varlist_end()); +} + +void OMPCopyprivateClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) { + assert(DstExprs.size() == varlist_size() && "Number of destination " + "expressions is not the same as " + "the preallocated buffer"); + std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end()); +} + +void OMPCopyprivateClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) { + assert(AssignmentOps.size() == varlist_size() && + "Number of assignment expressions is not the same as the preallocated " + "buffer"); + std::copy(AssignmentOps.begin(), AssignmentOps.end(), + getDestinationExprs().end()); +} + +OMPCopyprivateClause *OMPCopyprivateClause::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs, + ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) { void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyprivateClause), llvm::alignOf<Expr *>()) + - sizeof(Expr *) * VL.size()); + 4 * sizeof(Expr *) * VL.size()); OMPCopyprivateClause *Clause = new (Mem) OMPCopyprivateClause(StartLoc, LParenLoc, EndLoc, VL.size()); Clause->setVarRefs(VL); + Clause->setSourceExprs(SrcExprs); + Clause->setDestinationExprs(DstExprs); + Clause->setAssignmentOps(AssignmentOps); return Clause; } @@ -1406,7 +1430,7 @@ OMPCopyprivateClause *OMPCopyprivateClause::CreateEmpty(const ASTContext &C, unsigned N) { void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyprivateClause), llvm::alignOf<Expr *>()) + - sizeof(Expr *) * N); + 4 * sizeof(Expr *) * N); return new (Mem) OMPCopyprivateClause(N); } diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 900ff3abe3a..f29f6a838dc 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -381,6 +381,15 @@ void OMPClauseProfiler::VisitOMPCopyinClause(const OMPCopyinClause *C) { void OMPClauseProfiler::VisitOMPCopyprivateClause(const OMPCopyprivateClause *C) { VisitOMPClauseList(C); + for (auto *E : C->source_exprs()) { + Profiler->VisitStmt(E); + } + for (auto *E : C->destination_exprs()) { + Profiler->VisitStmt(E); + } + for (auto *E : C->assignment_ops()) { + Profiler->VisitStmt(E); + } } void OMPClauseProfiler::VisitOMPFlushClause(const OMPFlushClause *C) { VisitOMPClauseList(C); diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 25755838013..ef2d2147aca 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -580,6 +580,21 @@ CGOpenMPRuntime::createRuntimeFunction(OpenMPRTLFunction Function) { RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task"); break; } + case OMPRTL__kmpc_copyprivate: { + // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, + // kmp_int32 cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), + // kmp_int32 didit); + llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; + auto *CpyFnTy = + llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false); + llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, + CGM.VoidPtrTy, CpyFnTy->getPointerTo(), + CGM.Int32Ty}; + llvm::FunctionType *FnTy = + llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); + RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate"); + break; + } } return RTLFn; } @@ -965,19 +980,107 @@ void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args); } +static llvm::Value *emitCopyprivateCopyFunction( + CodeGenModule &CGM, llvm::Type *ArgsType, ArrayRef<const Expr *> SrcExprs, + ArrayRef<const Expr *> DstExprs, ArrayRef<const Expr *> AssignmentOps) { + auto &C = CGM.getContext(); + // void copy_func(void *LHSArg, void *RHSArg); + FunctionArgList Args; + ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr, + C.VoidPtrTy); + ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr, + C.VoidPtrTy); + Args.push_back(&LHSArg); + Args.push_back(&RHSArg); + FunctionType::ExtInfo EI; + auto &CGFI = CGM.getTypes().arrangeFreeFunctionDeclaration( + C.VoidTy, Args, EI, /*isVariadic=*/false); + auto *Fn = llvm::Function::Create( + CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage, + ".omp.copyprivate.copy_func", &CGM.getModule()); + CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, CGFI, Fn); + CodeGenFunction CGF(CGM); + CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args); + // Dst = (void*[n])(LHSArg); + // Src = (void*[n])(RHSArg); + auto *LHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( + CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&LHSArg), + CGF.PointerAlignInBytes), + ArgsType); + auto *RHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( + CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&RHSArg), + CGF.PointerAlignInBytes), + ArgsType); + // *(Type0*)Dst[0] = *(Type0*)Src[0]; + // *(Type1*)Dst[1] = *(Type1*)Src[1]; + // ... + // *(Typen*)Dst[n] = *(Typen*)Src[n]; + CodeGenFunction::OMPPrivateScope Scope(CGF); + for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { + Scope.addPrivate( + cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()), + [&]() -> llvm::Value *{ + return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( + CGF.Builder.CreateAlignedLoad(CGF.Builder.CreateStructGEP(RHS, I), + CGM.PointerAlignInBytes), + CGF.ConvertTypeForMem(C.getPointerType(SrcExprs[I]->getType()))); + }); + Scope.addPrivate( + cast<VarDecl>(cast<DeclRefExpr>(DstExprs[I])->getDecl()), + [&]() -> llvm::Value *{ + return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( + CGF.Builder.CreateAlignedLoad(CGF.Builder.CreateStructGEP(LHS, I), + CGM.PointerAlignInBytes), + CGF.ConvertTypeForMem(C.getPointerType(SrcExprs[I]->getType()))); + }); + } + Scope.Privatize(); + for (auto *E : AssignmentOps) { + CGF.EmitIgnoredExpr(E); + } + Scope.ForceCleanup(); + CGF.FinishFunction(); + return Fn; +} + void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, const std::function<void()> &SingleOpGen, - SourceLocation Loc) { + SourceLocation Loc, + ArrayRef<const Expr *> CopyprivateVars, + ArrayRef<const Expr *> SrcExprs, + ArrayRef<const Expr *> DstExprs, + ArrayRef<const Expr *> AssignmentOps) { + assert(CopyprivateVars.size() == SrcExprs.size() && + CopyprivateVars.size() == DstExprs.size() && + CopyprivateVars.size() == AssignmentOps.size()); + auto &C = CGM.getContext(); + // int32 did_it = 0; // if(__kmpc_single(ident_t *, gtid)) { // SingleOpGen(); // __kmpc_end_single(ident_t *, gtid); + // did_it = 1; // } + // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, + // <copy_func>, did_it); + + llvm::AllocaInst *DidIt = nullptr; + if (!CopyprivateVars.empty()) { + // int32 did_it = 0; + auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); + DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); + CGF.InitTempAlloca(DidIt, CGF.Builder.getInt32(0)); + } // Prepare arguments and build a call to __kmpc_single llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; auto *IsSingle = CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_single), Args); emitIfStmt(CGF, IsSingle, [&]() -> void { SingleOpGen(); + if (DidIt) { + // did_it = 1; + CGF.Builder.CreateAlignedStore(CGF.Builder.getInt32(1), DidIt, + DidIt->getAlignment()); + } // Build a call to __kmpc_end_single. // OpenMP [1.2.2 OpenMP Language Terminology] // For C/C++, an executable statement, possibly compound, with a single @@ -994,6 +1097,44 @@ void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, // fallthrough rather than pushing a normal cleanup for it. CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_end_single), Args); }); + // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, + // <copy_func>, did_it); + if (DidIt) { + llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); + auto CopyprivateArrayTy = + C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal, + /*IndexTypeQuals=*/0); + // Create a list of all private variables for copyprivate. + auto *CopyprivateList = + CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); + for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { + auto *Elem = CGF.Builder.CreateStructGEP(CopyprivateList, I); + CGF.Builder.CreateAlignedStore( + CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( + CGF.EmitLValue(CopyprivateVars[I]).getAddress(), CGF.VoidPtrTy), + Elem, CGM.PointerAlignInBytes); + } + // Build function that copies private values from single region to all other + // threads in the corresponding parallel region. + auto *CpyFn = emitCopyprivateCopyFunction( + CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), + SrcExprs, DstExprs, AssignmentOps); + auto *BufSize = CGF.Builder.getInt32( + C.getTypeSizeInChars(CopyprivateArrayTy).getQuantity()); + auto *CL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList, + CGF.VoidPtrTy); + auto *DidItVal = + CGF.Builder.CreateAlignedLoad(DidIt, CGF.PointerAlignInBytes); + llvm::Value *Args[] = { + emitUpdateLocation(CGF, Loc), // ident_t *<loc> + getThreadID(CGF, Loc), // i32 <gtid> + BufSize, // i32 <buf_size> + CL, // void *<copyprivate list> + CpyFn, // void (*) (void *, void *) <copy_func> + DidItVal // i32 did_it + }; + CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args); + } } void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h index a3f957045d7..f8849e627c8 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.h +++ b/clang/lib/CodeGen/CGOpenMPRuntime.h @@ -96,6 +96,10 @@ class CGOpenMPRuntime { // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t * // new_task); OMPRTL__kmpc_omp_task, + // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, + // kmp_int32 cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), + // kmp_int32 didit); + OMPRTL__kmpc_copyprivate, }; /// \brief Values for bit flags used in the ident_t to describe the fields. @@ -348,7 +352,11 @@ public: /// single region. virtual void emitSingleRegion(CodeGenFunction &CGF, const std::function<void()> &SingleOpGen, - SourceLocation Loc); + SourceLocation Loc, + ArrayRef<const Expr *> CopyprivateVars, + ArrayRef<const Expr *> SrcExprs, + ArrayRef<const Expr *> DstExprs, + ArrayRef<const Expr *> AssignmentOps); /// \brief Emits explicit barrier for OpenMP threads. /// \param IsExplicit true, if it is explicitly specified barrier. diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 42e6a841cdf..9af74749f17 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -882,7 +882,7 @@ void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) { InlinedOpenMPRegionScopeRAII Region(*this, S); EmitStmt(Stmt); EnsureInsertPoint(); - }, S.getLocStart()); + }, S.getLocStart(), llvm::None, llvm::None, llvm::None, llvm::None); } // Emit an implicit barrier at the end. @@ -898,11 +898,38 @@ void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &S) { } void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) { + llvm::SmallVector<const Expr *, 8> CopyprivateVars; + llvm::SmallVector<const Expr *, 8> SrcExprs; + llvm::SmallVector<const Expr *, 8> DstExprs; + llvm::SmallVector<const Expr *, 8> AssignmentOps; + // Check if there are any 'copyprivate' clauses associated with this 'single' + // construct. + auto CopyprivateFilter = [](const OMPClause *C) -> bool { + return C->getClauseKind() == OMPC_copyprivate; + }; + // Build a list of copyprivate variables along with helper expressions + // (<source>, <destination>, <destination>=<source> expressions) + typedef OMPExecutableDirective::filtered_clause_iterator<decltype( + CopyprivateFilter)> CopyprivateIter; + for (CopyprivateIter I(S.clauses(), CopyprivateFilter); I; ++I) { + auto *C = cast<OMPCopyprivateClause>(*I); + CopyprivateVars.append(C->varlists().begin(), C->varlists().end()); + SrcExprs.append(C->source_exprs().begin(), C->source_exprs().end()); + DstExprs.append(C->destination_exprs().begin(), + C->destination_exprs().end()); + AssignmentOps.append(C->assignment_ops().begin(), + C->assignment_ops().end()); + } + // Emit code for 'single' region along with 'copyprivate' clauses CGM.getOpenMPRuntime().emitSingleRegion(*this, [&]() -> void { InlinedOpenMPRegionScopeRAII Region(*this, S); EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); EnsureInsertPoint(); - }, S.getLocStart()); + }, S.getLocStart(), CopyprivateVars, SrcExprs, DstExprs, AssignmentOps); + // Emit an implicit barrier at the end. + if (!S.getSingleClause(OMPC_nowait)) + CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), + /*IsExplicit=*/false); } void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) { diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 474668abf89..151eb7e48d9 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -604,7 +604,10 @@ public: } /// \brief Exit scope - all the mapped variables are restored. - ~OMPPrivateScope() { ForceCleanup(); } + ~OMPPrivateScope() { + if (PerformCleanup) + ForceCleanup(); + } }; /// \brief Takes the old cleanup stack size and emits the cleanup blocks diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 81d04a8c2f6..e027e5555d6 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -5614,11 +5614,17 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList, SourceLocation LParenLoc, SourceLocation EndLoc) { SmallVector<Expr *, 8> Vars; + SmallVector<Expr *, 8> SrcExprs; + SmallVector<Expr *, 8> DstExprs; + SmallVector<Expr *, 8> AssignmentOps; for (auto &RefExpr : VarList) { assert(RefExpr && "NULL expr in OpenMP copyprivate clause."); if (isa<DependentScopeDeclRefExpr>(RefExpr)) { // It will be analyzed later. Vars.push_back(RefExpr); + SrcExprs.push_back(nullptr); + DstExprs.push_back(nullptr); + AssignmentOps.push_back(nullptr); continue; } @@ -5640,6 +5646,9 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList, 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; } @@ -5648,8 +5657,8 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList, // private or firstprivate clause on the single construct. if (!DSAStack->isThreadPrivate(VD)) { auto DVar = DSAStack->getTopDSA(VD, false); - if (DVar.CKind != OMPC_copyprivate && DVar.CKind != OMPC_unknown && - !(DVar.CKind == OMPC_private && !DVar.RefExpr)) { + if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate && + DVar.RefExpr) { Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind) << getOpenMPClauseName(OMPC_copyprivate); @@ -5676,41 +5685,36 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList, // A variable of class type (or array thereof) that appears in a // copyin clause requires an accessible, unambiguous copy assignment // operator for the class type. - Type = Context.getBaseElementType(Type); - CXXRecordDecl *RD = - getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr; - // FIXME This code must be replaced by actual assignment of the - // threadprivate variable. - if (RD) { - CXXMethodDecl *MD = LookupCopyingAssignment(RD, 0, false, 0); - DeclAccessPair FoundDecl = DeclAccessPair::make(MD, MD->getAccess()); - if (MD) { - if (CheckMemberAccess(ELoc, RD, FoundDecl) == AR_inaccessible || - MD->isDeleted()) { - Diag(ELoc, diag::err_omp_required_method) - << getOpenMPClauseName(OMPC_copyprivate) << 2; - bool IsDecl = VD->isThisDeclarationADefinition(Context) == - VarDecl::DeclarationOnly; - Diag(VD->getLocation(), - IsDecl ? diag::note_previous_decl : diag::note_defined_here) - << VD; - Diag(RD->getLocation(), diag::note_previous_decl) << RD; - continue; - } - MarkFunctionReferenced(ELoc, MD); - DiagnoseUseOfDecl(MD, ELoc); - } - } + auto *SrcVD = BuildVarDecl(*this, DE->getLocStart(), VD->getType(), + ".copyprivate.src"); + auto *PseudoSrcExpr = BuildDeclRefExpr(SrcVD, DE->getType(), VK_LValue, + DE->getExprLoc()).get(); + auto *DstVD = BuildVarDecl(*this, DE->getLocStart(), VD->getType(), + ".copyprivate.dst"); + auto *PseudoDstExpr = BuildDeclRefExpr(DstVD, DE->getType(), VK_LValue, + DE->getExprLoc()).get(); + auto AssignmentOp = BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign, + PseudoDstExpr, PseudoSrcExpr); + if (AssignmentOp.isInvalid()) + continue; + AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(), + /*DiscardedValue=*/true); + if (AssignmentOp.isInvalid()) + continue; // No need to mark vars as copyprivate, they are already threadprivate or // implicitly private. Vars.push_back(DE); + SrcExprs.push_back(PseudoSrcExpr); + DstExprs.push_back(PseudoDstExpr); + AssignmentOps.push_back(AssignmentOp.get()); } if (Vars.empty()) return nullptr; - return OMPCopyprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars); + return OMPCopyprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, + Vars, SrcExprs, DstExprs, AssignmentOps); } OMPClause *Sema::ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList, diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index eec0fe43b28..216764f19eb 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1969,11 +1969,23 @@ void OMPClauseReader::VisitOMPCopyinClause(OMPCopyinClause *C) { void OMPClauseReader::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) { C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); unsigned NumVars = C->varlist_size(); - SmallVector<Expr *, 16> Vars; - Vars.reserve(NumVars); + SmallVector<Expr *, 16> Exprs; + Exprs.reserve(NumVars); for (unsigned i = 0; i != NumVars; ++i) - Vars.push_back(Reader->Reader.ReadSubExpr()); - C->setVarRefs(Vars); + Exprs.push_back(Reader->Reader.ReadSubExpr()); + C->setVarRefs(Exprs); + Exprs.clear(); + for (unsigned i = 0; i != NumVars; ++i) + Exprs.push_back(Reader->Reader.ReadSubExpr()); + C->setSourceExprs(Exprs); + Exprs.clear(); + for (unsigned i = 0; i != NumVars; ++i) + Exprs.push_back(Reader->Reader.ReadSubExpr()); + C->setDestinationExprs(Exprs); + Exprs.clear(); + for (unsigned i = 0; i != NumVars; ++i) + Exprs.push_back(Reader->Reader.ReadSubExpr()); + C->setAssignmentOps(Exprs); } void OMPClauseReader::VisitOMPFlushClause(OMPFlushClause *C) { diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 3f568a6365c..cf0314a4b1b 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1857,6 +1857,12 @@ void OMPClauseWriter::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) { Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); for (auto *VE : C->varlists()) Writer->Writer.AddStmt(VE); + for (auto *E : C->source_exprs()) + Writer->Writer.AddStmt(E); + for (auto *E : C->destination_exprs()) + Writer->Writer.AddStmt(E); + for (auto *E : C->assignment_ops()) + Writer->Writer.AddStmt(E); } void OMPClauseWriter::VisitOMPFlushClause(OMPFlushClause *C) { |