[clang] [OpenMP] Support capturing structured bindings in OpenMP regions. (PR #190832)
Erich Keane via cfe-commits
cfe-commits at lists.llvm.org
Thu Apr 30 06:13:51 PDT 2026
================
@@ -3771,6 +3771,99 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
// an enclosing scope.
if (const auto *BD = dyn_cast<BindingDecl>(ND)) {
if (E->refersToEnclosingVariableOrCapture()) {
+ // OpenMP case: binding was captured via its decomposed decl.
+ if (auto *DD = dyn_cast<VarDecl>(BD->getDecomposedDecl())) {
+ if (CapturedStmtInfo &&
+ CapturedStmtInfo->getKind() == CapturedRegionKind::CR_OpenMP &&
+ CGM.getLangOpts().OpenMP) {
+ auto I = LocalDeclMap.find(DD);
+ if (I != LocalDeclMap.end()) {
+ Address DDAddr = I->second;
+ llvm::Type *ExpectedTy = CGM.getTypes().ConvertTypeForMem(
+ DD->getType().getCanonicalType());
+ if (DDAddr.getElementType() != ExpectedTy)
+ DDAddr = DDAddr.withElementType(ExpectedTy);
+ LValue CapLVal;
+ if (DD->getType()->isReferenceType())
+ CapLVal = EmitLoadOfReferenceLValue(DDAddr, DD->getType(),
+ AlignmentSource::Decl);
+ else
+ CapLVal =
+ MakeAddrLValue(DDAddr, DD->getType().getCanonicalType());
+ if (getLangOpts().OpenMP &&
+ CGM.getOpenMPRuntime().isNontemporalDecl(DD))
+ CapLVal.setNontemporal(/*Value=*/true);
+ // Extract the specific binding from the decomposed object.
+ Expr *BindingExpr = BD->getBinding()->IgnoreImplicit();
+ if (auto *ME = dyn_cast<MemberExpr>(BindingExpr)) {
+ // Struct/union: access field.
+ return EmitLValueForField(CapLVal,
+ cast<FieldDecl>(ME->getMemberDecl()));
+ }
+ if (auto *ASE = dyn_cast<ArraySubscriptExpr>(BindingExpr)) {
+ Address Base = CapLVal.getAddress();
+ llvm::Value *Idx = EmitScalarExpr(ASE->getIdx());
+ llvm::Value *Indices[] = {llvm::ConstantInt::get(Int32Ty, 0),
+ Idx};
+ llvm::Type *ElemTy =
+ CGM.getTypes().ConvertTypeForMem(ASE->getType());
+ llvm::Value *EltPtr = Builder.CreateInBoundsGEP(
+ Base.getElementType(), Base.emitRawPointer(*this), Indices,
+ "arrayidx");
+ CharUnits Align = Base.getAlignment().alignmentOfArrayElement(
+ getContext().getTypeSizeInChars(ASE->getType()));
+ Address EltAddr(EltPtr, ElemTy, Align);
+ return MakeAddrLValue(EltAddr, ASE->getType());
+ }
+ // Fallback for complex binding types.
+ // TODO: Tuple bindings (std::tuple, std::pair via tuple protocol)
+ // use hidden temporary variables that aren't captured in OpenMP
+ // regions. Need to re-emit the get<N>() call on the captured tuple
+ // base object. For now, this will fail.
+ if (isa<DeclRefExpr>(BindingExpr))
+ llvm_unreachable(
+ "tuple-like structured bindings not yet supported in OpenMP");
+ return EmitLValue(BindingExpr);
+ }
+ // DD not in LocalDeclMap, check capture struct
+ if (auto *FD = CapturedStmtInfo->lookup(DD)) {
----------------
erichkeane wrote:
Ah, I see the 'else' here. We should be checking whether it is captured first and do the work for that, THEN we can use the emit-lvalue type stuff.
https://github.com/llvm/llvm-project/pull/190832
More information about the cfe-commits
mailing list