================
@@ -22651,14 +22949,90 @@ class MapBaseChecker final : public
StmtVisitor<MapBaseChecker, bool> {
public:
bool VisitDeclRefExpr(DeclRefExpr *DRE) {
- if (!isa<VarDecl>(DRE->getDecl())) {
+ ValueDecl *D = DRE->getDecl();
+ Expr *E = DRE;
+
+ // Handle BindingDecls by mapping them as member accesses.
+ // When the user writes:
+ // auto [a, b] = p;
+ // #pragma omp target map(tofrom:a) map(to:b)
+ // we transform it to:
+ // #pragma omp target map(tofrom:p.x) map(to:p.y)
+ // This avoids conflicts when different bindings have different map types.
+ if (auto *BD = dyn_cast<BindingDecl>(D)) {
+ auto *DD = cast<DecompositionDecl>(BD->getDecomposedDecl());
+ Expr *BindingExpr = BD->getBinding();
+
+ // Check if the binding is a member expression (struct/class
+ // decomposition).
+ if (auto *ME = dyn_cast_or_null<MemberExpr>(BindingExpr)) {
+
+ // Get the original variable that the decomposition was initialized
+ // from.
+ if (const VarDecl *OrigVar =
+ getOriginalVarOrDiagnose(SemaRef, DD, DRE->getExprLoc())) {
+
+ // Create a new member expression: OrigVar.field.
+ // This transforms map(a) -> map(p.x)
+ DeclarationNameInfo BaseNameInfo(OrigVar->getDeclName(),
+ DRE->getLocation());
+ Expr *BaseExpr = DeclRefExpr::Create(
+ SemaRef.Context, DRE->getQualifierLoc(),
+ DRE->getTemplateKeywordLoc(), const_cast<VarDecl *>(OrigVar),
+ /*RefersToEnclosingVariableOrCapture=*/false, BaseNameInfo,
+ OrigVar->getType(), DRE->getValueKind(), nullptr,
+ /*TemplateArgs=*/nullptr, DRE->isNonOdrUse());
+
+ // Create member expression: base.member.
+ E = MemberExpr::Create(
+ SemaRef.Context, BaseExpr, /*IsArrow=*/false,
+ ME->getOperatorLoc(), ME->getQualifierLoc(),
+ ME->getTemplateKeywordLoc(), ME->getMemberDecl(),
+ ME->getFoundDecl(), ME->getMemberNameInfo(),
+ /*TemplateArgs=*/nullptr, ME->getType(), ME->getValueKind(),
+ ME->getObjectKind(), ME->isNonOdrUse());
+
+ // Now process this as a member expression, which will properly
+ // handle the field-level mapping.
+ return Visit(E);
+ }
+ return false;
+ }
+
+ // Fallback: redirect to DecompositionDecl for non-struct bindings
+ // (arrays, tuples).
+ D = DD;
+ DeclarationNameInfo NameInfo(D->getDeclName(), DRE->getLocation());
+ E = DeclRefExpr::Create(SemaRef.Context, DRE->getQualifierLoc(),
+ DRE->getTemplateKeywordLoc(), DD,
+ /*RefersToEnclosingVariableOrCapture=*/false,
+ NameInfo, D->getType(), DRE->getValueKind(),
+ DRE->getFoundDecl(),
+ /*TemplateArgs=*/nullptr, DRE->isNonOdrUse());
+ }
+ // Handle DecompositionDecl directly (implicit captures).
+ else if (auto *DD = dyn_cast<DecompositionDecl>(D)) {
+ if (const VarDecl *OrigVar =
+ getOriginalVarOrDiagnose(SemaRef, DD, DRE->getExprLoc())) {
+ D = const_cast<VarDecl *>(OrigVar);
+ DeclarationNameInfo NameInfo(D->getDeclName(), DRE->getLocation());
+ E = DeclRefExpr::Create(SemaRef.Context, DRE->getQualifierLoc(),
+ DRE->getTemplateKeywordLoc(), D,
+ /*RefersToEnclosingVariableOrCapture=*/false,
+ NameInfo, D->getType(), DRE->getValueKind(),
+ DRE->getFoundDecl(),
+ /*TemplateArgs=*/nullptr, DRE->isNonOdrUse());
+ } else {
+ return false;
+ }
+ } else if (!isa<VarDecl>(D)) {
emitErrorMsg();
return false;
}
assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
RelevantExpr = DRE;
----------------
alexey-bataev wrote:
Previously, DRE was the same as E, but now you updated Components, but do not
update RelevantExpr
https://github.com/llvm/llvm-project/pull/190832
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits