================
@@ -22651,14 +23010,91 @@ 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)) {
+
+        // Use the DecompositionDecl as the base for the member expression.
+        // The structured binding creates a copy (if initialized from a
+        // variable) or holds the only storage (if initialized from a prvalue).
+        // Using DD ensures map clauses reference the correct storage.
+        DeclarationNameInfo BaseNameInfo(DD->getDeclName(), 
DRE->getLocation());
+        Expr *BaseExpr = DeclRefExpr::Create(
+            SemaRef.Context, DRE->getQualifierLoc(),
+            DRE->getTemplateKeywordLoc(), DD,
+            /*RefersToEnclosingVariableOrCapture=*/false, BaseNameInfo,
+            DD->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);
+      }
+      if (isa_and_present<ArraySubscriptExpr>(BindingExpr)) {
+        if (getOriginalVarOrDiagnose(SemaRef, DD, DRE->getExprLoc())) {
+          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());
+          return Visit(E);
----------------
alexey-bataev wrote:

```suggestion
      if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(BindingExpr)) {
        DeclarationNameInfo BaseNameInfo(DD->getDeclName(), DRE->getLocation());
        Expr *BaseExpr = DeclRefExpr::Create(
            SemaRef.Context, DRE->getQualifierLoc(),
            DRE->getTemplateKeywordLoc(), DD,
            /*RefersToEnclosingVariableOrCapture=*/false, BaseNameInfo,
            DD->getType().getNonReferenceType(), DRE->getValueKind(), nullptr,
            /*TemplateArgs=*/nullptr, DRE->isNonOdrUse());
        E = new (SemaRef.Context)
            ArraySubscriptExpr(BaseExpr, ASE->getIdx(), ASE->getType(),
                                ASE->getValueKind(), ASE->getObjectKind(),
                                ASE->getRBracketLoc());
        return Visit(E);
      }
```
???

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