================
@@ -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

Reply via email to