Skip to content

Commit e0cabe2

Browse files
committed
Debug info: Emit objc_direct methods as members of their containing class
even in DWARF 4 and earlier. This allows the debugger to recognize them as direct functions as opposed to Objective-C methods. <rdar://problem/57327663> Differential Revision: https://reviews.llvm.org/D70544
1 parent ab41180 commit e0cabe2

File tree

3 files changed

+50
-24
lines changed

3 files changed

+50
-24
lines changed

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3495,14 +3495,15 @@ llvm::DISubprogram *CGDebugInfo::getObjCMethodDeclaration(
34953495
if (!D || DebugKind <= codegenoptions::DebugLineTablesOnly)
34963496
return nullptr;
34973497

3498-
if (CGM.getCodeGenOpts().DwarfVersion < 5)
3498+
const auto *OMD = dyn_cast<ObjCMethodDecl>(D);
3499+
if (!OMD)
3500+
return nullptr;
3501+
3502+
if (CGM.getCodeGenOpts().DwarfVersion < 5 && !OMD->isDirectMethod())
34993503
return nullptr;
35003504

35013505
// Starting with DWARF V5 method declarations are emitted as children of
35023506
// the interface type.
3503-
const auto *OMD = dyn_cast<ObjCMethodDecl>(D);
3504-
if (!OMD)
3505-
return nullptr;
35063507
auto *ID = dyn_cast_or_null<ObjCInterfaceDecl>(D->getDeclContext());
35073508
if (!ID)
35083509
ID = OMD->getClassInterface();
@@ -3517,7 +3518,7 @@ llvm::DISubprogram *CGDebugInfo::getObjCMethodDeclaration(
35173518
InterfaceType, getObjCMethodName(OMD), StringRef(),
35183519
InterfaceType->getFile(), LineNo, FnType, LineNo, Flags, SPFlags);
35193520
DBuilder.finalizeSubprogram(FD);
3520-
ObjCMethodCache[ID].push_back(FD);
3521+
ObjCMethodCache[ID].push_back({FD, OMD->isDirectMethod()});
35213522
return FD;
35223523
}
35233524

@@ -4713,27 +4714,28 @@ void CGDebugInfo::finalize() {
47134714
DBuilder.replaceTemporary(llvm::TempDIType(E.Decl), Ty);
47144715
}
47154716

4716-
if (CGM.getCodeGenOpts().DwarfVersion >= 5) {
4717-
// Add methods to interface.
4718-
for (const auto &P : ObjCMethodCache) {
4719-
if (P.second.empty())
4720-
continue;
4717+
// Add methods to interface.
4718+
for (const auto &P : ObjCMethodCache) {
4719+
if (P.second.empty())
4720+
continue;
47214721

4722-
QualType QTy(P.first->getTypeForDecl(), 0);
4723-
auto It = TypeCache.find(QTy.getAsOpaquePtr());
4724-
assert(It != TypeCache.end());
4722+
QualType QTy(P.first->getTypeForDecl(), 0);
4723+
auto It = TypeCache.find(QTy.getAsOpaquePtr());
4724+
assert(It != TypeCache.end());
47254725

4726-
llvm::DICompositeType *InterfaceDecl =
4727-
cast<llvm::DICompositeType>(It->second);
4726+
llvm::DICompositeType *InterfaceDecl =
4727+
cast<llvm::DICompositeType>(It->second);
47284728

4729-
SmallVector<llvm::Metadata *, 16> EltTys;
4730-
auto CurrenetElts = InterfaceDecl->getElements();
4731-
EltTys.append(CurrenetElts.begin(), CurrenetElts.end());
4732-
for (auto &MD : P.second)
4733-
EltTys.push_back(MD);
4734-
llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys);
4735-
DBuilder.replaceArrays(InterfaceDecl, Elements);
4736-
}
4729+
auto CurElts = InterfaceDecl->getElements();
4730+
SmallVector<llvm::Metadata *, 16> EltTys(CurElts.begin(), CurElts.end());
4731+
4732+
// For DWARF v4 or earlier, only add objc_direct methods.
4733+
for (auto &SubprogramDirect : P.second)
4734+
if (CGM.getCodeGenOpts().DwarfVersion >= 5 || SubprogramDirect.getInt())
4735+
EltTys.push_back(SubprogramDirect.getPointer());
4736+
4737+
llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys);
4738+
DBuilder.replaceArrays(InterfaceDecl, Elements);
47374739
}
47384740

47394741
for (const auto &P : ReplaceMap) {

clang/lib/CodeGen/CGDebugInfo.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,10 @@ class CGDebugInfo {
114114
llvm::SmallVector<ObjCInterfaceCacheEntry, 32> ObjCInterfaceCache;
115115

116116
/// Cache of forward declarations for methods belonging to the interface.
117-
llvm::DenseMap<const ObjCInterfaceDecl *, std::vector<llvm::DISubprogram *>>
117+
/// The extra bit on the DISubprogram specifies whether a method is
118+
/// "objc_direct".
119+
llvm::DenseMap<const ObjCInterfaceDecl *,
120+
std::vector<llvm::PointerIntPair<llvm::DISubprogram *, 1>>>
118121
ObjCMethodCache;
119122

120123
/// Cache of references to clang modules and precompiled headers.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %clang_cc1 -dwarf-version=5 -emit-llvm -debug-info-kind=limited -w -triple x86_64-apple-darwin10 %s -o - | FileCheck %s
2+
// RUN: %clang_cc1 -dwarf-version=4 -emit-llvm -debug-info-kind=limited -w -triple x86_64-apple-darwin10 %s -o - | FileCheck %s
3+
4+
__attribute__((objc_root_class))
5+
@interface Root
6+
@end
7+
8+
@implementation Root
9+
- (int)getInt __attribute__((objc_direct)) {
10+
return 42;
11+
}
12+
@end
13+
14+
// Test that objc_direct methods are always (even in DWARF < 5) emitted
15+
// as members of their containing class.
16+
17+
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Root",
18+
// CHECK-SAME: elements: ![[MEMBERS:[0-9]+]],
19+
// CHECK-SAME: runtimeLang: DW_LANG_ObjC)
20+
// CHECK: ![[MEMBERS]] = !{![[GETTER:[0-9]+]]}
21+
// CHECK: ![[GETTER]] = !DISubprogram(name: "-[Root getInt]",

0 commit comments

Comments
 (0)