Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -3569,7 +3569,24 @@ if (Name.startswith("\01")) Name = Name.substr(1); - if (!HasDecl || D->isImplicit() || D->hasAttr()) { + bool Artificial = !HasDecl || D->isImplicit() || D->hasAttr(); + if (!Artificial) + Artificial = isa(D) && + (GD.getDynamicInitKind() == DynamicInitKind::Initializer || + GD.getDynamicInitKind() == DynamicInitKind::AtExit); + if (!Artificial) { + // Look up the lexical stack see if we're already into an artificial + // subprogram. + llvm::DILocalScope *PrevScope = + !LexicalBlockStack.empty() + ? dyn_cast(LexicalBlockStack.back()) + : nullptr; + llvm::DISubprogram *PrevSP = + PrevScope ? PrevScope->getSubprogram() : nullptr; + Artificial = PrevSP && (PrevSP->getFlags() & llvm::DINode::FlagArtificial); + } + + if (Artificial) { Flags |= llvm::DINode::FlagArtificial; // Artificial functions should not silently reuse CurLoc. CurLoc = SourceLocation(); Index: lib/CodeGen/CGDeclCXX.cpp =================================================================== --- lib/CodeGen/CGDeclCXX.cpp +++ lib/CodeGen/CGDeclCXX.cpp @@ -247,6 +247,8 @@ CGF.StartFunction(GlobalDecl(&VD, DynamicInitKind::AtExit), CGM.getContext().VoidTy, fn, FI, FunctionArgList()); + // Emit an artificial location for this function. + auto AL = ApplyDebugLocation::CreateArtificial(CGF); llvm::CallInst *call = CGF.Builder.CreateCall(dtor, addr); @@ -642,8 +644,9 @@ StartFunction(GlobalDecl(D, DynamicInitKind::Initializer), getContext().VoidTy, Fn, getTypes().arrangeNullaryFunction(), - FunctionArgList(), D->getLocation(), - D->getInit()->getExprLoc()); + FunctionArgList()); + // Emit an artificial location for this function. + auto AL = ApplyDebugLocation::CreateArtificial(*this); // Use guarded initialization if the global variable is weak. This // occurs for, e.g., instantiated static data members and @@ -769,6 +772,8 @@ CurEHLocation = VD->getBeginLoc(); StartFunction(VD, getContext().VoidTy, fn, FI, args); + // Emit an artificial location for this function. + auto AL = ApplyDebugLocation::CreateArtificial(*this); emitDestroy(addr, type, destroyer, useEHCleanupForArray); Index: test/CodeGenCXX/debug-info-atexit-stub.cpp =================================================================== --- test/CodeGenCXX/debug-info-atexit-stub.cpp +++ test/CodeGenCXX/debug-info-atexit-stub.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -emit-llvm %s -triple x86_64-windows-msvc -gcodeview -debug-info-kind=limited -o - | FileCheck %s + +struct a { + ~a(); +}; +template struct c : a { + c(void (b::*)()); +}; +struct B { + virtual void e(); +}; +c *d() { static c f(&B::e); return &f; } + +// CHECK: define internal void @"??__Ff@?1??d@@YAPEAU?$c@UB@@@@XZ@YAXXZ"() +// CHECK-SAME: !dbg ![[SUBPROGRAM:[0-9]+]] { +// CHECK: call void @"??1?$c@UB@@@@QEAA@XZ"(%struct.c* @"?f@?1??d@@YAPEAU?$c@UB@@@@XZ@4U2@A"), !dbg ![[LOCATION:[0-9]+]] +// CHECK-NEXT: ret void, !dbg ![[LOCATION]] +// CHECK: ![[SUBPROGRAM]] = distinct !DISubprogram(name: "`dynamic atexit destructor for 'f'" +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: ![[LOCATION]] = !DILocation(line: 0, scope: ![[SUBPROGRAM]]) \ No newline at end of file Index: test/CodeGenCXX/debug-info-destroy-helper.cpp =================================================================== --- test/CodeGenCXX/debug-info-destroy-helper.cpp +++ test/CodeGenCXX/debug-info-destroy-helper.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -emit-llvm %s -triple x86_64-windows-msvc -gcodeview -debug-info-kind=limited -o - | FileCheck %s + +struct b { + b(char *); + ~b(); +}; +struct a { + ~a(); +}; +struct { + b c; + const a &d; +} e[]{nullptr, {}}; + +// CHECK: define internal void @__cxx_global_array_dtor(i8* %0) +// CHECK-SAME: !dbg ![[SUBPROGRAM:[0-9]+]] { +// CHECK: arraydestroy.body +// CHECK: %arraydestroy.elementPast = +// CHECK-SAME: !dbg ![[LOCATION:[0-9]+]] +// CHECK: call void @"??1@@QEAA@XZ"(%struct.anon* %arraydestroy.element) +// CHECK-SAME: !dbg ![[LOCATION]] +// CHECK: ![[SUBPROGRAM]] = distinct !DISubprogram(name: "__cxx_global_array_dtor" +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: ![[LOCATION]] = !DILocation(line: 0, Index: test/CodeGenCXX/debug-info-global-ctor-dtor.cpp =================================================================== --- test/CodeGenCXX/debug-info-global-ctor-dtor.cpp +++ test/CodeGenCXX/debug-info-global-ctor-dtor.cpp @@ -29,25 +29,26 @@ A FooTpl::sdm_tpl(sizeof(U) + sizeof(T)); template A FooTpl::sdm_tpl; -// CHECK-NOKEXT: !DISubprogram(name: "__cxx_global_var_init",{{.*}} line: 15,{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK-NOKEXT: !DISubprogram(name: "__dtor_glob",{{.*}} line: 15,{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK-NOKEXT: !DISubprogram(name: "__cxx_global_var_init.1",{{.*}} line: 16,{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK-NOKEXT: !DISubprogram(name: "__cxx_global_array_dtor",{{.*}} line: 16,{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK-NOKEXT: !DISubprogram(name: "__dtor_array",{{.*}} line: 16,{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK-NOKEXT: !DISubprogram(name: "__dtor__ZZ3foovE4stat",{{.*}} line: 19,{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-NOKEXT: !DISubprogram(name: "__cxx_global_var_init",{{.*}} flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-NOKEXT: !DISubprogram(name: "__dtor_glob",{{.*}} flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-NOKEXT: !DISubprogram(name: "__cxx_global_var_init.1",{{.*}} flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-NOKEXT: !DISubprogram(name: "__cxx_global_array_dtor",{{.*}} flags: DIFlagArtificial | DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-NOKEXT: !DISubprogram(name: "__dtor_array",{{.*}} flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-NOKEXT: !DISubprogram(name: "__dtor__ZZ3foovE4stat",{{.*}} flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition // CHECK-NOKEXT: !DISubprogram({{.*}} DISPFlagLocalToUnit | DISPFlagDefinition // CHECK-KEXT: !DISubprogram({{.*}} DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK-MSVC: !DISubprogram(name: "`dynamic initializer for 'glob'",{{.*}} line: 15,{{.*}}: DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK-MSVC: !DISubprogram(name: "`dynamic atexit destructor for 'glob'",{{.*}} line: 15,{{.*}}: DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK-MSVC: !DISubprogram(name: "`dynamic initializer for 'array'",{{.*}} line: 16,{{.*}}: DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK-MSVC: !DISubprogram(name: "__cxx_global_array_dtor",{{.*}} line: 16,{{.*}}: DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK-MSVC: !DISubprogram(name: "`dynamic atexit destructor for 'array'",{{.*}} line: 16,{{.*}}: DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK-MSVC: !DISubprogram(name: "`dynamic atexit destructor for 'stat'",{{.*}} line: 19,{{.*}}: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-MSVC: !DISubprogram(name: "`dynamic initializer for 'glob'",{{.*}} flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-MSVC: !DISubprogram(name: "`dynamic atexit destructor for 'glob'",{{.*}} flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-MSVC: !DISubprogram(name: "`dynamic initializer for 'array'",{{.*}} flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-MSVC: !DISubprogram(name: "__cxx_global_array_dtor",{{.*}} flags: DIFlagArtificial | DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-MSVC: !DISubprogram(name: "`dynamic atexit destructor for 'array'",{{.*}} flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-MSVC: !DISubprogram(name: "`dynamic atexit destructor for 'stat'",{{.*}} flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition // MSVC does weird stuff when templates are involved, so we don't match exactly, // but these names are reasonable. // FIXME: These should not be marked DISPFlagLocalToUnit. -// CHECK-MSVC: !DISubprogram(name: "FooTpl::`dynamic initializer for 'sdm_tpl'",{{.*}} line: 29,{{.*}}: DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK-MSVC: !DISubprogram(name: "FooTpl::`dynamic atexit destructor for 'sdm_tpl'",{{.*}} line: 29,{{.*}}: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-MSVC: !DISubprogram(name: "FooTpl::`dynamic initializer for 'sdm_tpl'",{{.*}} flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-MSVC: !DISubprogram(name: "FooTpl::`dynamic atexit destructor for 'sdm_tpl'",{{.*}} flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-MSVC: !DISubprogram(linkageName: "_GLOBAL__sub_I_debug_info_global_ctor_dtor.cpp",{{.*}} flags: DIFlagArtificial \ No newline at end of file Index: test/CodeGenCXX/debug-info-line.cpp =================================================================== --- test/CodeGenCXX/debug-info-line.cpp +++ test/CodeGenCXX/debug-info-line.cpp @@ -314,7 +314,7 @@ // CHECK: [[DBG_F9]] = !DILocation(line: 1000, // CHECK: [[DBG_F10_STORE]] = !DILocation(line: 1100, // CHECK: [[DBG_GLBL_CTOR_B]] = !DILocation(line: 1200, -// CHECK: [[DBG_GLBL_DTOR_B]] = !DILocation(line: 1200, +// CHECK: [[DBG_GLBL_DTOR_B]] = !DILocation(line: 0, // CHECK: [[DBG_F11]] = !DILocation(line: 1300, // CHECK: [[DBG_F12]] = !DILocation(line: 1400, // CHECK: [[DBG_F13]] = !DILocation(line: 1500,