Skip to content

Commit 053e352

Browse files
chaitanyavdaniel-grumberg
authored andcommitted
[clang][ExtractAPI] Remove extra pointer indirection from declaration fragments for Obj-C lightweight generics on id
Fixes llvm#61479 Reviewed By: dang Differential Revision: https://reviews.llvm.org/D146866
1 parent 8dc7a71 commit 053e352

File tree

2 files changed

+358
-5
lines changed

2 files changed

+358
-5
lines changed

clang/lib/ExtractAPI/DeclarationFragments.cpp

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -160,14 +160,26 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
160160
DeclarationFragments Fragments;
161161

162162
// Declaration fragments of a pointer type is the declaration fragments of
163-
// the pointee type followed by a `*`, except for Objective-C `id` and `Class`
164-
// pointers, where we do not spell out the `*`.
165-
if (T->isPointerType() ||
166-
(T->isObjCObjectPointerType() &&
167-
!T->getAs<ObjCObjectPointerType>()->isObjCIdOrClassType())) {
163+
// the pointee type followed by a `*`,
164+
if (T->isPointerType())
168165
return Fragments
169166
.append(getFragmentsForType(T->getPointeeType(), Context, After))
170167
.append(" *", DeclarationFragments::FragmentKind::Text);
168+
169+
// For Objective-C `id` and `Class` pointers
170+
// we do not spell out the `*`.
171+
if (T->isObjCObjectPointerType() &&
172+
!T->getAs<ObjCObjectPointerType>()->isObjCIdOrClassType()) {
173+
174+
Fragments.append(getFragmentsForType(T->getPointeeType(), Context, After));
175+
176+
// id<protocol> is an qualified id type
177+
// id<protocol>* is not an qualified id type
178+
if (!T->getAs<ObjCObjectPointerType>()->isObjCQualifiedIdType()) {
179+
Fragments.append(" *", DeclarationFragments::FragmentKind::Text);
180+
}
181+
182+
return Fragments;
171183
}
172184

173185
// Declaration fragments of a lvalue reference type is the declaration
Lines changed: 341 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,341 @@
1+
// RUN: rm -rf %t
2+
// RUN: split-file %s %t
3+
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
4+
// RUN: %t/reference.output.json.in >> %t/reference.output.json
5+
// RUN: %clang -extract-api -x objective-c-header -target arm64-apple-macosx \
6+
// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
7+
8+
// Generator version is not consistent across test runs, normalize it.
9+
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
10+
// RUN: %t/output.json >> %t/output-normalized.json
11+
// RUN: diff %t/reference.output.json %t/output-normalized.json
12+
13+
// CHECK-NOT: error:
14+
// CHECK-NOT: warning:
15+
16+
//--- input.h
17+
@protocol MyProtocol
18+
@end
19+
20+
@interface MyInterface
21+
@property(copy, readwrite) id<MyProtocol> obj1;
22+
@property(readwrite) id<MyProtocol> *obj2;
23+
@end
24+
//--- reference.output.json.in
25+
{
26+
"metadata": {
27+
"formatVersion": {
28+
"major": 0,
29+
"minor": 5,
30+
"patch": 3
31+
},
32+
"generator": "?"
33+
},
34+
"module": {
35+
"name": "",
36+
"platform": {
37+
"architecture": "arm64",
38+
"operatingSystem": {
39+
"minimumVersion": {
40+
"major": 11,
41+
"minor": 0,
42+
"patch": 0
43+
},
44+
"name": "macosx"
45+
},
46+
"vendor": "apple"
47+
}
48+
},
49+
"relationships": [
50+
{
51+
"kind": "memberOf",
52+
"source": "c:objc(cs)MyInterface(py)obj1",
53+
"target": "c:objc(cs)MyInterface",
54+
"targetFallback": "MyInterface"
55+
},
56+
{
57+
"kind": "memberOf",
58+
"source": "c:objc(cs)MyInterface(py)obj2",
59+
"target": "c:objc(cs)MyInterface",
60+
"targetFallback": "MyInterface"
61+
}
62+
],
63+
"symbols": [
64+
{
65+
"accessLevel": "public",
66+
"declarationFragments": [
67+
{
68+
"kind": "keyword",
69+
"spelling": "@interface"
70+
},
71+
{
72+
"kind": "text",
73+
"spelling": " "
74+
},
75+
{
76+
"kind": "identifier",
77+
"spelling": "MyInterface"
78+
}
79+
],
80+
"identifier": {
81+
"interfaceLanguage": "objective-c",
82+
"precise": "c:objc(cs)MyInterface"
83+
},
84+
"kind": {
85+
"displayName": "Class",
86+
"identifier": "objective-c.class"
87+
},
88+
"location": {
89+
"position": {
90+
"character": 12,
91+
"line": 4
92+
},
93+
"uri": "file://INPUT_DIR/input.h"
94+
},
95+
"names": {
96+
"navigator": [
97+
{
98+
"kind": "identifier",
99+
"spelling": "MyInterface"
100+
}
101+
],
102+
"subHeading": [
103+
{
104+
"kind": "identifier",
105+
"spelling": "MyInterface"
106+
}
107+
],
108+
"title": "MyInterface"
109+
},
110+
"pathComponents": [
111+
"MyInterface"
112+
]
113+
},
114+
{
115+
"accessLevel": "public",
116+
"declarationFragments": [
117+
{
118+
"kind": "keyword",
119+
"spelling": "@property"
120+
},
121+
{
122+
"kind": "text",
123+
"spelling": " ("
124+
},
125+
{
126+
"kind": "keyword",
127+
"spelling": "atomic"
128+
},
129+
{
130+
"kind": "text",
131+
"spelling": ", "
132+
},
133+
{
134+
"kind": "keyword",
135+
"spelling": "copy"
136+
},
137+
{
138+
"kind": "text",
139+
"spelling": ", "
140+
},
141+
{
142+
"kind": "keyword",
143+
"spelling": "readwrite"
144+
},
145+
{
146+
"kind": "text",
147+
"spelling": ") "
148+
},
149+
{
150+
"kind": "typeIdentifier",
151+
"preciseIdentifier": "c:Qoobjc(pl)MyProtocol",
152+
"spelling": "id<MyProtocol>"
153+
},
154+
{
155+
"kind": "text",
156+
"spelling": " "
157+
},
158+
{
159+
"kind": "identifier",
160+
"spelling": "obj1"
161+
}
162+
],
163+
"identifier": {
164+
"interfaceLanguage": "objective-c",
165+
"precise": "c:objc(cs)MyInterface(py)obj1"
166+
},
167+
"kind": {
168+
"displayName": "Instance Property",
169+
"identifier": "objective-c.property"
170+
},
171+
"location": {
172+
"position": {
173+
"character": 43,
174+
"line": 5
175+
},
176+
"uri": "file://INPUT_DIR/input.h"
177+
},
178+
"names": {
179+
"navigator": [
180+
{
181+
"kind": "identifier",
182+
"spelling": "obj1"
183+
}
184+
],
185+
"subHeading": [
186+
{
187+
"kind": "identifier",
188+
"spelling": "obj1"
189+
}
190+
],
191+
"title": "obj1"
192+
},
193+
"pathComponents": [
194+
"MyInterface",
195+
"obj1"
196+
]
197+
},
198+
{
199+
"accessLevel": "public",
200+
"declarationFragments": [
201+
{
202+
"kind": "keyword",
203+
"spelling": "@property"
204+
},
205+
{
206+
"kind": "text",
207+
"spelling": " ("
208+
},
209+
{
210+
"kind": "keyword",
211+
"spelling": "atomic"
212+
},
213+
{
214+
"kind": "text",
215+
"spelling": ", "
216+
},
217+
{
218+
"kind": "keyword",
219+
"spelling": "assign"
220+
},
221+
{
222+
"kind": "text",
223+
"spelling": ", "
224+
},
225+
{
226+
"kind": "keyword",
227+
"spelling": "unsafe_unretained"
228+
},
229+
{
230+
"kind": "text",
231+
"spelling": ", "
232+
},
233+
{
234+
"kind": "keyword",
235+
"spelling": "readwrite"
236+
},
237+
{
238+
"kind": "text",
239+
"spelling": ") "
240+
},
241+
{
242+
"kind": "typeIdentifier",
243+
"preciseIdentifier": "c:Qoobjc(pl)MyProtocol",
244+
"spelling": "id<MyProtocol>"
245+
},
246+
{
247+
"kind": "text",
248+
"spelling": " * "
249+
},
250+
{
251+
"kind": "identifier",
252+
"spelling": "obj2"
253+
}
254+
],
255+
"identifier": {
256+
"interfaceLanguage": "objective-c",
257+
"precise": "c:objc(cs)MyInterface(py)obj2"
258+
},
259+
"kind": {
260+
"displayName": "Instance Property",
261+
"identifier": "objective-c.property"
262+
},
263+
"location": {
264+
"position": {
265+
"character": 38,
266+
"line": 6
267+
},
268+
"uri": "file://INPUT_DIR/input.h"
269+
},
270+
"names": {
271+
"navigator": [
272+
{
273+
"kind": "identifier",
274+
"spelling": "obj2"
275+
}
276+
],
277+
"subHeading": [
278+
{
279+
"kind": "identifier",
280+
"spelling": "obj2"
281+
}
282+
],
283+
"title": "obj2"
284+
},
285+
"pathComponents": [
286+
"MyInterface",
287+
"obj2"
288+
]
289+
},
290+
{
291+
"accessLevel": "public",
292+
"declarationFragments": [
293+
{
294+
"kind": "keyword",
295+
"spelling": "@protocol"
296+
},
297+
{
298+
"kind": "text",
299+
"spelling": " "
300+
},
301+
{
302+
"kind": "identifier",
303+
"spelling": "MyProtocol"
304+
}
305+
],
306+
"identifier": {
307+
"interfaceLanguage": "objective-c",
308+
"precise": "c:objc(pl)MyProtocol"
309+
},
310+
"kind": {
311+
"displayName": "Protocol",
312+
"identifier": "objective-c.protocol"
313+
},
314+
"location": {
315+
"position": {
316+
"character": 11,
317+
"line": 1
318+
},
319+
"uri": "file://INPUT_DIR/input.h"
320+
},
321+
"names": {
322+
"navigator": [
323+
{
324+
"kind": "identifier",
325+
"spelling": "MyProtocol"
326+
}
327+
],
328+
"subHeading": [
329+
{
330+
"kind": "identifier",
331+
"spelling": "MyProtocol"
332+
}
333+
],
334+
"title": "MyProtocol"
335+
},
336+
"pathComponents": [
337+
"MyProtocol"
338+
]
339+
}
340+
]
341+
}

0 commit comments

Comments
 (0)