]> granicus.if.org Git - clang/commitdiff
DebugInfo: hoist definition into global context when needed
authorSaleem Abdulrasool <compnerd@compnerd.org>
Sat, 28 Feb 2015 00:13:13 +0000 (00:13 +0000)
committerSaleem Abdulrasool <compnerd@compnerd.org>
Sat, 28 Feb 2015 00:13:13 +0000 (00:13 +0000)
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!

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@230816 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGDebugInfo.cpp
test/CodeGenCXX/inline-dllexport-member.cpp [new file with mode: 0644]

index 6d78ee8754031d951a1cbfcfd48a6e822a4f3419..42d5c3613be59ca47d06fe02324ef3cb0cc53f00 100644 (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");
diff --git a/test/CodeGenCXX/inline-dllexport-member.cpp b/test/CodeGenCXX/inline-dllexport-member.cpp
new file mode 100644 (file)
index 0000000..14634bd
--- /dev/null
@@ -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 ]
+