From 29dbb7b2421c7631bf4e86948c3536700e2ca447 Mon Sep 17 00:00:00 2001
From: Adrian Prantl <aprantl@apple.com>
Date: Wed, 20 Apr 2016 23:59:32 +0000
Subject: [PATCH] Module Debugging: Emit the canonical debug info for
 Objective-C classes in the compile unit that contains their implementation
 even if their interface is declared in a module.

The private @implementation of an @interface may have additional
hidden ivars so we should not defer to the public version of the
type that is found in the module.

<rdar://problem/25541798>

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@266937 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/CodeGen/CGDebugInfo.cpp     |  7 +++++--
 test/Modules/ExtDebugInfo.m     | 14 +++++++++++++-
 test/Modules/Inputs/DebugObjC.h |  6 ++++++
 test/Modules/ModuleDebugInfo.m  |  7 +++++--
 4 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 0c61496162a..9e8abdc2f5c 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -1664,8 +1664,11 @@ llvm::DIType *CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
   if (!ID)
     return nullptr;
 
-  // Return a forward declaration if this type was imported from a clang module.
-  if (DebugTypeExtRefs && ID->isFromASTFile() && ID->getDefinition())
+  // Return a forward declaration if this type was imported from a clang module,
+  // and this is not the compile unit with the implementation of the type (which
+  // may contain hidden ivars).
+  if (DebugTypeExtRefs && ID->isFromASTFile() && ID->getDefinition() &&
+      !ID->getImplementation())
     return DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
                                       ID->getName(),
                                       getDeclContextDescriptor(ID), Unit, 0);
diff --git a/test/Modules/ExtDebugInfo.m b/test/Modules/ExtDebugInfo.m
index 3b907ac729a..71ca853fb7d 100644
--- a/test/Modules/ExtDebugInfo.m
+++ b/test/Modules/ExtDebugInfo.m
@@ -18,6 +18,11 @@
 @import DebugObjC;
 #endif
 
+@implementation ObjCClassWithPrivateIVars {
+  int hidden_ivar;
+}
+@end
+
 TypedefUnion tdu;
 TypedefEnum tde;
 TypedefStruct tds;
@@ -29,9 +34,16 @@ int foo(ObjCClass *c) {
   return [c property];
 }
 
+// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "ObjCClassWithPrivateIVars",
+// CHECK-SAME:             flags: DIFlagObjcClassComplete
+
+// CHECK: ![[MOD:.*]] = !DIModule(scope: null, name: "DebugObjC
+
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "hidden_ivar",
+// CHECK-SAME:           flags: DIFlagPrivate)
+
 // CHECK: !DIGlobalVariable(name: "GlobalUnion",
 // CHECK-SAME:              type: ![[GLOBAL_UNION:[0-9]+]]
-// CHECK: ![[MOD:.*]] = !DIModule(scope: null, name: "DebugObjC
 // CHECK: ![[GLOBAL_UNION]] = distinct !DICompositeType(tag: DW_TAG_union_type,
 // CHECK-SAME:                elements: !{{[0-9]+}})
 
diff --git a/test/Modules/Inputs/DebugObjC.h b/test/Modules/Inputs/DebugObjC.h
index eb7a9f9da9f..af1cd981ce1 100644
--- a/test/Modules/Inputs/DebugObjC.h
+++ b/test/Modules/Inputs/DebugObjC.h
@@ -1,3 +1,4 @@
+// -*- ObjC -*-
 @class FwdDecl;
 
 @interface ObjCClass {
@@ -9,6 +10,11 @@
 @property int property;
 @end
 
+@interface ObjCClassWithPrivateIVars {
+  int public_ivar;
+}
+@end
+
 @interface ObjCClass (Category)
 - categoryMethod;
 @end
diff --git a/test/Modules/ModuleDebugInfo.m b/test/Modules/ModuleDebugInfo.m
index 360db919ab9..ce35c7c8361 100644
--- a/test/Modules/ModuleDebugInfo.m
+++ b/test/Modules/ModuleDebugInfo.m
@@ -33,13 +33,13 @@
 // CHECK: ![[TD_ENUM:.*]] = !DICompositeType(tag: DW_TAG_enumeration_type,
 // CHECK-NOT:              name:
 // CHECK-SAME:             elements:
-// CHECK-SAME:             )
 
 // CHECK: !DISubprogram(name: "+[ObjCClass classMethod]",
 // CHECK-SAME:          scope: ![[MODULE]],
 
 // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "ObjCClass",
 // CHECK-SAME:             scope: ![[MODULE]],
+// CHECK-SAME:             elements
 
 // The forward declaration should not be in the module scope.
 // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "OpaqueData", file
@@ -47,13 +47,16 @@
 // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "FwdDecl",
 // CHECK-SAME:             scope: ![[MODULE]],
 
+// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "ObjCClassWithPrivateIVars",
+// CHECK-SAME:             scope: ![[MODULE]],
+// CHECK-SAME:             elements
+
 // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "FwdDeclared"
 // CHECK-SAME:             elements:
 
 // CHECK: ![[TD_UNION:.*]] = distinct !DICompositeType(tag: DW_TAG_union_type,
 // CHECK-NOT:              name:
 // CHECK-SAME:             elements:
-// CHECK-SAME:             )
 
 // CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "TypedefUnion",
 // CHECK-SAME:           baseType: ![[TD_UNION]])
-- 
GitLab