diff --git a/clang/include/clang/AST/Mangle.h b/clang/include/clang/AST/Mangle.h --- a/clang/include/clang/AST/Mangle.h +++ b/clang/include/clang/AST/Mangle.h @@ -89,6 +89,17 @@ return Result.first->second; } + uint64_t getAnonymousStructIdForDebugInfo(const NamedDecl *D) { + llvm::DenseMap::iterator Result = + AnonStructIds.find(D); + // The decl should already be inserted, but return 0 in case it is not. + if (Result == AnonStructIds.end()) + return 0; + return Result->second; + } + + virtual unsigned getLambdaNumber(const CXXRecordDecl *Lambda) = 0; + /// @name Mangler Entry Points /// @{ diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -203,6 +203,14 @@ disc = discriminator-2; return true; } + + unsigned getLambdaNumber(const CXXRecordDecl *Lambda) override { + unsigned Number = Lambda->getLambdaManglingNumber(); + if (Number == 0) + return getAnonymousStructIdForDebugInfo(Lambda); + return Number; + } + /// @} }; diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -228,6 +228,13 @@ return true; } + unsigned getLambdaNumber(const CXXRecordDecl *Lambda) override { + unsigned LambdaManglingNumber = Lambda->getLambdaManglingNumber(); + if (LambdaManglingNumber) + return LambdaManglingNumber; + return getLambdaIdForDebugInfo(Lambda); + } + unsigned getLambdaId(const CXXRecordDecl *RD) { assert(RD->isLambda() && "RD must be a lambda!"); assert(!RD->isExternallyVisible() && "RD must not be visible!"); @@ -238,6 +245,19 @@ return Result.first->second; } + unsigned getLambdaIdForDebugInfo(const CXXRecordDecl *RD) { + assert(RD->isLambda() && "RD must be a lambda!"); + assert(!RD->isExternallyVisible() && "RD must not be visible!"); + assert(RD->getLambdaManglingNumber() == 0 && + "RD must not have a mangling number!"); + llvm::DenseMap::iterator Result = + LambdaIds.find(RD); + // The lambda should exist, but return 0 in case it doesn't. + if (Result == LambdaIds.end()) + return 0; + return Result->second; + } + /// Return a character sequence that is (somewhat) unique to the TU suitable /// for mangling anonymous namespaces. StringRef getAnonymousNamespaceHash() const { diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -317,8 +317,9 @@ if (const IdentifierInfo *II = RD->getIdentifier()) return II->getName(); - // The CodeView printer in LLVM wants to see the names of unnamed types: it is - // used to reconstruct the fully qualified type names. + // The CodeView printer in LLVM wants to see the names of unnamed types + // because they need to have a unique identifier. + // These names are used to reconstruct the fully qualified type names. if (CGM.getCodeGenOpts().EmitCodeView) { if (const TypedefNameDecl *D = RD->getTypedefNameForAnonDecl()) { assert(RD->getDeclContext() == D->getDeclContext() && @@ -342,6 +343,18 @@ // associate typedef mangled in if they have one. Name = TND->getName(); + // Give lambdas a display name based on their name mangling. + if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) + if (CXXRD->isLambda()) { + unsigned LambdaNumber = + CGM.getCXXABI().getMangleContext().getLambdaNumber(CXXRD); + + SmallString<256> LambdaName(" UnnamedType("" // MSVC-SAME: identifier: ".?AV@?0??main@@9@" // MSVC-SAME: ) diff --git a/clang/test/CodeGenCXX/debug-info-gline-tables-only-codeview.cpp b/clang/test/CodeGenCXX/debug-info-gline-tables-only-codeview.cpp --- a/clang/test/CodeGenCXX/debug-info-gline-tables-only-codeview.cpp +++ b/clang/test/CodeGenCXX/debug-info-gline-tables-only-codeview.cpp @@ -6,10 +6,15 @@ namespace NS { struct C { void m() {} + // Test externally visible lambda. + void lambda2() { []() {}(); } }; void f() {} } +// Test non- externally visible lambda. +auto lambda1 = []() { return 1; }; + NS::C c; void test() { @@ -27,4 +32,16 @@ // CHECK-NOT: identifier // CHECK: ![[MTYPE]] = !DISubroutineType(types: !{{.*}}) c.m(); + + // CHECK: !DISubprogram(name: "operator()", scope: ![[LAMBDA1:[0-9]+]] + // CHECK: ![[LAMBDA1]] = !DICompositeType(tag: DW_TAG_class_type, + // CHECK-SAME: name: "" + // CHECK-SAME: flags: DIFlagFwdDecl + lambda1(); + + // CHECK: !DISubprogram(name: "operator()", scope: ![[LAMBDA2:[0-9]+]] + // CHECK: ![[LAMBDA2]] = !DICompositeType(tag: DW_TAG_class_type, + // CHECK-SAME: name: "" + // CHECK-SAME: flags: DIFlagFwdDecl + c.lambda2(); }