https://github.com/piotrekjeremicz updated 
https://github.com/llvm/llvm-project/pull/227771

>From dbe5d08dee8e86d1eac52e65739acc3bcc81f02c Mon Sep 17 00:00:00 2001
From: Piotrek Jeremicz <[email protected]>
Date: Mon, 28 Sep 2026 14:22:13 +0200
Subject: [PATCH 1/2] [clang][ObjC] Only describe a property's ivar as backing
 storage when accessors are synthesized stubs

---
 clang/lib/CodeGen/CGDebugInfo.cpp             |  6 +++-
 .../DebugInfo/ObjC/property-backing-storage.m | 35 +++++++++++++++++--
 2 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp 
b/clang/lib/CodeGen/CGDebugInfo.cpp
index 93428777b9b24..e192d0cfaf2ba 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -3826,12 +3826,16 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const 
ObjCInterfaceType *Ty,
       if (ObjCPropertyImplDecl *PImpD =
               ImpD->FindPropertyImplIvarDecl(Field->getIdentifier())) {
         if (ObjCPropertyDecl *PD = PImpD->getPropertyDecl()) {
-          SynthesizedProperty = PD;
           SourceLocation Loc = PD->getLocation();
           PUnit = getOrCreateFile(Loc);
           PLine = getLineNumber(Loc);
           ObjCMethodDecl *Getter = PImpD->getGetterMethodDecl();
           ObjCMethodDecl *Setter = PImpD->getSetterMethodDecl();
+          bool GetterIsStub = !Getter || Getter->isSynthesizedAccessorStub();
+          bool SetterIsStub = PD->isReadOnly() || !Setter ||
+                              Setter->isSynthesizedAccessorStub();
+          if (GetterIsStub && SetterIsStub)
+            SynthesizedProperty = PD;
           PropertyNode = DBuilder.createObjCProperty(
               PD->getName(), PUnit, PLine,
               hasDefaultGetterName(PD, Getter)
diff --git a/clang/test/DebugInfo/ObjC/property-backing-storage.m 
b/clang/test/DebugInfo/ObjC/property-backing-storage.m
index 456926e3a9dd4..76117aca3b854 100644
--- a/clang/test/DebugInfo/ObjC/property-backing-storage.m
+++ b/clang/test/DebugInfo/ObjC/property-backing-storage.m
@@ -9,8 +9,14 @@
 //   3. implicitBacking   - no @synthesize at all; the compiler
 //                           auto-synthesizes both the accessors and a
 //                           default-named ivar (_implicitBacking).
+// It also verifies that no DIProperty is emitted when an accessor is
+// hand-written (class HandwrittenAccessor), because such an accessor may do
+// more than forward to the ivar, so a debugger must not bypass it. The legacy
+// DIObjCProperty is still emitted in that case.
 
-// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o %t.ll
+// RUN: FileCheck %s < %t.ll
+// RUN: FileCheck %s --check-prefix=NO-DIPROPERTY < %t.ll
 
 // CHECK-DAG: ![[DECLARED_PROP:[0-9]+]] = !DIObjCProperty(name: 
"declaredBacking", file: ![[FILE:[0-9]+]], line: {{[0-9]+}}, attributes: 2316, 
type: ![[INT_TY:[0-9]+]])
 // CHECK-DAG: ![[UNDECLARED_PROP:[0-9]+]] = !DIObjCProperty(name: 
"undeclaredBacking", file: ![[FILE]], line: {{[0-9]+}}, attributes: 2316, type: 
![[INT_TY]])
@@ -25,6 +31,19 @@
 // CHECK-DAG: ![[IMPLICIT_IVAR:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, 
name: "_implicitBacking", {{.*}}file: ![[FILE]], {{.*}}extraData: 
![[IMPLICIT_PROP]])
 // CHECK-DAG: !DIProperty(name: "implicitBacking", file: ![[FILE]], line: 
{{[0-9]+}}, type: ![[INT_TY]], backing_storage: ![[IMPLICIT_IVAR]])
 
+//
+// Hand-written accessors: the legacy DIObjCProperty is still emitted and
+// linked from the ivar...
+// CHECK-DAG: ![[COMPUTED_PROP:[0-9]+]] = !DIObjCProperty(name: "computed", 
file: ![[FILE]], line: {{[0-9]+}}, attributes: 2124, type: ![[INT_TY]])
+// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "_computed", 
{{.*}}file: ![[FILE]], {{.*}}extraData: ![[COMPUTED_PROP]])
+// CHECK-DAG: ![[CLAMPED_PROP:[0-9]+]] = !DIObjCProperty(name: "clamped", 
file: ![[FILE]], line: {{[0-9]+}}, attributes: 2124, type: ![[INT_TY]])
+// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "_clamped", {{.*}}file: 
![[FILE]], {{.*}}extraData: ![[CLAMPED_PROP]])
+//
+// ...but no DIProperty is. These use a separate prefix with only NOT lines so
+// they scan the whole output, not just the text after the last CHECK-DAG 
match.
+// NO-DIPROPERTY-NOT: !DIProperty(name: "computed"
+// NO-DIPROPERTY-NOT: !DIProperty(name: "clamped"
+
 @interface C {
   int _customDeclaredIvar;
 }
@@ -38,4 +57,16 @@ @implementation C
 @synthesize undeclaredBacking = _customUndeclaredIvar;
 @end
 
-void foo(C *cptr) {}
+@interface HandwrittenAccessor
+// Hand-written getter, synthesized setter.
+@property(nonatomic) int computed;
+// Synthesized getter, hand-written setter.
+@property(nonatomic) int clamped;
+@end
+
+@implementation HandwrittenAccessor
+- (int)computed { return _computed * 100; }
+- (void)setClamped:(int)clamped { _clamped = clamped > 10 ? 10 : clamped; }
+@end
+
+void foo(C *cptr, HandwrittenAccessor *hptr) {}

>From b397fad0c2949662b02a8e72efa1560e45ae17a3 Mon Sep 17 00:00:00 2001
From: Piotrek Jeremicz <[email protected]>
Date: Sat, 10 Oct 2026 17:23:51 +0200
Subject: [PATCH 2/2] Removed comments

---
 clang/test/DebugInfo/ObjC/property-backing-storage.m | 11 +----------
 1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/clang/test/DebugInfo/ObjC/property-backing-storage.m 
b/clang/test/DebugInfo/ObjC/property-backing-storage.m
index 76117aca3b854..71be8121d3bdc 100644
--- a/clang/test/DebugInfo/ObjC/property-backing-storage.m
+++ b/clang/test/DebugInfo/ObjC/property-backing-storage.m
@@ -9,10 +9,6 @@
 //   3. implicitBacking   - no @synthesize at all; the compiler
 //                           auto-synthesizes both the accessors and a
 //                           default-named ivar (_implicitBacking).
-// It also verifies that no DIProperty is emitted when an accessor is
-// hand-written (class HandwrittenAccessor), because such an accessor may do
-// more than forward to the ivar, so a debugger must not bypass it. The legacy
-// DIObjCProperty is still emitted in that case.
 
 // RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o %t.ll
 // RUN: FileCheck %s < %t.ll
@@ -31,16 +27,11 @@
 // CHECK-DAG: ![[IMPLICIT_IVAR:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, 
name: "_implicitBacking", {{.*}}file: ![[FILE]], {{.*}}extraData: 
![[IMPLICIT_PROP]])
 // CHECK-DAG: !DIProperty(name: "implicitBacking", file: ![[FILE]], line: 
{{[0-9]+}}, type: ![[INT_TY]], backing_storage: ![[IMPLICIT_IVAR]])
 
-//
-// Hand-written accessors: the legacy DIObjCProperty is still emitted and
-// linked from the ivar...
 // CHECK-DAG: ![[COMPUTED_PROP:[0-9]+]] = !DIObjCProperty(name: "computed", 
file: ![[FILE]], line: {{[0-9]+}}, attributes: 2124, type: ![[INT_TY]])
 // CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "_computed", 
{{.*}}file: ![[FILE]], {{.*}}extraData: ![[COMPUTED_PROP]])
 // CHECK-DAG: ![[CLAMPED_PROP:[0-9]+]] = !DIObjCProperty(name: "clamped", 
file: ![[FILE]], line: {{[0-9]+}}, attributes: 2124, type: ![[INT_TY]])
 // CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "_clamped", {{.*}}file: 
![[FILE]], {{.*}}extraData: ![[CLAMPED_PROP]])
-//
-// ...but no DIProperty is. These use a separate prefix with only NOT lines so
-// they scan the whole output, not just the text after the last CHECK-DAG 
match.
+
 // NO-DIPROPERTY-NOT: !DIProperty(name: "computed"
 // NO-DIPROPERTY-NOT: !DIProperty(name: "clamped"
 

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to