From 2834af3e6238ff837ec4b020e1f749535cd228e1 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Mon, 30 Jan 2017 06:36:08 +0000 Subject: [PATCH] Reapply "DebugInfo: Omit class definitions even in the presence of available_externally vtables" Accounts for a case that caused an assertion failure by attempting to query for the vtable linkage of a non-dynamic type.t This reverts commit r292801. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@293462 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGDebugInfo.cpp | 30 ++++++++++++++------- lib/CodeGen/CGDebugInfo.h | 1 + lib/CodeGen/CGVTables.cpp | 7 ++--- test/CodeGenCXX/debug-info-class-optzns.cpp | 26 ++++++++++++++++++ 4 files changed, 51 insertions(+), 13 deletions(-) create mode 100644 test/CodeGenCXX/debug-info-class-optzns.cpp diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index c177a24162..b58afaaa60 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -1714,7 +1714,27 @@ void CGDebugInfo::completeType(const RecordDecl *RD) { completeRequiredType(RD); } +/// Return true if the class or any of its methods are marked dllimport. +static bool isClassOrMethodDLLImport(const CXXRecordDecl *RD) { + if (RD->hasAttr()) + return true; + for (const CXXMethodDecl *MD : RD->methods()) + if (MD->hasAttr()) + return true; + return false; +} + void CGDebugInfo::completeClassData(const RecordDecl *RD) { + if (auto *CXXRD = dyn_cast(RD)) + if (CXXRD->isDynamicClass() && + CGM.getVTableLinkage(CXXRD) == + llvm::GlobalValue::AvailableExternallyLinkage && + !isClassOrMethodDLLImport(CXXRD)) + return; + completeClass(RD); +} + +void CGDebugInfo::completeClass(const RecordDecl *RD) { if (DebugKind <= codegenoptions::DebugLineTablesOnly) return; QualType Ty = CGM.getContext().getRecordType(RD); @@ -1760,16 +1780,6 @@ static bool isDefinedInClangModule(const RecordDecl *RD) { return true; } -/// Return true if the class or any of its methods are marked dllimport. -static bool isClassOrMethodDLLImport(const CXXRecordDecl *RD) { - if (RD->hasAttr()) - return true; - for (const CXXMethodDecl *MD : RD->methods()) - if (MD->hasAttr()) - return true; - return false; -} - static bool shouldOmitDefinition(codegenoptions::DebugInfoKind DebugKind, bool DebugTypeExtRefs, const RecordDecl *RD, const LangOptions &LangOpts) { diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index ac2e8dd2e0..ea451d0548 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -409,6 +409,7 @@ public: void completeType(const RecordDecl *RD); void completeRequiredType(const RecordDecl *RD); void completeClassData(const RecordDecl *RD); + void completeClass(const RecordDecl *RD); void completeTemplateDefinition(const ClassTemplateSpecializationDecl &SD); diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp index 04c5cfe536..24c7f15a08 100644 --- a/lib/CodeGen/CGVTables.cpp +++ b/lib/CodeGen/CGVTables.cpp @@ -744,9 +744,10 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) { switch (keyFunction->getTemplateSpecializationKind()) { case TSK_Undeclared: case TSK_ExplicitSpecialization: - assert((def || CodeGenOpts.OptimizationLevel > 0) && - "Shouldn't query vtable linkage without key function or " - "optimizations"); + assert((def || CodeGenOpts.OptimizationLevel > 0 || + CodeGenOpts.getDebugInfo() != codegenoptions::NoDebugInfo) && + "Shouldn't query vtable linkage without key function, " + "optimizations, or debug info"); if (!def && CodeGenOpts.OptimizationLevel > 0) return llvm::GlobalVariable::AvailableExternallyLinkage; diff --git a/test/CodeGenCXX/debug-info-class-optzns.cpp b/test/CodeGenCXX/debug-info-class-optzns.cpp new file mode 100644 index 0000000000..d58510b715 --- /dev/null +++ b/test/CodeGenCXX/debug-info-class-optzns.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -triple x86_64-unknown_unknown -emit-llvm -debug-info-kind=limited %s -O1 -o - | FileCheck %s + +// Ensure class definitions are not emitted to debug info just because the +// vtable is emitted for optimization purposes (as available_externally). The +// class definition debug info should only go where the vtable is actually +// emitted into the object file. + +// CHECK: @_ZTV3foo = available_externally + +// Verify that this doesn't involve querying for the vtable of types that aren't +// dynamic (that would cause an assertion in the case below) + +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "bar" +template struct bar {}; +extern template struct bar; +bar *p1; +bar a; + +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "foo" +// CHECK-SAME: DIFlagFwdDecl + +struct foo { + virtual void f(); +}; + +foo f; -- 2.40.0