[clang] e0cabe2 - Debug info: Emit objc_direct methods as members of their containing class
Adrian Prantl via cfe-commits
cfe-commits at lists.llvm.org
Thu Nov 21 11:01:19 PST 2019
Author: Adrian Prantl
Date: 2019-11-21T11:01:10-08:00
New Revision: e0cabe280b80ab71045d90b2d6f1a70e5d4c5d05
URL: https://github.com/llvm/llvm-project/commit/e0cabe280b80ab71045d90b2d6f1a70e5d4c5d05
DIFF: https://github.com/llvm/llvm-project/commit/e0cabe280b80ab71045d90b2d6f1a70e5d4c5d05.diff
LOG: 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
Added:
clang/test/CodeGenObjC/debug-info-direct-method.m
Modified:
clang/lib/CodeGen/CGDebugInfo.cpp
clang/lib/CodeGen/CGDebugInfo.h
Removed:
################################################################################
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index a9b3831aa0b5..a8d4ed12808e 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -3495,14 +3495,15 @@ llvm::DISubprogram *CGDebugInfo::getObjCMethodDeclaration(
if (!D || DebugKind <= codegenoptions::DebugLineTablesOnly)
return nullptr;
- if (CGM.getCodeGenOpts().DwarfVersion < 5)
+ const auto *OMD = dyn_cast<ObjCMethodDecl>(D);
+ if (!OMD)
+ return nullptr;
+
+ if (CGM.getCodeGenOpts().DwarfVersion < 5 && !OMD->isDirectMethod())
return nullptr;
// Starting with DWARF V5 method declarations are emitted as children of
// the interface type.
- const auto *OMD = dyn_cast<ObjCMethodDecl>(D);
- if (!OMD)
- return nullptr;
auto *ID = dyn_cast_or_null<ObjCInterfaceDecl>(D->getDeclContext());
if (!ID)
ID = OMD->getClassInterface();
@@ -3517,7 +3518,7 @@ llvm::DISubprogram *CGDebugInfo::getObjCMethodDeclaration(
InterfaceType, getObjCMethodName(OMD), StringRef(),
InterfaceType->getFile(), LineNo, FnType, LineNo, Flags, SPFlags);
DBuilder.finalizeSubprogram(FD);
- ObjCMethodCache[ID].push_back(FD);
+ ObjCMethodCache[ID].push_back({FD, OMD->isDirectMethod()});
return FD;
}
@@ -4713,27 +4714,28 @@ void CGDebugInfo::finalize() {
DBuilder.replaceTemporary(llvm::TempDIType(E.Decl), Ty);
}
- if (CGM.getCodeGenOpts().DwarfVersion >= 5) {
- // Add methods to interface.
- for (const auto &P : ObjCMethodCache) {
- if (P.second.empty())
- continue;
+ // Add methods to interface.
+ for (const auto &P : ObjCMethodCache) {
+ if (P.second.empty())
+ continue;
- QualType QTy(P.first->getTypeForDecl(), 0);
- auto It = TypeCache.find(QTy.getAsOpaquePtr());
- assert(It != TypeCache.end());
+ QualType QTy(P.first->getTypeForDecl(), 0);
+ auto It = TypeCache.find(QTy.getAsOpaquePtr());
+ assert(It != TypeCache.end());
- llvm::DICompositeType *InterfaceDecl =
- cast<llvm::DICompositeType>(It->second);
+ llvm::DICompositeType *InterfaceDecl =
+ cast<llvm::DICompositeType>(It->second);
- SmallVector<llvm::Metadata *, 16> EltTys;
- auto CurrenetElts = InterfaceDecl->getElements();
- EltTys.append(CurrenetElts.begin(), CurrenetElts.end());
- for (auto &MD : P.second)
- EltTys.push_back(MD);
- llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys);
- DBuilder.replaceArrays(InterfaceDecl, Elements);
- }
+ auto CurElts = InterfaceDecl->getElements();
+ SmallVector<llvm::Metadata *, 16> EltTys(CurElts.begin(), CurElts.end());
+
+ // For DWARF v4 or earlier, only add objc_direct methods.
+ for (auto &SubprogramDirect : P.second)
+ if (CGM.getCodeGenOpts().DwarfVersion >= 5 || SubprogramDirect.getInt())
+ EltTys.push_back(SubprogramDirect.getPointer());
+
+ llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys);
+ DBuilder.replaceArrays(InterfaceDecl, Elements);
}
for (const auto &P : ReplaceMap) {
diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h
index 5341bfa7f350..13e9c7a38fcc 100644
--- a/clang/lib/CodeGen/CGDebugInfo.h
+++ b/clang/lib/CodeGen/CGDebugInfo.h
@@ -114,7 +114,10 @@ class CGDebugInfo {
llvm::SmallVector<ObjCInterfaceCacheEntry, 32> ObjCInterfaceCache;
/// Cache of forward declarations for methods belonging to the interface.
- llvm::DenseMap<const ObjCInterfaceDecl *, std::vector<llvm::DISubprogram *>>
+ /// The extra bit on the DISubprogram specifies whether a method is
+ /// "objc_direct".
+ llvm::DenseMap<const ObjCInterfaceDecl *,
+ std::vector<llvm::PointerIntPair<llvm::DISubprogram *, 1>>>
ObjCMethodCache;
/// Cache of references to clang modules and precompiled headers.
diff --git a/clang/test/CodeGenObjC/debug-info-direct-method.m b/clang/test/CodeGenObjC/debug-info-direct-method.m
new file mode 100644
index 000000000000..f822088f946c
--- /dev/null
+++ b/clang/test/CodeGenObjC/debug-info-direct-method.m
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -dwarf-version=5 -emit-llvm -debug-info-kind=limited -w -triple x86_64-apple-darwin10 %s -o - | FileCheck %s
+// RUN: %clang_cc1 -dwarf-version=4 -emit-llvm -debug-info-kind=limited -w -triple x86_64-apple-darwin10 %s -o - | FileCheck %s
+
+__attribute__((objc_root_class))
+ at interface Root
+ at end
+
+ at implementation Root
+- (int)getInt __attribute__((objc_direct)) {
+ return 42;
+}
+ at end
+
+// Test that objc_direct methods are always (even in DWARF < 5) emitted
+// as members of their containing class.
+
+// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Root",
+// CHECK-SAME: elements: ![[MEMBERS:[0-9]+]],
+// CHECK-SAME: runtimeLang: DW_LANG_ObjC)
+// CHECK: ![[MEMBERS]] = !{![[GETTER:[0-9]+]]}
+// CHECK: ![[GETTER]] = !DISubprogram(name: "-[Root getInt]",
More information about the cfe-commits
mailing list