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
