akhuang updated this revision to Diff 319668.
akhuang added a comment.
make function return lambda string, and add test for lambda in function
parameters
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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits