DebugInfo: hoist definition into global context when needed

When generating debug info for a static inline member which is initialized for
the DLLExport storage class, hoist the definition into a non-composite type
context. Otherwise, we would trigger an assertion when generating the DIE for
the associated global value as the debug context has a type association. This
addresses PR22669.

Thanks to David Blakie for help in coming up with a solution to this!

llvm-svn: 230816
This commit is contained in:
Saleem Abdulrasool 2015-02-28 00:13:13 +00:00
parent b2e16973df
commit cd187f033e
2 changed files with 22 additions and 3 deletions

View File

@ -2376,9 +2376,17 @@ void CGDebugInfo::collectVarDeclProps(const VarDecl *VD, llvm::DIFile &Unit,
// FIXME: Generalize this for even non-member global variables where the
// declaration and definition may have different lexical decl contexts, once
// we have support for emitting declarations of (non-member) global variables.
VDContext = getContextDescriptor(
dyn_cast<Decl>(VD->isStaticDataMember() ? VD->getLexicalDeclContext()
: VD->getDeclContext()));
const DeclContext *DC = VD->isStaticDataMember() ? VD->getLexicalDeclContext()
: VD->getDeclContext();
// When a record type contains an in-line initialization of a static data
// member, and the record type is marked as __declspec(dllexport), an implicit
// definition of the member will be created in the record context. DWARF
// doesn't seem to have a nice way to describe this in a form that consumers
// are likely to understand, so fake the "normal" situation of a definition
// outside the class by putting it in the global scope.
if (DC->isRecord())
DC = CGM.getContext().getTranslationUnitDecl();
VDContext = getContextDescriptor(dyn_cast<Decl>(DC));
}
llvm::DISubprogram
@ -3171,6 +3179,7 @@ llvm::DIDerivedType
CGDebugInfo::getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D) {
if (!D->isStaticDataMember())
return llvm::DIDerivedType();
auto MI = StaticDataMemberCache.find(D->getCanonicalDecl());
if (MI != StaticDataMemberCache.end()) {
assert(MI->second && "Static data member declaration should still exist");

View File

@ -0,0 +1,10 @@
// RUN: %clang_cc1 -triple i686-windows-gnu -fms-compatibility -g -emit-llvm %s -o - \
// RUN: | FileCheck %s
struct __declspec(dllexport) s {
static const unsigned int ui = 0;
};
// CHECK: , [[SCOPE:![^,]*]], {{.*}}, i32* @_ZN1s2uiE, {{.*}}} ; [ DW_TAG_variable ] [ui] [line 5] [def]
// CHECK: [[SCOPE]] = {{.*}} ; [ DW_TAG_file_type ]