diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index e74fe02bd0cf5..f7fd1d1831500 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -304,12 +304,24 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC) { // Yeah, I think the only cases left where lambdas don't need a // mangling are when they have (effectively) internal linkage or appear // in a non-inline function in a non-module translation unit. - if (auto *ND = dyn_cast(ManglingContextDecl ? ManglingContextDecl - : cast(DC)); + + Decl *ManglingContextDeclForModule = [&]() { + if (!ManglingContextDecl || [&]() { + // If we must allocate mangling numbers but the + // `ManglingContextDecl` is a local variable, use the `DeclContext` + // containing the lambda expression instead. + VarDecl *Var = dyn_cast(ManglingContextDecl); + return Var && Var->isLocalVarDecl(); + }()) + return const_cast(cast(DC)); + + return ManglingContextDecl; + }(); + + if (auto *ND = dyn_cast(ManglingContextDeclForModule); ND && (ND->isInNamedModule() || ND->isFromGlobalModule()) && ND->isExternallyVisible()) { - if (!ManglingContextDecl) - ManglingContextDecl = const_cast(cast(DC)); + ManglingContextDecl = ND; return NonInlineInModulePurview; } diff --git a/clang/test/Modules/pr178893.cppm b/clang/test/Modules/pr178893.cppm new file mode 100644 index 0000000000000..6d2a599588667 --- /dev/null +++ b/clang/test/Modules/pr178893.cppm @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -std=c++20 -triple x86_64-apple-macosx10.7.0 -fmodules -xc++ -emit-llvm -o - %s -w | FileCheck %s + +// CHECK-LABEL: define linkonce_odr noundef i32 @_ZZN8PR178893W3mod6format5parseEPiENKUlvE_clEv +// CHECK-LABEL: define linkonce_odr noundef i32 @_ZZN8PR178893W3mod6format5parseEPiENKUlvE0_clEv + +export module mod; + +namespace PR178893 { + struct format { + static inline int parse(int* i) + { + int number; + number = [&]() -> int { return i[0]; }(); + + volatile bool b = true; + if (b) { + auto identifier = [&]() -> int { return i[1]; }(); + return identifier; + } + + return number; + } + }; + + int test_format() { + int n[2] = {1, 0}; + return format::parse(n); + } +}