diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp index 3811f4a8ab799..88eeca5ab36c9 100644 --- a/lib/IRGen/IRGenDebugInfo.cpp +++ b/lib/IRGen/IRGenDebugInfo.cpp @@ -2469,6 +2469,19 @@ IRGenDebugInfoImpl::emitFunction(const SILDebugScope *DS, llvm::Function *Fn, /*IsLocalToUnit=*/Fn ? Fn->hasInternalLinkage() : true, /*IsDefinition=*/true, /*IsOptimized=*/Opts.shouldOptimize()); + // When the function is a method, we want a DW_AT_declaration there. + // Because there's no good way to cross the CU boundary to insert a nested + // DISubprogram definition in one CU into a type defined in another CU when + // doing LTO builds. + if (Rep == SILFunctionTypeRepresentation::Method) { + llvm::DISubprogram::DISPFlags SPFlags = llvm::DISubprogram::toSPFlags( + /*IsLocalToUnit=*/Fn ? Fn->hasInternalLinkage() : true, + /*IsDefinition=*/false, /*IsOptimized=*/Opts.shouldOptimize()); + Decl = DBuilder.createMethod(Scope, Name, LinkageName, File, Line, DIFnTy, + 0, 0, nullptr, Flags, SPFlags, + TemplateParameters, Error); + } + // Construct the DISubprogram. llvm::DISubprogram *SP = DBuilder.createFunction( Scope, Name, LinkageName, File, Line, DIFnTy, ScopeLine, Flags, SPFlags, diff --git a/test/DebugInfo/method-declaration.swift b/test/DebugInfo/method-declaration.swift new file mode 100644 index 0000000000000..b1fdb35d5dfa0 --- /dev/null +++ b/test/DebugInfo/method-declaration.swift @@ -0,0 +1,37 @@ +// RUN: %target-swift-frontend -primary-file %s -emit-ir -gdwarf-types -o - | %FileCheck %s + +// Verify that we added a declaration for a method. + +// CHECK: define{{.*}}foo_static_method{{.*}} !dbg ![[FOO_STATIC_METHOD_DEF_DBG:[0-9]+]] +// CHECK: define{{.*}}foo_method{{.*}} !dbg ![[FOO_METHOD_DEF_DBG:[0-9]+]] +// CHECK: define{{.*}}bar_static_method{{.*}} !dbg ![[BAR_STATIC_METHOD_DEF_DBG:[0-9]+]] +// CHECK: define{{.*}}bar_method{{.*}} !dbg ![[BAR_METHOD_DEF_DBG:[0-9]+]] +// CHECK: define{{.*}}a_function{{.*}} !dbg ![[FUNC_DEF_DBG:[0-9]+]] + +// CHECK-DAG: ![[FOO_DBG:[0-9]+]] = !DICompositeType(tag: {{.*}} name: "Foo", {{.*}} identifier: +public struct Foo { +// CHECK-DAG: ![[FOO_STATIC_METHOD_DEF_DBG]] = distinct !DISubprogram(name: "foo_static_method"{{.*}}, scope: ![[FOO_DBG]]{{.*}}DISPFlagDefinition{{.*}}, declaration: ![[FOO_STATIC_METHOD_DECL_DBG:[0-9]+]] +// CHECK-DAG: ![[FOO_STATIC_METHOD_DECL_DBG]] = !DISubprogram(name: "foo_static_method"{{.*}}, scope: ![[FOO_DBG]] + static func foo_static_method() {} +// CHECK-DAG: ![[FOO_METHOD_DEF_DBG]] = distinct !DISubprogram(name: "foo_method"{{.*}}, scope: ![[FOO_DBG]]{{.*}}DISPFlagDefinition{{.*}}, declaration: ![[FOO_METHOD_DECL_DBG:[0-9]+]] +// CHECK-DAG: ![[FOO_METHOD_DECL_DBG]] = !DISubprogram(name: "foo_method"{{.*}}, scope: ![[FOO_DBG]] + func foo_method() {} +} + +// CHECK-DAG: ![[BAR_DBG:[0-9]+]] = !DICompositeType(tag: {{.*}} name: "Bar", {{.*}} identifier: +public class Bar { +// CHECK-DAG: ![[BAR_STATIC_METHOD_DEF_DBG]] = distinct !DISubprogram(name: "bar_static_method"{{.*}}, scope: ![[BAR_DBG]]{{.*}}DISPFlagDefinition{{.*}}, declaration: ![[BAR_STATIC_METHOD_DECL_DBG:[0-9]+]] +// CHECK-DAG: ![[BAR_STATIC_METHOD_DECL_DBG]] = !DISubprogram(name: "bar_static_method"{{.*}}, scope: ![[BAR_DBG]] + static func bar_static_method() {} +// CHECK-DAG: ![[BAR_METHOD_DEF_DBG]] = distinct !DISubprogram(name: "bar_method"{{.*}}, scope: ![[BAR_DBG]]{{.*}}DISPFlagDefinition{{.*}}, declaration: ![[BAR_METHOD_DECL_DBG:[0-9]+]] +// CHECK-DAG: ![[BAR_METHOD_DECL_DBG]] = !DISubprogram(name: "bar_method"{{.*}}, scope: ![[BAR_DBG]] + func bar_method() {} +} + +// CHECK: ![[FUNC_DEF_DBG]] = distinct !DISubprogram(name: "a_function" +// CHECK-NOT: declaration +// CHECK-SAME: DISPFlagDefinition +// CHECK-NOT: declaration +// CHECK-SAME: ) +func a_function() {} +