From: Bob Haarman Date: Tue, 25 Oct 2016 22:19:32 +0000 (+0000) Subject: [codeview] emit debug info for indirect virtual base classes X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6ffe5365235b91e800680d854f2d946312abe004;p=clang [codeview] emit debug info for indirect virtual base classes Summary: Fixes PR28281. MSVC lists indirect virtual base classes in the field list of a class. This change makes Clang emit the information necessary for LLVM to emit such records. Reviewers: rnk, ruiu, zturner Differential Revision: https://reviews.llvm.org/D25579 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@285132 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 9b623d7443..6a6b83e331 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/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" @@ -1380,13 +1381,33 @@ void CGDebugInfo::CollectCXXMemberFunctions( void CGDebugInfo::CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile *Unit, SmallVectorImpl &EltTys, llvm::DIType *RecordTy) { - const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); - for (const auto &BI : RD->bases()) { - llvm::DINode::DIFlags BFlags = llvm::DINode::FlagZero; - uint64_t BaseOffset; + 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.getCodeGenOpts().EmitCodeView) { + CollectCXXBasesAux(RD, Unit, EltTys, RecordTy, RD->vbases(), SeenTypes, + llvm::DINode::FlagIndirectVirtualBase); + } +} +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 : Bases) { const auto *Base = cast(BI.getType()->getAs()->getDecl()); + if (!SeenTypes.insert(Base).second) + continue; + auto *BaseTy = getOrCreateType(BI.getType(), Unit); + llvm::DINode::DIFlags BFlags = StartingFlags; + uint64_t BaseOffset; if (BI.isVirtual()) { if (CGM.getTarget().getCXXABI().isItaniumFamily()) { @@ -1401,15 +1422,15 @@ void CGDebugInfo::CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile *Unit, 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); } } diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index d2af9be9b6..f43261a47d 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/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 @@ class MDNode; } namespace clang { -class CXXMethodDecl; class ClassTemplateSpecializationDecl; class GlobalDecl; class ModuleMap; @@ -218,6 +219,15 @@ class CGDebugInfo { 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, diff --git a/test/CodeGenCXX/debug-info-ms-vbase.cpp b/test/CodeGenCXX/debug-info-ms-vbase.cpp index 1590657d81..3de3a751cb 100644 --- a/test/CodeGenCXX/debug-info-ms-vbase.cpp +++ b/test/CodeGenCXX/debug-info-ms-vbase.cpp @@ -24,6 +24,17 @@ // 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: DIFlagIndirectVirtualBase +// CHECK-SAME: ) + +// CHECK: !DIDerivedType(tag: DW_TAG_inheritance, scope: ![[HasIndirectVirtualBase]], baseType: ![[SecondaryVTable]] +// CHECK-SAME: flags: +// CHECK-SAME: DIFlagIndirectVirtualBase + // CHECK: ![[DynamicNoVFPtr:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "DynamicNoVFPtr", // CHECK-SAME: elements: ![[elements:[0-9]+]] @@ -52,3 +63,6 @@ struct HasPrimaryBase : virtual SecondaryVTable, HasVirtualMethod { }; HasPrimaryBase has_primary_base; +struct HasIndirectVirtualBase : public HasPrimaryBase {}; + +HasIndirectVirtualBase has_indirect_virtual_base;