Skip to content

Commit 4f3cc97

Browse files
authored
Merge pull request #11701 from swiftlang/clang/property-artificial-param-to-21.x
🍒 [clang][DebugInfo] Don't mark explicit parameter of synthesized ObjC property accessors artificial
2 parents 81388c1 + 498dbe3 commit 4f3cc97

File tree

2 files changed

+96
-1
lines changed

2 files changed

+96
-1
lines changed

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,33 @@ static bool IsArtificial(VarDecl const *VD) {
122122
cast<Decl>(VD->getDeclContext())->isImplicit());
123123
}
124124

125+
/// Returns \c true if the specified variable \c VD is an explicit parameter of
126+
/// a synthesized Objective-C property accessor. E.g., a synthesized property
127+
/// setter method will have a single explicit parameter which is the property to
128+
/// set.
129+
static bool IsObjCSynthesizedPropertyExplicitParameter(VarDecl const *VD) {
130+
assert(VD);
131+
132+
if (!llvm::isa<ParmVarDecl>(VD))
133+
return false;
134+
135+
// Not a property method.
136+
const auto *Method =
137+
llvm::dyn_cast_or_null<ObjCMethodDecl>(VD->getDeclContext());
138+
if (!Method)
139+
return false;
140+
141+
// Not a synthesized property accessor.
142+
if (!Method->isImplicit() || !Method->isPropertyAccessor())
143+
return false;
144+
145+
// Not an explicit parameter.
146+
if (VD->isImplicit())
147+
return false;
148+
149+
return true;
150+
}
151+
125152
CGDebugInfo::CGDebugInfo(CodeGenModule &CGM)
126153
: CGM(CGM), DebugKind(CGM.getCodeGenOpts().getDebugInfo()),
127154
DebugTypeExtRefs(CGM.getCodeGenOpts().DebugTypeExtRefs),
@@ -5160,7 +5187,12 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD,
51605187
}
51615188
SmallVector<uint64_t, 13> Expr;
51625189
llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
5163-
if (VarIsArtificial)
5190+
5191+
// While synthesized Objective-C property setters are "artificial" (i.e., they
5192+
// are not spelled out in source), we want to pretend they are just like a
5193+
// regular non-compiler generated method. Hence, don't mark explicitly passed
5194+
// parameters of such methods as artificial.
5195+
if (VarIsArtificial && !IsObjCSynthesizedPropertyExplicitParameter(VD))
51645196
Flags |= llvm::DINode::FlagArtificial;
51655197

51665198
auto Align = getDeclAlignIfRequired(VD, CGM.getContext());
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Test that synthesized accessors get treated like regular method declarations/definitions.
2+
// I.e.:
3+
// 1. explicitly passed parameter are not marked artificial.
4+
// 2. Each property accessor has a method declaration and definition.
5+
6+
// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -dwarf-version=5 -debug-info-kind=limited %s -o - | FileCheck %s --implicit-check-not "DIFlagArtificial"
7+
8+
@interface Foo
9+
@property int p1;
10+
@end
11+
12+
@implementation Foo
13+
@end
14+
15+
int main(void) {
16+
Foo *f;
17+
f.p1 = 2;
18+
return f.p1;
19+
}
20+
21+
// CHECK: ![[P1_TYPE:[0-9]+]] = !DIBasicType(name: "int"
22+
// CHECK: ![[GETTER_DECL:[0-9]+]] = !DISubprogram(name: "-[Foo p1]"
23+
// CHECK-SAME: type: ![[GETTER_TYPE:[0-9]+]]
24+
// CHECK-SAME: flags: DIFlagArtificial | DIFlagPrototyped
25+
// CHECK-SAME: spFlags: DISPFlagLocalToUnit)
26+
27+
// CHECK: ![[GETTER_TYPE]] = !DISubroutineType(types: ![[GETTER_PARAMS:[0-9]+]])
28+
// CHECK: ![[GETTER_PARAMS]] = !{![[P1_TYPE]], ![[ID_TYPE:[0-9]+]], ![[SEL_TYPE:[0-9]+]]}
29+
// CHECK: ![[ID_TYPE]] = !DIDerivedType(tag: DW_TAG_pointer_type
30+
// CHECK-SAME: flags: DIFlagArtificial | DIFlagObjectPointer)
31+
// CHECK: ![[SEL_TYPE]] = !DIDerivedType(tag: DW_TAG_typedef, name: "SEL"
32+
// CHECK-SAME: flags: DIFlagArtificial)
33+
34+
// CHECK: ![[SETTER_DECL:[0-9]+]] = !DISubprogram(name: "-[Foo setP1:]"
35+
// CHECK-SAME: type: ![[SETTER_TYPE:[0-9]+]]
36+
// CHECK-SAME: flags: DIFlagArtificial | DIFlagPrototyped
37+
// CHECK-SAME: spFlags: DISPFlagLocalToUnit)
38+
// CHECK: ![[SETTER_TYPE]] = !DISubroutineType(types: ![[SETTER_PARAMS:[0-9]+]])
39+
// CHECK: ![[SETTER_PARAMS]] = !{null, ![[ID_TYPE]], ![[SEL_TYPE]], ![[P1_TYPE]]}
40+
41+
// CHECK: ![[GETTER_DEF:[0-9]+]] = distinct !DISubprogram(name: "-[Foo p1]"
42+
// CHECK-SAME: type: ![[GETTER_TYPE]]
43+
// CHECK-SAME: flags: DIFlagArtificial | DIFlagPrototyped
44+
// CHECK-SAME: spFlags: DISPFlagLocalToUnit | DISPFlagDefinition
45+
// CHECK-SAME: declaration: ![[GETTER_DECL]]
46+
47+
// CHECK: !DILocalVariable(name: "self", arg: 1, scope: ![[GETTER_DEF]]
48+
// CHECK-SAME: flags: DIFlagArtificial | DIFlagObjectPointer)
49+
//
50+
// CHECK: !DILocalVariable(name: "_cmd", arg: 2, scope: ![[GETTER_DEF]],
51+
// CHECK-SAME: flags: DIFlagArtificial)
52+
53+
// CHECK: ![[SETTER_DEF:[0-9]+]] = distinct !DISubprogram(name: "-[Foo setP1:]",
54+
// CHECK-SAME: type: ![[SETTER_TYPE]]
55+
// CHECK-SAME: flags: DIFlagArtificial | DIFlagPrototyped
56+
// CHECK-SAME: spFlags: DISPFlagLocalToUnit | DISPFlagDefinition
57+
// CHECK-SAME: declaration: ![[SETTER_DECL]]
58+
59+
// CHECK: !DILocalVariable(name: "self", arg: 1, scope: ![[SETTER_DEF]]
60+
// CHECK-SAME: flags: DIFlagArtificial | DIFlagObjectPointer
61+
// CHECK: !DILocalVariable(name: "_cmd", arg: 2, scope: ![[SETTER_DEF]]
62+
// CHECK-SAME: flags: DIFlagArtificial
63+
// CHECK: !DILocalVariable(name: "p1", arg: 3, scope: ![[SETTER_DEF]]

0 commit comments

Comments
 (0)