================
@@ -4626,43 +4635,89 @@ static bool
 buildCapturedStmtCaptureList(Sema &S, CapturedRegionScopeInfo *RSI,
                              SmallVectorImpl<CapturedStmt::Capture> &Captures,
                              SmallVectorImpl<Expr *> &CaptureInits) {
+  bool HasError = false; // Track if any errors occurred.
+  llvm::SmallPtrSet<VarDecl *, 4> CapturedDecomposed;
   for (const sema::Capture &Cap : RSI->Captures) {
     if (Cap.isInvalid())
       continue;
 
+    ValueDecl *CapVar = nullptr;
+    if (Cap.isVariableCapture()) {
+      CapVar = Cap.getVariable();
+      if (auto *BD = dyn_cast<BindingDecl>(CapVar)) {
+        // Detect structured bindings in OpenMP captured regions.
+        // When a BindingDecl (e.g., 'a' from 'auto [a, b] = p')
+        // is referenced inside an OpenMP region.
+        // This is reached during capture list construction when processing the
+        // OpenMP region, before expression evaluation in SemaExpr.cpp.
+        // Note: The reset to DecompositionDecl in SemaExpr.cpp happens during
+        // expression evaluation (a later phase). This code runs during capture
+        // list construction (earlier phase).
+        if (RSI->CapRegionKind == CR_OpenMP && BD->getHoldingVar()) {
+          S.Diag(Cap.getLocation(), diag::err_capture_tuple_binding_openmp)
+              << CapVar;
+          S.Diag(CapVar->getLocation(), diag::note_entity_declared_at)
+              << CapVar;
+          HasError = true; // Mark error but continue.
+          continue;        // Skip this capture, move to next.
+        }
+        CapVar = cast<VarDecl>(BD->getDecomposedDecl());
+      }
+      if (RSI->CapRegionKind == CR_OpenMP) {
+        if (auto *DD = dyn_cast<DecompositionDecl>(CapVar)) {
+          if (!CapturedDecomposed.insert(DD).second) {
+            continue; // Skip duplicate
+          }
+        }
----------------
alexey-bataev wrote:

The CapturedDecomposed dedup skips duplicate captures when multiple bindings 
from the same DecompositionDecl are used. This means CapturedStmt::captures() 
has fewer entries than RSI->Captures. Any AST consumer that walks both in 
lockstep (template instantiation, AST rewriters, libTooling clients) could 
desync. The existing template instantiation tests pass, but there should be a 
test with a dependent-type decomposition in a template that uses all bindings 
(e.g., template<typename T> void f(T p) { auto [a,b,c] = p; #pragma omp 
parallel firstprivate(a) { use(a+b+c); } }).

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