diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 441135dc90d0..5448d7b1c5db 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1195,6 +1195,15 @@ llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction( MicrosoftVTableContext::MethodVFTableLocation ML = CGM.getMicrosoftVTableContext().getMethodVFTableLocation(GD); VIndex = ML.Index; + + // CodeView only records the vftable offset in the class that introduces + // the virtual method. This is possible because, unlike Itanium, the MS + // C++ ABI does not include all virtual methods from non-primary bases in + // the vtable for the most derived class. For example, if C inherits from + // A and B, C's primary vftable will not include B's virtual methods. + if (Method->begin_overridden_methods() == Method->end_overridden_methods()) + Flags |= llvm::DINode::FlagIntroducedVirtual; + // FIXME: Pass down ML.VFPtrOffset and ML.VBTableIndex. The debugger needs // these to synthesize a call to a virtual method in a complex inheritance // hierarchy. diff --git a/clang/test/CodeGenCXX/debug-info-ms-abi.cpp b/clang/test/CodeGenCXX/debug-info-ms-abi.cpp index 1664da38a8ca..a146ce94176e 100644 --- a/clang/test/CodeGenCXX/debug-info-ms-abi.cpp +++ b/clang/test/CodeGenCXX/debug-info-ms-abi.cpp @@ -10,10 +10,21 @@ struct Foo { }; Foo f; Foo::Nested n; + // CHECK: ![[Foo:[^ ]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", // CHECK-SAME: identifier: ".?AUFoo@@" -// CHECK: !DISubprogram(name: "f", {{.*}} containingType: ![[Foo]], virtuality: DW_VIRTUALITY_virtual, virtualIndex: 0, {{.*}}) -// CHECK: !DISubprogram(name: "g", {{.*}} containingType: ![[Foo]], virtuality: DW_VIRTUALITY_virtual, virtualIndex: 1, {{.*}}) -// CHECK: !DISubprogram(name: "h", {{.*}} containingType: ![[Foo]], virtuality: DW_VIRTUALITY_virtual, virtualIndex: 2, {{.*}}) + +// CHECK: !DISubprogram(name: "f", +// CHECK-SAME: containingType: ![[Foo]], virtuality: DW_VIRTUALITY_virtual, virtualIndex: 0, +// CHECK-SAME: flags: DIFlagPrototyped | DIFlagIntroducedVirtual, + +// CHECK: !DISubprogram(name: "g", +// CHECK-SAME: containingType: ![[Foo]], virtuality: DW_VIRTUALITY_virtual, virtualIndex: 1, +// CHECK-SAME: flags: DIFlagPrototyped | DIFlagIntroducedVirtual, + +// CHECK: !DISubprogram(name: "h", +// CHECK-SAME: containingType: ![[Foo]], virtuality: DW_VIRTUALITY_virtual, virtualIndex: 2, +// CHECK-SAME: flags: DIFlagPrototyped | DIFlagIntroducedVirtual, + // CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Nested", // CHECK-SAME: identifier: ".?AUNested@Foo@@"