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 @@ -254,24 +254,12 @@ FunctionTemplateSpecializationInfo *Info = FD->getTemplateSpecializationInfo(); - // Emit the unqualified name in normal operation. LLVM and the debugger can - // compute the fully qualified name from the scope chain. If we're only - // emitting line table info, there won't be any scope chains, so emit the - // fully qualified name here so that stack traces are more accurate. - // FIXME: Do this when emitting DWARF as well as when emitting CodeView after - // evaluating the size impact. - bool UseQualifiedName = DebugKind == codegenoptions::DebugLineTablesOnly && - CGM.getCodeGenOpts().EmitCodeView; - - if (!Info && FII && !UseQualifiedName) + if (!Info && FII) return FII->getName(); SmallString<128> NS; llvm::raw_svector_ostream OS(NS); - if (!UseQualifiedName) - FD->printName(OS); - else - FD->printQualifiedName(OS, getPrintingPolicy()); + FD->printName(OS); // Add any template specialization args. if (Info) { @@ -1058,7 +1046,10 @@ Flags |= llvm::DINode::FlagNonTrivial; // Create the type. - SmallString<256> Identifier = getTypeIdentifier(Ty, CGM, TheCU); + SmallString<256> Identifier; + // Don't include a linkage name in line tables only. + if (CGM.getCodeGenOpts().hasReducedDebugInfo()) + Identifier = getTypeIdentifier(Ty, CGM, TheCU); llvm::DICompositeType *RetTy = DBuilder.createReplaceableCompositeType( getTagForRecord(RD), RDName, Ctx, DefUnit, Line, 0, Size, Align, Flags, Identifier); @@ -2326,6 +2317,9 @@ if (ES->hasExternalDefinitions(RD) == ExternalASTSource::EK_Always) return true; + if (DebugKind == codegenoptions::DebugLineTablesOnly) + return true; + if (DebugKind > codegenoptions::LimitedDebugInfo) return false; @@ -3473,7 +3467,11 @@ DebugKind <= codegenoptions::DebugLineTablesOnly)) LinkageName = StringRef(); - if (CGM.getCodeGenOpts().hasReducedDebugInfo()) { + // Emit the function scope in line tables only mode (if CodeView) to + // differentiate between function names. + if (CGM.getCodeGenOpts().hasReducedDebugInfo() || + (DebugKind == codegenoptions::DebugLineTablesOnly && + CGM.getCodeGenOpts().EmitCodeView)) { if (const NamespaceDecl *NSDecl = dyn_cast_or_null(FD->getDeclContext())) FDContext = getOrCreateNamespace(NSDecl); @@ -3482,6 +3480,8 @@ llvm::DIScope *Mod = getParentModuleOrNull(RDecl); FDContext = getContextDescriptor(RDecl, Mod ? Mod : TheCU); } + } + if (CGM.getCodeGenOpts().hasReducedDebugInfo()) { // Check if it is a noreturn-marked function if (FD->isNoReturn()) Flags |= llvm::DINode::FlagNoReturn; diff --git a/clang/test/CodeGenCXX/debug-info-codeview-display-name.cpp b/clang/test/CodeGenCXX/debug-info-codeview-display-name.cpp --- a/clang/test/CodeGenCXX/debug-info-codeview-display-name.cpp +++ b/clang/test/CodeGenCXX/debug-info-codeview-display-name.cpp @@ -20,11 +20,9 @@ namespace N { int b() { return 0; } -// UNQUAL-DAG: "b" -// QUAL-DAG: "N::b" +// CHECK-DAG: "b" namespace { void func() { } } -// UNQUAL-DAG: "func" -// QUAL-DAG: "N::`anonymous namespace'::func" +// CHECK-DAG: "func" } void _c(void) { @@ -35,24 +33,19 @@ struct foo { int operator+(int); foo(){} -// UNQUAL-DAG: "foo" -// QUAL-DAG: "foo::foo" +// CHECK-DAG: "foo" ~foo(){} -// UNQUAL-DAG: "~foo" -// QUAL-DAG: "foo::~foo" +// CHECK-DAG: "~foo" foo(int i){} -// UNQUAL-DAG: "foo" -// QUAL-DAG: "foo::foo" +// CHECK-DAG: "foo" foo(char *q){} -// UNQUAL-DAG: "foo" -// QUAL-DAG: "foo::foo" +// CHECK-DAG: "foo" static foo* static_method() { return 0; } -// UNQUAL-DAG: "static_method" -// QUAL-DAG: "foo::static_method" +// CHECK-DAG: "static_method" }; @@ -61,8 +54,7 @@ foo::static_method(); } -// UNQUAL-DAG: "operator+" -// QUAL-DAG: "foo::operator+" +// CHECK-DAG: "operator+" int foo::operator+(int a) { return a; } // PR17371 @@ -82,17 +74,11 @@ void OverloadedNewDelete::operator delete[](void *) { } int OverloadedNewDelete::operator+(int x) { return x; }; -// UNQUAL-DAG: "operator new" -// UNQUAL-DAG: "operator new[]" -// UNQUAL-DAG: "operator delete" -// UNQUAL-DAG: "operator delete[]" -// UNQUAL-DAG: "operator+" -// QUAL-DAG: "OverloadedNewDelete::operator new" -// QUAL-DAG: "OverloadedNewDelete::operator new[]" -// QUAL-DAG: "OverloadedNewDelete::operator delete" -// QUAL-DAG: "OverloadedNewDelete::operator delete[]" -// QUAL-DAG: "OverloadedNewDelete::operator+" - +// CHECK-DAG: "operator new" +// CHECK-DAG: "operator new[]" +// CHECK-DAG: "operator delete" +// CHECK-DAG: "operator delete[]" +// CHECK-DAG: "operator+" template void fn_tmpl() {} diff --git a/clang/test/CodeGenCXX/debug-info-codeview-scopes.cpp b/clang/test/CodeGenCXX/debug-info-codeview-scopes.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGenCXX/debug-info-codeview-scopes.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -debug-info-kind=line-tables-only -S -emit-llvm -std=c++11 -o - %s | FileCheck --check-prefix LINUX %s +// RUN: %clang_cc1 -triple x86_64-windows-msvc -debug-info-kind=line-tables-only -gcodeview -S -emit-llvm -std=c++11 -o - %s | FileCheck --check-prefix MSVC %s + +// Check that we emit type information for function scopes in line tables for +// CodeView. + +namespace A { +void f() {} + +struct S { + static void m() {} +}; +} + +int main() { + A::f(); + A::S::m(); + return 0; + // MSVC: !{{[0-9]+}} = distinct !DISubprogram(name: "f" + // MSVC-SAME: scope: [[SCOPE1:![0-9]+]] + // MSVC-SAME: ) + // MSVC: [[SCOPE1]] = !DINamespace(name: "A", {{.*}}) + // MSVC: !{{[0-9]+}} = distinct !DISubprogram(name: "m" + // MSVC-SAME: scope: [[SCOPE2:![0-9]+]] + // MSVC-SAME: ) + // MSVC: [[SCOPE2]] = !DICompositeType(tag: DW_TAG_structure_type, + // MSVC-SAME: name: "S", + // MSVC-SAME: scope: [[SCOPE1]] + // MSVC-SAME: ) + + // LINUX-NOT: !DINamespace + // LINUX-NOT: !DICompositeType + return 0; +} diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -367,8 +367,10 @@ return I->second; // The display name includes function template arguments. Drop them to match - // MSVC. - StringRef DisplayName = SP->getName().split('<').first; + // MSVC, if not using line tables only. + StringRef DisplayName = SP->getName(); + if (SP->getUnit()->getEmissionKind() != DICompileUnit::LineTablesOnly) + DisplayName = SP->getName().split('<').first; const DIScope *Scope = SP->getScope(); TypeIndex TI; diff --git a/llvm/test/DebugInfo/COFF/function-display-name.ll b/llvm/test/DebugInfo/COFF/function-display-name.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/COFF/function-display-name.ll @@ -0,0 +1,51 @@ +; RUN: llc -mtriple=i686-pc-win32 -o - -O0 -filetype=obj < %s \ +; RUN: | llvm-readobj --codeview - | FileCheck %s + +; Check that we removed templated args from the display name in full debug mode +; but not with line tables only. + +; CHECK: FuncId (0x1002) { +; CHECK-NEXT: TypeLeafKind: LF_FUNC_ID ({{.*}}) +; CHECK-NEXT: ParentScope: 0x0 +; CHECK-NEXT: FunctionType: void () ({{.*}}) +; CHECK-NEXT: Name: Test() + +; CHECK: FuncId (0x1003) { +; CHECK-NEXT: TypeLeafKind: LF_FUNC_ID ({{.*}}) +; CHECK-NEXT: ParentScope: 0x0 +; CHECK-NEXT: FunctionType: void () ({{.*}}) +; CHECK-NEXT: Name: Test + +; ModuleID = 't.cpp' +source_filename = "t.cpp" +target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc" + +define i32 @"?Test1"() !dbg !7 { +entry: + ret i32 0, !dbg !10 +} + +define i32 @"?Test2"() !dbg !13 { +entry: + ret i32 0, !dbg !12 +} + +!llvm.dbg.cu = !{!0, !11} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 12.0.0 (https://github.com/llvm/llvm-project.git b93410cbeaa48fec9a15a23e4770be10abc04d4e)", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "", directory: "C:\\src\\tests", checksumkind: CSK_MD5, checksum: "a28f11090424d4b37acdde65a98985a1") +!2 = !{} +!3 = !{i32 2, !"CodeView", i32 1} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 2} +!6 = !{!"clang version 12.0.0 (https://github.com/llvm/llvm-project.git b93410cbeaa48fec9a15a23e4770be10abc04d4e)"} +!7 = distinct !DISubprogram(name: "Test()", scope: !8, file: !8, line: 19, type: !9, scopeLine: 19, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2) +!8 = !DIFile(filename: "t.cpp", directory: "C:\\src\\tests", checksumkind: CSK_MD5, checksum: "a28f11090424d4b37acdde65a98985a1") +!9 = !DISubroutineType(types: !2) +!10 = !DILocation(line: 25, column: 3, scope: !7) +!11 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!12 = !DILocation(line: 0, column: 0, scope: !13) +!13 = distinct !DISubprogram(name: "Test", scope: !8, file: !8, line: 1, type: !9, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !11, retainedNodes: !2)