Index: lib/CodeGen/CGDebugInfo.h =================================================================== --- lib/CodeGen/CGDebugInfo.h +++ lib/CodeGen/CGDebugInfo.h @@ -15,12 +15,14 @@ #define LLVM_CLANG_LIB_CODEGEN_CGDEBUGINFO_H #include "CGBuilder.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" #include "clang/AST/ExternalASTSource.h" #include "clang/AST/Type.h" #include "clang/Basic/SourceLocation.h" #include "clang/Frontend/CodeGenOptions.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/Optional.h" #include "llvm/IR/DIBuilder.h" #include "llvm/IR/DebugInfo.h" @@ -32,7 +34,6 @@ } namespace clang { -class CXXMethodDecl; class ClassTemplateSpecializationDecl; class GlobalDecl; class ModuleMap; @@ -218,6 +219,15 @@ SmallVectorImpl &EltTys, llvm::DIType *RecordTy); + /// Helper function for CollectCXXBases. + /// Adds debug info entries for types in Bases that are not in SeenTypes. + void CollectCXXBasesAux(const CXXRecordDecl *RD, llvm::DIFile *Unit, + SmallVectorImpl &EltTys, + llvm::DIType *RecordTy, + const CXXRecordDecl::base_class_const_range &Bases, + llvm::DenseSet &SeenTypes, + llvm::DINode::DIFlags StartingFlags); + /// A helper function to collect template parameters. llvm::DINodeArray CollectTemplateParams(const TemplateParameterList *TPList, ArrayRef TAList, Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -13,9 +13,9 @@ #include "CGDebugInfo.h" #include "CGBlocks.h" -#include "CGRecordLayout.h" #include "CGCXXABI.h" #include "CGObjCRuntime.h" +#include "CGRecordLayout.h" #include "CodeGenFunction.h" #include "CodeGenModule.h" #include "clang/AST/ASTContext.h" @@ -31,6 +31,7 @@ #include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/ModuleMap.h" #include "clang/Lex/PreprocessorOptions.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/IR/Constants.h" @@ -1366,37 +1367,61 @@ void CGDebugInfo::CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile *Unit, SmallVectorImpl &EltTys, llvm::DIType *RecordTy) { + llvm::DenseSet SeenTypes; + CollectCXXBasesAux(RD, Unit, EltTys, RecordTy, RD->bases(), SeenTypes, + llvm::DINode::FlagZero); + + // If we are generating CodeView debug info, we also need to emit records for + // indirect virtual base classes. + if (CGM.getTarget().getCXXABI().isMicrosoft()) { + CollectCXXBasesAux(RD, Unit, EltTys, RecordTy, RD->vbases(), SeenTypes, + llvm::DINode::FlagIndirect | llvm::DINode::FlagVirtual); + } +} + +void CGDebugInfo::CollectCXXBasesAux( + const CXXRecordDecl *RD, llvm::DIFile *Unit, + SmallVectorImpl &EltTys, llvm::DIType *RecordTy, + const CXXRecordDecl::base_class_const_range &Bases, + llvm::DenseSet &SeenTypes, + llvm::DINode::DIFlags StartingFlags) { const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); - for (const auto &BI : RD->bases()) { - llvm::DINode::DIFlags BFlags = llvm::DINode::FlagZero; + const auto cxxABI = CGM.getTarget().getCXXABI(); + for (const auto &BI : Bases) { + auto *BaseTy = getOrCreateType(BI.getType(), Unit); + if (SeenTypes.find(BaseTy) != SeenTypes.end()) + continue; + llvm::DINode::DIFlags BFlags = StartingFlags; uint64_t BaseOffset; const auto *Base = cast(BI.getType()->getAs()->getDecl()); if (BI.isVirtual()) { - if (CGM.getTarget().getCXXABI().isItaniumFamily()) { + if (cxxABI.isItaniumFamily()) { // virtual base offset offset is -ve. The code generator emits dwarf // expression where it expects +ve number. - BaseOffset = 0 - CGM.getItaniumVTableContext() - .getVirtualBaseOffsetOffset(RD, Base) - .getQuantity(); + BaseOffset = 0 - + CGM.getItaniumVTableContext() + .getVirtualBaseOffsetOffset(RD, Base) + .getQuantity(); } else { // In the MS ABI, store the vbtable offset, which is analogous to the // vbase offset offset in Itanium. BaseOffset = 4 * CGM.getMicrosoftVTableContext().getVBTableIndex(RD, Base); } - BFlags = llvm::DINode::FlagVirtual; + BFlags |= llvm::DINode::FlagVirtual; } else BaseOffset = CGM.getContext().toBits(RL.getBaseClassOffset(Base)); // FIXME: Inconsistent units for BaseOffset. It is in bytes when // BI->isVirtual() and bits when not. BFlags |= getAccessFlag(BI.getAccessSpecifier(), RD); - llvm::DIType *DTy = DBuilder.createInheritance( - RecordTy, getOrCreateType(BI.getType(), Unit), BaseOffset, BFlags); + llvm::DIType *DTy = + DBuilder.createInheritance(RecordTy, BaseTy, BaseOffset, BFlags); EltTys.push_back(DTy); + SeenTypes.insert(BaseTy); } } Index: test/CodeGenCXX/debug-info-ms-vbase.cpp =================================================================== --- test/CodeGenCXX/debug-info-ms-vbase.cpp +++ test/CodeGenCXX/debug-info-ms-vbase.cpp @@ -24,6 +24,18 @@ // CHECK: ![[HasVirtualMethod_base]] = !DIDerivedType(tag: DW_TAG_inheritance, scope: ![[HasPrimaryBase]], baseType: ![[HasVirtualMethod]]) +// CHECK: ![[HasIndirectVirtualBase:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "HasIndirectVirtualBase" +// CHECK-SAME: elements: ![[elements:[0-9]+]] + +// CHECK: !DIDerivedType(tag: DW_TAG_inheritance, scope: ![[HasIndirectVirtualBase]], baseType: ![[HasPrimaryBase]] +// CHECK-NOT: DIFlagIndirect +// CHECK-SAME: ) + +// CHECK: !DIDerivedType(tag: DW_TAG_inheritance, scope: ![[HasIndirectVirtualBase]], baseType: ![[SecondaryVTable]] +// CHECK-SAME: flags: +// CHECK-SAME: DIFlagVirtual +// CHECK-SAME: DIFlagIndirect + // CHECK: ![[DynamicNoVFPtr:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "DynamicNoVFPtr", // CHECK-SAME: elements: ![[elements:[0-9]+]] @@ -52,3 +64,6 @@ HasPrimaryBase has_primary_base; +struct HasIndirectVirtualBase : public HasPrimaryBase { }; + +HasIndirectVirtualBase has_indirect_virtual_base;