This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. Closed by commit rGd73564c51003: [DebugInfo][CodeView] Use <lambda_n> as the display name for lambdas. (authored by akhuang).
Changed prior to commit: https://reviews.llvm.org/D95187?vs=319668&id=319991#toc Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D95187/new/ https://reviews.llvm.org/D95187 Files: clang/include/clang/AST/Mangle.h clang/lib/AST/ItaniumMangle.cpp clang/lib/AST/MicrosoftMangle.cpp clang/lib/CodeGen/CGDebugInfo.cpp clang/test/CodeGenCXX/debug-info-codeview-unnamed.cpp clang/test/CodeGenCXX/debug-info-gline-tables-only-codeview.cpp
Index: clang/test/CodeGenCXX/debug-info-gline-tables-only-codeview.cpp =================================================================== --- clang/test/CodeGenCXX/debug-info-gline-tables-only-codeview.cpp +++ clang/test/CodeGenCXX/debug-info-gline-tables-only-codeview.cpp @@ -1,17 +1,26 @@ -// RUN: %clang_cc1 %s -gcodeview -debug-info-kind=line-tables-only -S \ -// RUN: -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -gcodeview -debug-info-kind=line-tables-only -emit-llvm \ +// RUN: -o - | FileCheck %s // Checks that clang with "-gline-tables-only" with CodeView emits some debug // info for variables and types when they appear in function scopes. namespace NS { struct C { void m() {} + // Test externally visible lambda. + void lambda2() { []() {}(); } + + // Test naming for function parameters. + void lambda_params(int x = [](){ return 0; }(), int y = [](){ return 1; }()) {} }; void f() {} } +// Test non- externally visible lambda. +auto lambda1 = []() { return 1; }; + NS::C c; + void test() { // CHECK: !DISubprogram(name: "f", scope: ![[NS:[0-9]+]], // CHECK-SAME: type: ![[F:[0-9]+]] @@ -21,10 +30,30 @@ NS::f(); // CHECK: ![[M:[0-9]+]] = distinct !DISubprogram(name: "m", scope: ![[C:[0-9]+]], - // CHECK-SAME: type: ![[MTYPE:[0-9]+]] + // CHECK-SAME: type: ![[MTYPE:[0-9]+]], // CHECK: ![[C]] = !DICompositeType(tag: DW_TAG_structure_type, name: "C", // CHECK-SAME: flags: DIFlagFwdDecl // CHECK-NOT: identifier // CHECK: ![[MTYPE]] = !DISubroutineType({{.*}}types: !{{.*}}) c.m(); + + // CHECK: !DISubprogram(name: "operator()", scope: ![[LAMBDA0:[0-9]+]], + // CHECK: ![[LAMBDA0]] = !DICompositeType(tag: DW_TAG_class_type, + // CHECK-SAME: name: "<lambda_0>", + // CHECK-SAME: flags: DIFlagFwdDecl + lambda1(); + + // CHECK: !DISubprogram(name: "operator()", scope: ![[LAMBDA1_1:[0-9]+]], + // CHECK: ![[LAMBDA1_1]] = !DICompositeType(tag: DW_TAG_class_type, + // CHECK-SAME: name: "<lambda_1_1>", + // CHECK: !DISubprogram(name: "operator()", scope: ![[LAMBDA2_1:[0-9]+]], + // CHECK: ![[LAMBDA2_1]] = !DICompositeType(tag: DW_TAG_class_type, + // CHECK-SAME: name: "<lambda_2_1>", + c.lambda_params(); + + // CHECK: !DISubprogram(name: "operator()", scope: ![[LAMBDA1:[0-9]+]], + // CHECK: ![[LAMBDA1]] = !DICompositeType(tag: DW_TAG_class_type, + // CHECK-SAME: name: "<lambda_1>", + // CHECK-SAME: flags: DIFlagFwdDecl + c.lambda2(); } Index: clang/test/CodeGenCXX/debug-info-codeview-unnamed.cpp =================================================================== --- clang/test/CodeGenCXX/debug-info-codeview-unnamed.cpp +++ clang/test/CodeGenCXX/debug-info-codeview-unnamed.cpp @@ -100,7 +100,7 @@ // MSVC-SAME: ) // MSVC: [[TYPE_OF_FOUR]] = distinct !DICompositeType // MSVC-SAME: tag: DW_TAG_class_type - // MSVC-NOT: name: + // MSVC-SAME: name: "<lambda_0>" // MSVC-SAME: identifier: ".?AV<lambda_0>@?0??main@@9@" // MSVC-SAME: ) Index: clang/lib/CodeGen/CGDebugInfo.cpp =================================================================== --- clang/lib/CodeGen/CGDebugInfo.cpp +++ 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,14 @@ // 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<CXXRecordDecl>(RD)) + if (CXXRD->isLambda()) { + StringRef LambdaName = + CGM.getCXXABI().getMangleContext().getLambdaString(CXXRD); + return internString(LambdaName); + } + if (!Name.empty()) { SmallString<256> UnnamedType("<unnamed-type-"); UnnamedType += Name; Index: clang/lib/AST/MicrosoftMangle.cpp =================================================================== --- clang/lib/AST/MicrosoftMangle.cpp +++ clang/lib/AST/MicrosoftMangle.cpp @@ -228,6 +228,34 @@ return true; } + StringRef getLambdaString(const CXXRecordDecl *Lambda) override { + assert(Lambda->isLambda() && "RD must be a lambda!"); + llvm::SmallString<10> Name("<lambda_"); + + Decl *LambdaContextDecl = Lambda->getLambdaContextDecl(); + unsigned LambdaManglingNumber = Lambda->getLambdaManglingNumber(); + unsigned LambdaId; + const ParmVarDecl *Parm = dyn_cast_or_null<ParmVarDecl>(LambdaContextDecl); + const FunctionDecl *Func = + Parm ? dyn_cast<FunctionDecl>(Parm->getDeclContext()) : nullptr; + + if (Func) { + unsigned DefaultArgNo = + Func->getNumParams() - Parm->getFunctionScopeIndex(); + Name += llvm::utostr(DefaultArgNo); + Name += "_"; + } + + if (LambdaManglingNumber) + LambdaId = LambdaManglingNumber; + else + LambdaId = getLambdaIdForDebugInfo(Lambda); + + Name += llvm::utostr(LambdaId); + Name += ">"; + return StringRef(Name); + } + unsigned getLambdaId(const CXXRecordDecl *RD) { assert(RD->isLambda() && "RD must be a lambda!"); assert(!RD->isExternallyVisible() && "RD must not be visible!"); @@ -238,6 +266,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<const CXXRecordDecl *, unsigned>::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 { Index: clang/lib/AST/ItaniumMangle.cpp =================================================================== --- clang/lib/AST/ItaniumMangle.cpp +++ clang/lib/AST/ItaniumMangle.cpp @@ -203,6 +203,36 @@ disc = discriminator-2; return true; } + + StringRef getLambdaString(const CXXRecordDecl *Lambda) override { + // This function matches the one in MicrosoftMangle, which returns + // the string that is used in lambda mangled names. + assert(Lambda->isLambda() && "RD must be a lambda!"); + llvm::SmallString<10> Name("<lambda"); + Decl *LambdaContextDecl = Lambda->getLambdaContextDecl(); + unsigned LambdaManglingNumber = Lambda->getLambdaManglingNumber(); + unsigned LambdaId; + const ParmVarDecl *Parm = dyn_cast_or_null<ParmVarDecl>(LambdaContextDecl); + const FunctionDecl *Func = + Parm ? dyn_cast<FunctionDecl>(Parm->getDeclContext()) : nullptr; + + if (Func) { + unsigned DefaultArgNo = + Func->getNumParams() - Parm->getFunctionScopeIndex(); + Name += llvm::utostr(DefaultArgNo); + Name += "_"; + } + + if (LambdaManglingNumber) + LambdaId = LambdaManglingNumber; + else + LambdaId = getAnonymousStructIdForDebugInfo(Lambda); + + Name += llvm::utostr(LambdaId); + Name += '>'; + return StringRef(Name); + } + /// @} }; Index: clang/include/clang/AST/Mangle.h =================================================================== --- clang/include/clang/AST/Mangle.h +++ clang/include/clang/AST/Mangle.h @@ -89,6 +89,17 @@ return Result.first->second; } + uint64_t getAnonymousStructIdForDebugInfo(const NamedDecl *D) { + llvm::DenseMap<const NamedDecl *, uint64_t>::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 StringRef getLambdaString(const CXXRecordDecl *Lambda) = 0; + /// @name Mangler Entry Points /// @{
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits