https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/231606

>From a30e32dd23f8f0b69e5b05df0b968c1b798757b8 Mon Sep 17 00:00:00 2001
From: Ambrose Leeb <[email protected]>
Date: Tue, 13 Oct 2026 18:04:09 +0000
Subject: [PATCH] [Clang] Fix lambda numbering for reopened namespaces

Have `getManglingNumberContext()` use the primary `DeclContext` to make
sure that reopened namespaces share a mangling context; otherwise, we
may end up with symbol collisions between different lambdas.

Fixes #231096.
---
 clang/docs/ReleaseNotes.md                    |  3 +
 clang/lib/AST/ASTContext.cpp                  |  3 +
 .../CodeGenCUDA/lambda-reopened-namespace.cu  | 56 +++++++++++++++++++
 3 files changed, 62 insertions(+)
 create mode 100644 clang/test/CodeGenCUDA/lambda-reopened-namespace.cu

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 1dc1764978ea27..474f8153987c0d 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -1109,6 +1109,9 @@ features cannot lower the translation-unit ABI level;
 
 #### CUDA Support
 
+- Fixed a CUDA miscompile caused by lambdas in reopened namespaces receiving
+  the same mangled name. (#GH231096)
+
 - Added `--cuda-emit-nvcc-abi` to emit the NVCC-compatible host registration 
ABI
   (`__cudaRegisterLinkedBinary`).
 
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 02d656feb0cee5..0af3bc3be0bd9d 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -13851,6 +13851,9 @@ void 
ASTContext::setClassMaybeNeedsVectorDeletingDestructor(
 MangleNumberingContext &
 ASTContext::getManglingNumberContext(const DeclContext *DC) {
   assert(LangOpts.CPlusPlus);  // We don't need mangling numbers for plain C.
+  // Reopened namespaces share a mangling context so that declarations in
+  // different namespace blocks do not receive duplicate mangling numbers.
+  DC = DC->getPrimaryContext();
   std::unique_ptr<MangleNumberingContext> &MCtx = MangleNumberingContexts[DC];
   if (!MCtx)
     MCtx = createMangleNumberingContext();
diff --git a/clang/test/CodeGenCUDA/lambda-reopened-namespace.cu 
b/clang/test/CodeGenCUDA/lambda-reopened-namespace.cu
new file mode 100644
index 00000000000000..0a72b20eb2503d
--- /dev/null
+++ b/clang/test/CodeGenCUDA/lambda-reopened-namespace.cu
@@ -0,0 +1,56 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -x cuda -emit-llvm -o - %s 
| FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -x cuda -O3 -emit-llvm -o 
- %s | FileCheck %s --check-prefix=OPT
+
+// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -aux-triple 
x86_64-unknown-linux-gnu \
+// RUN:   -fcuda-is-device -x cuda -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -aux-triple 
x86_64-unknown-linux-gnu \
+// RUN:   -fcuda-is-device -x cuda -O3 -emit-llvm -o - %s | FileCheck %s 
--check-prefix=OPT
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -x hip -emit-llvm -o - %s 
| FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -x hip -O3 -emit-llvm -o - 
%s | FileCheck %s --check-prefix=OPT
+
+// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -target-cpu gfx906 -aux-triple 
x86_64-unknown-linux-gnu \
+// RUN:   -fcuda-is-device -x hip -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -target-cpu gfx906 -aux-triple 
x86_64-unknown-linux-gnu \
+// RUN:   -fcuda-is-device -x hip -O3 -emit-llvm -o - %s | FileCheck %s 
--check-prefix=OPT
+
+#if defined(__CUDA_ARCH__) || defined(__HIP_DEVICE_COMPILE__)
+#define ATTR __attribute__((device))
+#else
+#define ATTR
+#endif
+
+// Forced CUDA/HIP lambda numbering must be shared by all declarations of the 
same
+// namespace. Otherwise, the second function pointer refers to the first 
lambda.
+namespace reopened {
+static ATTR int (*first)() = [] ATTR { return 144; };
+}
+namespace reopened {
+static ATTR int (*second)() = [] ATTR { return 7; };
+}
+
+// CHECK-DAG: @_ZN8reopenedL5firstE = internal{{.*}} global ptr 
@_ZN8reopenedUlvE_8__invokeEv
+// CHECK-DAG: @_ZN8reopenedL6secondE = internal{{.*}} global ptr 
@_ZN8reopenedUlvE0_8__invokeEv
+// CHECK-DAG: define internal{{.*}} i32 @_ZN8reopenedUlvE_8__invokeEv()
+// CHECK-DAG: define internal{{.*}} i32 @_ZN8reopenedUlvE0_8__invokeEv()
+// OPT-LABEL: define{{.*}} i32 @named_namespace()
+// OPT: ret i32 151
+extern "C" ATTR int named_namespace() {
+  return reopened::first() + reopened::second();
+}
+
+// Reopened anonymous namespaces also share the same numbering context.
+namespace {
+static ATTR int (*first)() = [] ATTR { return 20; };
+}
+namespace {
+static ATTR int (*second)() = [] ATTR { return 3; };
+}
+
+// CHECK-DAG: @_ZN12_GLOBAL__N_15firstE = internal{{.*}} global ptr 
@_ZN12_GLOBAL__N_1UlvE_8__invokeEv
+// CHECK-DAG: @_ZN12_GLOBAL__N_16secondE = internal{{.*}} global ptr 
@_ZN12_GLOBAL__N_1UlvE0_8__invokeEv
+// CHECK-DAG: define internal{{.*}} i32 @_ZN12_GLOBAL__N_1UlvE_8__invokeEv()
+// CHECK-DAG: define internal{{.*}} i32 @_ZN12_GLOBAL__N_1UlvE0_8__invokeEv()
+// OPT-LABEL: define{{.*}} i32 @anonymous_namespace()
+// OPT: ret i32 23
+extern "C" ATTR int anonymous_namespace() { return first() + second(); }

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to