Skip to content

Conversation

@Michael137
Copy link
Member

@Michael137 Michael137 commented Oct 28, 2025

Depends on:

When an Objective-C property has a backing ivar, we would previously not add a DW_AT_APPLE_property to the ivar's DW_TAG_member. This is what was intended based on the Objective-C DebugInfo docs but is not what LLVM currently generates.

LLDB currently doesn't ever try linking the ObjCPropertyDecls to their ObjCIvarDecls, but if we wanted to, this debug-info patch is a pre-requisite.

@llvmbot
Copy link
Member

llvmbot commented Oct 28, 2025

@llvm/pr-subscribers-debuginfo

Author: Michael Buch (Michael137)

Changes

Depends on:

When an Objective-C property has a backing ivar, we would previously not add a DW_AT_APPLE_property to the ivar's DW_TAG_member. This is what was intended based on the Objective-C DebugInfo docs but is not what LLVM currently generates.

LLDB currently doesn't ever try linking the ObjCPropertyDecls to their ObjCIvarDecls, but if we wanted to, this debug-info patch is a pre-requisite.


Full diff: https://github.com/llvm/llvm-project/pull/165409.diff

3 Files Affected:

  • (modified) llvm/lib/AsmParser/LLParser.cpp (+2-2)
  • (modified) llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp (+1-1)
  • (added) llvm/test/DebugInfo/Generic/objc-property.ll (+91)
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 5164cec33e6f5..e7a04d98df2af 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -6341,8 +6341,8 @@ bool LLParser::parseDIObjCProperty(MDNode *&Result, bool IsDistinct) {
 #undef VISIT_MD_FIELDS
 
   Result = GET_OR_DISTINCT(DIObjCProperty,
-                           (Context, name.Val, file.Val, line.Val, setter.Val,
-                            getter.Val, attributes.Val, type.Val));
+                           (Context, name.Val, file.Val, line.Val, getter.Val,
+                            setter.Val, attributes.Val, type.Val));
   return false;
 }
 
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index e40fb768027b8..7d7588c89fae2 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -1109,7 +1109,7 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
           constructMemberDIE(Buffer, DDTy);
         }
       } else if (auto *Property = dyn_cast<DIObjCProperty>(Element)) {
-        DIE &ElemDie = createAndAddDIE(Property->getTag(), Buffer);
+        DIE &ElemDie = createAndAddDIE(Property->getTag(), Buffer, Property);
         StringRef PropertyName = Property->getName();
         addString(ElemDie, dwarf::DW_AT_APPLE_property_name, PropertyName);
         if (Property->getType())
diff --git a/llvm/test/DebugInfo/Generic/objc-property.ll b/llvm/test/DebugInfo/Generic/objc-property.ll
new file mode 100644
index 0000000000000..c58cdc3f478e7
--- /dev/null
+++ b/llvm/test/DebugInfo/Generic/objc-property.ll
@@ -0,0 +1,91 @@
+; RUN: llc -filetype=obj -o - %s | llvm-dwarfdump --debug-info - | FileCheck %s
+
+; CHECK: DW_TAG_structure_type
+; CHECK:   DW_AT_name ("Foo")
+;
+; CHECK:   0x[[AUTO_SYNTH:[0-9a-f]+]]: DW_TAG_APPLE_property
+; CHECK:     DW_AT_APPLE_property_name ("autoSynthProp")
+; CHECK:     DW_AT_APPLE_property_attribute
+; CHECK-SAME: DW_APPLE_PROPERTY_assign, DW_APPLE_PROPERTY_readwrite,
+; CHECK-SAME: DW_APPLE_PROPERTY_atomic, DW_APPLE_PROPERTY_unsafe_unretained
+;
+; CHECK:   0x[[SYNTH:[0-9a-f]+]]: DW_TAG_APPLE_property
+; CHECK:     DW_AT_APPLE_property_name ("synthProp")
+; CHECK:     DW_AT_APPLE_property_attribute
+; CHECK-SAME: DW_APPLE_PROPERTY_assign, DW_APPLE_PROPERTY_readwrite,
+; CHECK-SAME: DW_APPLE_PROPERTY_atomic, DW_APPLE_PROPERTY_unsafe_unretained
+;
+; CHECK:   0x[[GET:[0-9a-f]+]]: DW_TAG_APPLE_property
+; CHECK:     DW_AT_APPLE_property_name ("customGetterProp")
+; CHECK:     DW_AT_APPLE_property_getter   ("customGetter")
+; CHECK:     DW_AT_APPLE_property_attribute
+; CHECK-SAME: DW_APPLE_PROPERTY_getter, DW_APPLE_PROPERTY_assign, DW_APPLE_PROPERTY_readwrite,
+; CHECK-SAME: DW_APPLE_PROPERTY_atomic, DW_APPLE_PROPERTY_unsafe_unretained
+;
+; CHECK:   0x[[SET:[0-9a-f]+]]: DW_TAG_APPLE_property
+; CHECK:     DW_AT_APPLE_property_name ("customSetterProp")
+; CHECK:     DW_AT_APPLE_property_setter   ("customSetter:")
+; CHECK:     DW_AT_APPLE_property_attribute
+; CHECK-SAME: DW_APPLE_PROPERTY_assign, DW_APPLE_PROPERTY_readwrite,
+; CHECK-SAME: DW_APPLE_PROPERTY_setter, DW_APPLE_PROPERTY_atomic, DW_APPLE_PROPERTY_unsafe_unretained
+;
+; CHECK:   0x[[ACCESSORS:[0-9a-f]+]]: DW_TAG_APPLE_property
+; CHECK:     DW_AT_APPLE_property_name ("customAccessorsProp")
+; CHECK:     DW_AT_APPLE_property_getter   ("customGetter")
+; CHECK:     DW_AT_APPLE_property_setter   ("customSetter:")
+; CHECK:     DW_AT_APPLE_property_attribute
+; CHECK-SAME: DW_APPLE_PROPERTY_getter, DW_APPLE_PROPERTY_assign, DW_APPLE_PROPERTY_readwrite,
+; CHECK-SAME: DW_APPLE_PROPERTY_setter, DW_APPLE_PROPERTY_atomic, DW_APPLE_PROPERTY_unsafe_unretained
+;
+; CHECK:   DW_TAG_member
+; CHECK:     DW_AT_name ("someBackingIvar")
+; CHECK:     DW_AT_APPLE_property (0x[[SYNTH]])
+;
+; CHECK:   DW_TAG_member
+; CHECK:     DW_AT_name ("_autoSynthProp")
+; CHECK:     DW_AT_APPLE_property (0x[[AUTO_SYNTH]])
+;
+; CHECK:   DW_TAG_member
+; CHECK:     DW_AT_name ("_customGetterProp")
+; CHECK:     DW_AT_APPLE_property (0x[[GET]])
+;
+; CHECK:   DW_TAG_member
+; CHECK:     DW_AT_name ("_customSetterProp")
+; CHECK:     DW_AT_APPLE_property (0x[[SET]])
+
+!llvm.module.flags = !{!7, !8}
+!llvm.dbg.cu = !{!13}
+
+!7 = !{i32 7, !"Dwarf Version", i32 5}
+!8 = !{i32 2, !"Debug Info Version", i32 3}
+!13 = distinct !DICompileUnit(language: DW_LANG_ObjC, file: !14, producer: "hand written", isOptimized: false, runtimeVersion: 2, emissionKind: FullDebug, retainedTypes: !15, splitDebugInlining: false, debugInfoForProfiling: true, nameTableKind: Apple)
+!14 = !DIFile(filename: "main.m", directory: "/tmp")
+!15 = !{!16}
+!16 = !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", scope: !14, file: !14, line: 1, size: 128, flags: DIFlagObjcClassComplete, elements: !17, runtimeLang: DW_LANG_ObjC)
+!17 = !{!18, !20, !21, !22, !23, !24, !25, !26, !27, !28, !35, !38, !39, !40, !41, !42, !43}
+!18 = !DIObjCProperty(name: "autoSynthProp", file: !14, line: 5, attributes: 2316, type: !19)
+!19 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!20 = !DIObjCProperty(name: "synthProp", file: !14, line: 6, attributes: 2316, type: !19)
+!21 = !DIObjCProperty(name: "customGetterProp", file: !14, line: 7, getter: "customGetter", attributes: 2318, type: !19)
+!22 = !DIObjCProperty(name: "customSetterProp", file: !14, line: 8, setter: "customSetter:", attributes: 2444, type: !19)
+!23 = !DIObjCProperty(name: "customAccessorsProp", file: !14, line: 9, setter: "customSetter:", getter: "customGetter", attributes: 2446, type: !19)
+!24 = !DIDerivedType(tag: DW_TAG_member, name: "someBackingIvar", scope: !14, file: !14, line: 2, baseType: !19, size: 32, flags: DIFlagProtected, extraData: !20)
+!25 = !DIDerivedType(tag: DW_TAG_member, name: "_autoSynthProp", scope: !14, file: !14, line: 5, baseType: !19, size: 32, flags: DIFlagPrivate, extraData: !18)
+!26 = !DIDerivedType(tag: DW_TAG_member, name: "_customGetterProp", scope: !14, file: !14, line: 7, baseType: !19, size: 32, flags: DIFlagPrivate, extraData: !21)
+!27 = !DIDerivedType(tag: DW_TAG_member, name: "_customSetterProp", scope: !14, file: !14, line: 8, baseType: !19, size: 32, flags: DIFlagPrivate, extraData: !22)
+!28 = !DISubprogram(name: "-[Foo customGetter]", scope: !16, file: !14, line: 19, type: !29, scopeLine: 19, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit)
+!29 = !DISubroutineType(types: !30)
+!30 = !{!19, !31, !32}
+!31 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !16, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
+!32 = !DIDerivedType(tag: DW_TAG_typedef, name: "SEL", file: !14, baseType: !33, flags: DIFlagArtificial)
+!33 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !34, size: 64)
+!34 = !DICompositeType(tag: DW_TAG_structure_type, name: "objc_selector", file: !14, flags: DIFlagFwdDecl)
+!35 = !DISubprogram(name: "-[Foo customSetter:]", scope: !16, file: !14, line: 23, type: !36, scopeLine: 23, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit)
+!36 = !DISubroutineType(types: !37)
+!37 = !{null, !31, !32, !19}
+!38 = !DISubprogram(name: "-[Foo synthProp]", scope: !16, file: !14, line: 17, type: !29, scopeLine: 17, flags: DIFlagArtificial | DIFlagPrototyped, spFlags: DISPFlagLocalToUnit)
+!39 = !DISubprogram(name: "-[Foo setSynthProp:]", scope: !16, file: !14, line: 17, type: !36, scopeLine: 17, flags: DIFlagArtificial | DIFlagPrototyped, spFlags: DISPFlagLocalToUnit)
+!40 = !DISubprogram(name: "-[Foo autoSynthProp]", scope: !16, file: !14, line: 5, type: !29, scopeLine: 5, flags: DIFlagArtificial | DIFlagPrototyped, spFlags: DISPFlagLocalToUnit)
+!41 = !DISubprogram(name: "-[Foo setAutoSynthProp:]", scope: !16, file: !14, line: 5, type: !36, scopeLine: 5, flags: DIFlagArtificial | DIFlagPrototyped, spFlags: DISPFlagLocalToUnit)
+!42 = !DISubprogram(name: "-[Foo setCustomGetterProp:]", scope: !16, file: !14, line: 7, type: !36, scopeLine: 7, flags: DIFlagArtificial | DIFlagPrototyped, spFlags: DISPFlagLocalToUnit)
+!43 = !DISubprogram(name: "-[Foo customSetterProp]", scope: !16, file: !14, line: 8, type: !29, scopeLine: 8, flags: DIFlagArtificial | DIFlagPrototyped, spFlags: DISPFlagLocalToUnit)

@Michael137 Michael137 force-pushed the llvm/objc-property-ivar-back-link branch 4 times, most recently from 8df8ba9 to 93fa594 Compare October 29, 2025 09:09
Copy link
Collaborator

@adrian-prantl adrian-prantl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exciting, and simple!

@Michael137 Michael137 force-pushed the llvm/objc-property-ivar-back-link branch from 93fa594 to c2e4ec9 Compare October 31, 2025 09:05
…AG_APPLE_property

Depends on:
* llvm#165373

When an Objective-C property has a backing ivar, we would previously not add a `DW_AT_APPLE_property` to the ivar's `DW_TAG_member`. This is what was intended based on the [Objective-C DebugInfo docs](https://github.com/llvm/llvm-project/blob/main/llvm/docs/SourceLevelDebugging.rst#proposal) but is not what LLVM currently generates.

LLDB currently doesn't ever try linking the `ObjCPropertyDecl`s to their `ObjCIvarDecl`s, but if we wanted to, this debug-info patch is a pre-requisite.
@Michael137 Michael137 force-pushed the llvm/objc-property-ivar-back-link branch from c2e4ec9 to 8416728 Compare October 31, 2025 09:14
@Michael137 Michael137 enabled auto-merge (squash) October 31, 2025 09:45
@Michael137 Michael137 merged commit 10fbbb6 into llvm:main Oct 31, 2025
9 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants