[clang] [Clang][OpenMP] Fix crash with captured pointer-to-VLA in outlined regions (PR #182480)
via cfe-commits
cfe-commits at lists.llvm.org
Mon May 25 15:55:17 PDT 2026
https://github.com/Karthikdhondi updated https://github.com/llvm/llvm-project/pull/182480
>From bb730f12cc3acda5d4025910043407c74ad90f60 Mon Sep 17 00:00:00 2001
From: "karthik.dhondi" <karthik.dhondi at gmail.com>
Date: Fri, 20 Feb 2026 17:04:11 +0530
Subject: [PATCH] [Clang][OpenMP] Fix crash with captured pointer-to-VLA in
outlined regions
Ensure VLA size expressions are emitted for captured pointer-to-VLA
variables (including reference cases) before outlining. Previously this
could trigger an assertion in getVLASize() during code generation.
Add regression tests for C23 auto, __auto_type, explicit casts, and C++
reference cases. And also for direct VLA, lvalue/rvalue references to VLAs, and multidimensional pointer-to-VLA.
Fixes #177608
---
clang/lib/CodeGen/CGStmtOpenMP.cpp | 18 ++++++++
.../parallel-pointer-to-vla-auto-ref.cpp | 46 +++++++++++++++++++
.../OpenMP/parallel-pointer-to-vla-auto.c | 26 +++++++++++
3 files changed, 90 insertions(+)
create mode 100644 clang/test/OpenMP/parallel-pointer-to-vla-auto-ref.cpp
create mode 100644 clang/test/OpenMP/parallel-pointer-to-vla-auto.c
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 1eaf8efa142c5..c75ea1cee68d6 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -860,6 +860,24 @@ llvm::Function *CodeGenFunction::GenerateOpenMPCapturedStmtFunction(
(void)LocalScope.Privatize();
for (const auto &VLASizePair : WrapperVLASizes)
VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
+
+ for (const CapturedStmt::Capture &Cap : S.captures()) {
+ if (!Cap.capturesVariable())
+ continue;
+
+ const VarDecl *VD = Cap.getCapturedVar();
+ QualType Ty = VD->getType();
+
+ if (Ty->isReferenceType())
+ Ty = Ty->getPointeeType();
+
+ if (const PointerType *PT = Ty->getAs<PointerType>()) {
+ QualType PointeeTy = PT->getPointeeType();
+ if (PointeeTy->isVariablyModifiedType())
+ EmitVariablyModifiedType(PointeeTy);
+ }
+ }
+
PGO->assignRegionCounters(GlobalDecl(CD), F);
CapturedStmtInfo->EmitBody(*this, CD->getBody());
LocalScope.ForceCleanup();
diff --git a/clang/test/OpenMP/parallel-pointer-to-vla-auto-ref.cpp b/clang/test/OpenMP/parallel-pointer-to-vla-auto-ref.cpp
new file mode 100644
index 0000000000000..f2011c25f1e29
--- /dev/null
+++ b/clang/test/OpenMP/parallel-pointer-to-vla-auto-ref.cpp
@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -std=c++20 -emit-llvm %s -o %t.ll
+// RUN: %clang_cc1 -fopenmp -std=c++20 -emit-llvm %s -o %t.ll
+
+void bar(int N, int (*arr_)[N][N]) {
+ auto &ref = arr_; // reference to pointer-to-VLA
+ #pragma omp parallel for
+ for (int i = 0; i < N; ++i)
+ (*ref)[i][i] = 1;
+}
+
+// Direct VLA capture.
+void direct_vla(int N) {
+ int arr[N];
+
+ #pragma omp parallel for
+ for (int i = 0; i < N; ++i)
+ arr[i] = i;
+}
+
+// Lvalue reference to VLA.
+void lvalue_ref_vla(int N, int (&arr)[N]) {
+ auto &ref = arr;
+
+ #pragma omp parallel for
+ for (int i = 0; i < N; ++i)
+ ref[i] = i;
+}
+
+// Rvalue reference to VLA.
+void rvalue_ref_vla(int N, int (&&arr)[N]) {
+ auto &&ref = arr;
+
+ #pragma omp parallel for
+ for (int i = 0; i < N; ++i)
+ ref[i] = i;
+}
+
+// Pointer to 2D VLA.
+void ptr_to_2d_vla(int N, int M, int (*p)[N][M]) {
+ auto &ref = p;
+
+ #pragma omp parallel for
+ for (int i = 0; i < N; ++i)
+ (*ref)[i][i % M] = i;
+}
+
diff --git a/clang/test/OpenMP/parallel-pointer-to-vla-auto.c b/clang/test/OpenMP/parallel-pointer-to-vla-auto.c
new file mode 100644
index 0000000000000..5521679ae94ed
--- /dev/null
+++ b/clang/test/OpenMP/parallel-pointer-to-vla-auto.c
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -std=c23 -emit-llvm %s -o %t.ll
+// RUN: %clang_cc1 -fopenmp -std=c23 -emit-llvm %s -o %t.ll
+
+// Case 1: C23 auto
+void foo1(int N, int (*arr_)[N][N]) {
+ auto arr = arr_;
+ #pragma omp parallel for
+ for (int n = 0; n < N; ++n)
+ (*arr)[n][n] = 1;
+}
+
+// Case 2: GNU __auto_type
+void foo2(int N, int (*arr_)[N][N]) {
+ __auto_type arr = arr_;
+ #pragma omp parallel for
+ for (int n = 0; n < N; ++n)
+ (*arr)[n][n] = 1;
+}
+
+// Case 3: auto with explicit cast
+void foo3(int N, int (*arr_)[N][N]) {
+ auto arr = (int (*)[N][N])arr_;
+ #pragma omp parallel for
+ for (int n = 0; n < N; ++n)
+ (*arr)[n][n] = 1;
+}
More information about the cfe-commits
mailing list