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; +}