jyu2 created this revision. jyu2 added reviewers: ABataev, jdoerfert, mikerice. jyu2 added projects: OpenMP, clang. Herald added a project: All. jyu2 requested review of this revision. Herald added a subscriber: sstefan1.
This is to fix assert when field is referenced and default clause is used. The problem of assert is the capture is not generated for the field. This patch is to generate capture when the field is used with implicit default, use it in the code, and save the capture off to make sure it is considered from that point and add first/private clauses. 1>Add new sema function isOpenMPFDCaptureDecl, the isOpenMPCaptureDecl is called before return. The capture reference is generated and saved in DSA. It is called in BuildFieldReferenceExpr. 2>Add new function insertDSA to save newly generated Capture info for FD. 3>Add addition argument in hasDSA to check default attribute for default(first|private). 4>Add new field ImplicitFD in DSAVarData used in VisitDeclRefExpr and when building the clause. 5>Change isOpenMPPrivateDecl where stop propagate the capture from the enclosing region for private variable. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D127803 Files: clang/include/clang/Sema/Sema.h clang/lib/Sema/SemaExprMember.cpp clang/lib/Sema/SemaOpenMP.cpp clang/lib/Sema/TreeTransform.h clang/test/OpenMP/default_firstprivate_ast_print.cpp clang/test/OpenMP/default_private_ast_print.cpp
Index: clang/test/OpenMP/default_private_ast_print.cpp =================================================================== --- clang/test/OpenMP/default_private_ast_print.cpp +++ clang/test/OpenMP/default_private_ast_print.cpp @@ -96,4 +96,50 @@ // DUMP-NEXT: -DeclRefExpr {{.*}} 'a' // DUMP-NEXT: -DeclRefExpr {{.*}} 'yy' } + +void zoo(int); +struct A { + int z; + int f; + A(); ~A(); + void foo() { + #pragma omp parallel private(z) default(private) + { + z++; f++; zoo(z+f); f++; + } + } +// PRINT: #pragma omp parallel private(this->z) default(private) +// DUMP: -OMPParallelDirective +// DUMP-NEXT: -OMPPrivateClause +// DUMP-NEXT: -DeclRefExpr {{.*}} 'z' +// DUMP-NEXT: -OMPDefaultClause +// DUMP-NEXT: -OMPPrivateClause +// DUMP-NEXT: -DeclRefExpr {{.*}} 'f' +// DUMP: -CXXThisExpr {{.*}} 'A *' implicit this + void bar() { + #pragma omp parallel private(z) default(private) + { + #pragma omp parallel private(z) default(private) + { + z++; f++; zoo(z+f); f++; + } + } + } +// PRINT: #pragma omp parallel private(this->z) default(private) +// PRINT: #pragma omp parallel private(this->z) default(private) +// DUMP: -OMPParallelDirective +// DUMP-NEXT: -OMPPrivateClause +// DUMP-NEXT: -DeclRefExpr {{.*}} 'z' +// DUMP-NEXT: -OMPDefaultClause +// DUMP: -OMPParallelDirective +// DUMP-NEXT: -OMPPrivateClause +// DUMP-NEXT: -DeclRefExpr {{.*}} 'z' +// DUMP-NEXT: -OMPDefaultClause +// DUMP-NEXT: -OMPPrivateClause {{.*}} <implicit> +// DUMP-NEXT: -DeclRefExpr {{.*}} 'f' +// DUMP: -CXXThisExpr +// DUMP: -MemberExpr +// DUMP-NEXT: -CXXThisExpr +// DUMP: -CXXThisExpr +}; #endif // HEADER Index: clang/test/OpenMP/default_firstprivate_ast_print.cpp =================================================================== --- clang/test/OpenMP/default_firstprivate_ast_print.cpp +++ clang/test/OpenMP/default_firstprivate_ast_print.cpp @@ -99,4 +99,53 @@ // DUMP-NEXT: -DeclRefExpr {{.*}} 'yy' // DUMP-NEXT: -DeclRefExpr {{.*}} 'y' } +void zoo(int); +struct A { + int z; + int f; + A(); ~A(); + void foo() { + #pragma omp parallel firstprivate(z) default(firstprivate) + { + z++; f++; zoo(z+f); f++; + } + } + // PRINT: #pragma omp parallel firstprivate(this->z) default(firstprivate) + // DUMP: -OMPParallelDirective + // DUMP-NEXT: -OMPFirstprivateClause + // DUMP-NEXT: -DeclRefExpr {{.*}} 'z' + // DUMP-NEXT: -OMPDefaultClause + // DUMP-NEXT: -OMPFirstprivateClause {{.*}} <implicit> + // DUMP-NEXT: -DeclRefExpr {{.*}} 'f' + // DUMP: -CXXThisExpr {{.*}} 'A *' implicit this + // DUMP-NEXT: -DeclRefExpr {{.*}} 'z' + // DUMP-NEXT: -DeclRefExpr {{.*}} 'f' + void bar() { + #pragma omp parallel firstprivate(z) default(firstprivate) + { + #pragma omp parallel private(z) default(firstprivate) + { + z++; f++; zoo(z+f); f++; + } + } + } + // PRINT: #pragma omp parallel firstprivate(this->z) default(firstprivate) + // PRINT: #pragma omp parallel private(this->z) default(firstprivate) + // DUMP: -OMPParallelDirective + // DUMP-NEXT: -OMPFirstprivateClause + // DUMP-NEXT: -DeclRefExpr {{.*}} 'z' + // DUMP-NEXT: -OMPDefaultClause + // DUMP: -OMPParallelDirective + // DUMP-NEXT: -OMPPrivateClaus + // DUMP-NEXT: -DeclRefExpr {{.*}} 'z' + // DUMP-NEXT: -OMPDefaultClause + // DUMP-NEXT: -OMPFirstprivateClause {{.*}} <implicit> + // DUMP-NEXT: -DeclRefExpr {{.*}} 'f' + // DUMP: -CXXThisExpr {{.*}} 'A *' implicit this + // DUMP-NEXT: -DeclRefExpr {{.*}} 'f' + // DUMP: -MemberExpr {{.*}} + // DUMP-NEXT: -CXXThisExpr + // DUMP: -CXXThisExpr {{.*}} 'A *' implicit this + // DUMP-NEXT: -DeclRefExpr {{.*}} 'z' +}; #endif // HEADER Index: clang/lib/Sema/TreeTransform.h =================================================================== --- clang/lib/Sema/TreeTransform.h +++ clang/lib/Sema/TreeTransform.h @@ -11057,7 +11057,7 @@ return ExprError(); } - if (!getDerived().AlwaysRebuild() && + if (!getDerived().AlwaysRebuild() && !getSema().getLangOpts().OpenMP && Base.get() == E->getBase() && QualifierLoc == E->getQualifierLoc() && Member == E->getMemberDecl() && Index: clang/lib/Sema/SemaOpenMP.cpp =================================================================== --- clang/lib/Sema/SemaOpenMP.cpp +++ clang/lib/Sema/SemaOpenMP.cpp @@ -75,14 +75,15 @@ DeclRefExpr *PrivateCopy = nullptr; SourceLocation ImplicitDSALoc; bool AppliedToPointee = false; + bool ImplicitFD = false; DSAVarData() = default; DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, const Expr *RefExpr, DeclRefExpr *PrivateCopy, SourceLocation ImplicitDSALoc, unsigned Modifier, - bool AppliedToPointee) + bool AppliedToPointee, bool ImplicitFD) : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr), PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc), - AppliedToPointee(AppliedToPointee) {} + AppliedToPointee(AppliedToPointee), ImplicitFD(ImplicitFD) {} }; using OperatorOffsetTy = llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>; @@ -109,6 +110,7 @@ /// true if the attribute is applied to the pointee, not the variable /// itself. bool AppliedToPointee = false; + bool ImplicitFD = false; }; using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>; using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>; @@ -526,6 +528,14 @@ DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0, bool AppliedToPointee = false); + void insertDSA(ValueDecl *D, Expr *E, DeclRefExpr *PrivateCopy, + OpenMPClauseKind A, + const llvm::function_ref<bool(OpenMPClauseKind, bool, + DefaultDataSharingAttributes)> + CPred, + const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred, + bool FromParent); + /// Adds additional information for the reduction items with the reduction id /// represented as an operator. void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR, @@ -577,7 +587,9 @@ /// predicate. const DSAVarData hasDSA(ValueDecl *D, - const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred, + const llvm::function_ref<bool(OpenMPClauseKind, bool, + DefaultDataSharingAttributes)> + CPred, const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred, bool FromParent) const; /// Checks if the specified variables has data-sharing attributes which @@ -1224,6 +1236,7 @@ DVar.ImplicitDSALoc = Iter->DefaultAttrLoc; DVar.Modifier = Data.Modifier; DVar.AppliedToPointee = Data.AppliedToPointee; + DVar.ImplicitFD = Data.ImplicitFD; return DVar; } @@ -1418,6 +1431,7 @@ Data.RefExpr.setPointerAndInt(E, IsLastprivate); Data.PrivateCopy = PrivateCopy; Data.AppliedToPointee = AppliedToPointee; + Data.ImplicitFD = false; if (PrivateCopy) { DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()]; Data.Modifier = Modifier; @@ -1425,6 +1439,7 @@ Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate); Data.PrivateCopy = nullptr; Data.AppliedToPointee = AppliedToPointee; + Data.ImplicitFD = false; } } } @@ -1533,7 +1548,7 @@ TaskgroupDescriptor = I->TaskgroupReductionRef; return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(), Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task, - /*AppliedToPointee=*/false); + /*AppliedToPointee=*/false, /*ImplicitFD=*/false); } return DSAVarData(); } @@ -1560,7 +1575,7 @@ TaskgroupDescriptor = I->TaskgroupReductionRef; return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(), Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task, - /*AppliedToPointee=*/false); + /*AppliedToPointee=*/false, /*ImplicitFD*/false); } return DSAVarData(); } @@ -1734,6 +1749,7 @@ DVar.DKind = I->Directive; DVar.Modifier = Data.Modifier; DVar.AppliedToPointee = Data.AppliedToPointee; + DVar.ImplicitFD = Data.ImplicitFD; return DVar; } } @@ -1785,6 +1801,7 @@ DVar.DKind = I->Directive; DVar.Modifier = Data.Modifier; DVar.AppliedToPointee = Data.AppliedToPointee; + DVar.ImplicitFD = Data.ImplicitFD; } return DVar; @@ -1813,11 +1830,13 @@ return getDSA(StartI, D); } -const DSAStackTy::DSAVarData -DSAStackTy::hasDSA(ValueDecl *D, - const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred, - const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred, - bool FromParent) const { +const DSAStackTy::DSAVarData DSAStackTy::hasDSA( + ValueDecl *D, + const llvm::function_ref<bool(OpenMPClauseKind, bool, + DefaultDataSharingAttributes)> + CPred, + const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred, + bool FromParent) const { if (isStackEmpty()) return {}; D = getCanonicalDecl(D); @@ -1831,12 +1850,57 @@ continue; const_iterator NewI = I; DSAVarData DVar = getDSA(NewI, D); - if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee)) + if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr)) return DVar; } return {}; } +void DSAStackTy::insertDSA( + ValueDecl *D, Expr *E, DeclRefExpr *PrivateCopy, OpenMPClauseKind A, + const llvm::function_ref<bool(OpenMPClauseKind, bool, + DefaultDataSharingAttributes)> + CPred, + const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred, + bool FromParent) { + if (isStackEmpty()) + return; + D = getCanonicalDecl(D); + iterator I = begin(); + iterator EndI = end(); + if (FromParent && I != EndI) + ++I; + for (; I != EndI; ++I) { + if (!DPred(I->Directive) && + !isImplicitOrExplicitTaskingRegion(I->Directive)) + continue; + const_iterator NewI = I; + DSAVarData DVar = getDSA(NewI, D); + if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr)) { + if (!I->SharingMap.count(D)) { + DSAInfo &Data = (*I).SharingMap[D]; + Data.Attributes = A; + Data.Modifier = 0; + Data.AppliedToPointee = false; + Data.RefExpr.setPointerAndInt(E, /*IsLastprivate*/false); + Data.PrivateCopy = PrivateCopy; + Data.ImplicitFD = true; + if (PrivateCopy) { + DSAInfo &Data = (*I).SharingMap[PrivateCopy->getDecl()]; + Data.Modifier = 0; + Data.Attributes = A; + Data.AppliedToPointee = false; + Data.RefExpr.setPointerAndInt(PrivateCopy, /*IsLastprivate*/false); + Data.PrivateCopy = nullptr; + Data.ImplicitFD = true; + } + } + return; + } + } + return; +} + const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA( ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred, const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred, @@ -2203,6 +2267,68 @@ false); } +static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id, + Expr *CaptureExpr, bool WithInit, + DeclContext *CurContext, + bool AsExpression); + +VarDecl *Sema::isOpenMPFDCaptureDecl( + ValueDecl *D, Expr *Base, bool IsArrow, SourceLocation OpLoc, + const CXXScopeSpec *SS, SourceLocation TemplateKWLoc, ValueDecl *Member, + DeclAccessPair FoundDecl, bool HadMultipleCandidates, + const DeclarationNameInfo &MemberNameInfo, QualType Ty, ExprValueKind VK, + ExprObjectKind OK) { + assert(LangOpts.OpenMP && "OpenMP is not allowed"); + D = getCanonicalDecl(D); + + auto *FD = dyn_cast<FieldDecl>(D); + if (DSAStack->getCurrentDirective() != OMPD_unknown && + (!DSAStack->isClauseParsingMode() || + DSAStack->getParentDirective() != OMPD_unknown)) { + DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA( + D, + [](OpenMPClauseKind C, bool AppliedToPointee, + DefaultDataSharingAttributes DefaultAttr) { + return isOpenMPPrivate(C) && !AppliedToPointee && + (DefaultAttr == DSA_firstprivate || + DefaultAttr == DSA_private); + }, + [](OpenMPDirectiveKind) { return true; }, + DSAStack->isClauseParsingMode()); + if (DVarPrivate.CKind == OMPC_unknown) + return isOpenMPCapturedDecl(FD); + + DeclRefExpr *VDPrivateRefExpr = DVarPrivate.PrivateCopy; + if (!VDPrivateRefExpr) { + ExprResult ME = BuildMemberExpr(Base, IsArrow, OpLoc, SS, TemplateKWLoc, + Member, FoundDecl, HadMultipleCandidates, + MemberNameInfo, Ty, VK, OK); + OMPCapturedExprDecl *CD = + buildCaptureDecl(*this, FD->getIdentifier(), ME.get(), + DVarPrivate.CKind == OMPC_private ? false : true, + CurContext->getParent(), + /*AsExpression=*/false); + VDPrivateRefExpr = + buildDeclRefExpr(*this, CD, CD->getType().getNonReferenceType(), + ME.get()->getExprLoc()); + // save captured expression in DSA. + DSAStack->insertDSA( + D, nullptr, VDPrivateRefExpr, DVarPrivate.CKind, + [](OpenMPClauseKind C, bool AppliedToPointee, + DefaultDataSharingAttributes DefaultAttr) { + return isOpenMPPrivate(C) && !AppliedToPointee && + (DefaultAttr == DSA_firstprivate || + DefaultAttr == DSA_private); + }, + [](OpenMPDirectiveKind) { return true; }, + DSAStack->isClauseParsingMode()); + } + if (DVarPrivate.CKind != OMPC_unknown) + return isOpenMPCapturedDecl(FD); + } + return nullptr; +} + VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo, unsigned StopAt) { assert(LangOpts.OpenMP && "OpenMP is not allowed"); @@ -2301,7 +2427,7 @@ // default(none) clause and not used in any clause. DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA( D, - [](OpenMPClauseKind C, bool AppliedToPointee) { + [](OpenMPClauseKind C, bool AppliedToPointee, ...) { return isOpenMPPrivate(C) && !AppliedToPointee; }, [](OpenMPDirectiveKind) { return true; }, @@ -2344,6 +2470,14 @@ OpenMPClauseKind Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, unsigned CapLevel) const { assert(LangOpts.OpenMP && "OpenMP is not allowed"); + if (DSAStack->getCurrentDirective() != OMPD_unknown && + (!DSAStack->isClauseParsingMode() || + DSAStack->getParentDirective() != OMPD_unknown)) { + DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level); + if (DVar.ImplicitFD && DVar.CKind == OMPC_private && + !DSAStack->isLoopControlVariable(D).first) + return OMPC_private; + } if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) { bool IsTriviallyCopyable = D->getType().getNonReferenceType().isTriviallyCopyableType(Context) && @@ -3522,6 +3656,8 @@ E->isInstantiationDependent()) return; if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) { + DSAStackTy::DSAVarData DVarImplicit = + Stack->getImplicitDSA(VD, /*FromParent=*/false); // Check the datasharing rules for the expressions in the clauses. if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) && !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr)) { @@ -3533,7 +3669,8 @@ } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD)) // Do not analyze internal variables and do not enclose them into // implicit clauses. - return; + if (!DVarImplicit.ImplicitFD) + return; VD = VD->getCanonicalDecl(); // Skip internally declared variables. if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) && @@ -3802,6 +3939,12 @@ if (DVar.CKind != OMPC_unknown) ImplicitFirstprivate.push_back(E); } + if (DVar.ImplicitFD && Stack->getDefaultDSA() == DSA_firstprivate && + !DVar.RefExpr && !Stack->isLoopControlVariable(FD).first) + ImplicitFirstprivate.push_back(E); + if (DVar.ImplicitFD && Stack->getDefaultDSA() == DSA_private && + !DVar.RefExpr && !Stack->isLoopControlVariable(FD).first) + ImplicitPrivate.push_back(E); return; } if (isOpenMPTargetExecutionDirective(DKind)) { @@ -4416,6 +4559,7 @@ static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id, Expr *CaptureExpr, bool WithInit, + DeclContext *CurContext, bool AsExpression) { assert(CaptureExpr); ASTContext &C = S.getASTContext(); @@ -4434,11 +4578,11 @@ } WithInit = true; } - auto *CED = OMPCapturedExprDecl::Create(C, S.CurContext, Id, Ty, + auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty, CaptureExpr->getBeginLoc()); if (!WithInit) CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C)); - S.CurContext->addHiddenDecl(CED); + CurContext->addHiddenDecl(CED); Sema::TentativeAnalysisScope Trap(S); S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false); return CED; @@ -4451,6 +4595,7 @@ CD = cast<OMPCapturedExprDecl>(VD); else CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit, + S.CurContext, /*AsExpression=*/false); return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(), CaptureExpr->getExprLoc()); @@ -4461,7 +4606,7 @@ if (!Ref) { OMPCapturedExprDecl *CD = buildCaptureDecl( S, &S.getASTContext().Idents.get(".capture_expr."), CaptureExpr, - /*WithInit=*/true, /*AsExpression=*/true); + /*WithInit=*/true, S.CurContext, /*AsExpression=*/true); Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(), CaptureExpr->getExprLoc()); } @@ -17201,6 +17346,8 @@ SourceLocation EndLoc) { SmallVector<Expr *, 8> Vars; SmallVector<Expr *, 8> PrivateCopies; + bool IsImplicitClause = + StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid(); for (Expr *RefExpr : VarList) { assert(RefExpr && "NULL expr in OpenMP private clause."); SourceLocation ELoc; @@ -17317,7 +17464,8 @@ DeclRefExpr *Ref = nullptr; if (!VD && !CurContext->isDependentContext()) Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false); - DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref); + if (!IsImplicitClause) + DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref); Vars.push_back((VD || CurContext->isDependentContext()) ? RefExpr->IgnoreParens() : Ref); @@ -17586,12 +17734,13 @@ *this, VDPrivate, RefExpr->getType().getUnqualifiedType(), RefExpr->getExprLoc()); DeclRefExpr *Ref = nullptr; + DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false); if (!VD && !CurContext->isDependentContext()) { if (TopDVar.CKind == OMPC_lastprivate) { Ref = TopDVar.PrivateCopy; } else { Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true); - if (!isOpenMPCapturedDecl(D)) + if (DVar.ImplicitFD || !isOpenMPCapturedDecl(D)) ExprCaptures.push_back(Ref->getDecl()); } } @@ -17861,7 +18010,7 @@ return true; DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA( VD, - [](OpenMPClauseKind C, bool AppliedToPointee) { + [](OpenMPClauseKind C, bool AppliedToPointee, ...) { return isOpenMPPrivate(C) && !AppliedToPointee; }, [](OpenMPDirectiveKind) { return true; }, Index: clang/lib/Sema/SemaExprMember.cpp =================================================================== --- clang/lib/Sema/SemaExprMember.cpp +++ clang/lib/Sema/SemaExprMember.cpp @@ -1866,10 +1866,13 @@ if (getLangOpts().OpenMP && IsArrow && !CurContext->isDependentContext() && isa<CXXThisExpr>(Base.get()->IgnoreParenImpCasts())) { - if (auto *PrivateCopy = isOpenMPCapturedDecl(Field)) { + if (auto *PrivateCopy = + isOpenMPFDCaptureDecl(Field, Base.get(), IsArrow, OpLoc, &SS, + /*TemplateKWLoc=*/SourceLocation(), Field, + FoundDecl, /*HadMultipleCandidates=*/false, + MemberNameInfo, MemberType, VK, OK)) return getOpenMPCapturedExpr(PrivateCopy, VK, OK, MemberNameInfo.getLoc()); - } } return BuildMemberExpr(Base.get(), IsArrow, OpLoc, &SS, Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -10614,6 +10614,16 @@ /// constructs. VarDecl *isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo = false, unsigned StopAt = 0); + + VarDecl *isOpenMPFDCaptureDecl(ValueDecl *D, Expr *Base, bool IsArrow, + SourceLocation OpLoc, const CXXScopeSpec *SS, + SourceLocation TemplateKWLoc, + ValueDecl *Member, DeclAccessPair FoundDecl, + bool HadMultipleCandidates, + const DeclarationNameInfo &MemberNameInfo, + QualType Ty, ExprValueKind VK, + ExprObjectKind OK); + ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK, ExprObjectKind OK, SourceLocation Loc);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits