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) {
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);
if (ES->hasExternalDefinitions(RD) == ExternalASTSource::EK_Always)
return true;
+ if (DebugKind == codegenoptions::DebugLineTablesOnly)
+ return true;
+
if (DebugKind > codegenoptions::LimitedDebugInfo)
return false;
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<NamespaceDecl>(FD->getDeclContext()))
FDContext = getOrCreateNamespace(NSDecl);
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;
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) {
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"
};
foo::static_method();
}
-// UNQUAL-DAG: "operator+"
-// QUAL-DAG: "foo::operator+"
+// CHECK-DAG: "operator+"
int foo::operator+(int a) { return a; }
// PR17371
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 <typename T, void (*)(void)>
void fn_tmpl() {}
--- /dev/null
+// 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;
+}