Skip to content

Commit 6119d0e

Browse files
[clang][ExtractAPI] Ensure typedef to pointer types are preserved (llvm#78584)
When generating declaration fragments for types that use typedefs to pointer types ensure that we keep the user-defined typedef form instead of desugaring the typedef. rdar://102137655
1 parent 279b2d7 commit 6119d0e

File tree

2 files changed

+321
-1
lines changed

2 files changed

+321
-1
lines changed

clang/lib/ExtractAPI/DeclarationFragments.cpp

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,46 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
252252

253253
DeclarationFragments Fragments;
254254

255+
// An ElaboratedType is a sugar for types that are referred to using an
256+
// elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a
257+
// qualified name, e.g., `N::M::type`, or both.
258+
if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) {
259+
ElaboratedTypeKeyword Keyword = ET->getKeyword();
260+
if (Keyword != ElaboratedTypeKeyword::ETK_None) {
261+
Fragments
262+
.append(ElaboratedType::getKeywordName(Keyword),
263+
DeclarationFragments::FragmentKind::Keyword)
264+
.appendSpace();
265+
}
266+
267+
if (const NestedNameSpecifier *NNS = ET->getQualifier())
268+
Fragments.append(getFragmentsForNNS(NNS, Context, After));
269+
270+
// After handling the elaborated keyword or qualified name, build
271+
// declaration fragments for the desugared underlying type.
272+
return Fragments.append(getFragmentsForType(ET->desugar(), Context, After));
273+
}
274+
275+
// If the type is a typedefed type, get the underlying TypedefNameDecl for a
276+
// direct reference to the typedef instead of the wrapped type.
277+
278+
// 'id' type is a typedef for an ObjCObjectPointerType
279+
// we treat it as a typedef
280+
if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) {
281+
const TypedefNameDecl *Decl = TypedefTy->getDecl();
282+
TypedefUnderlyingTypeResolver TypedefResolver(Context);
283+
std::string USR = TypedefResolver.getUSRForType(QualType(T, 0));
284+
285+
if (T->isObjCIdType()) {
286+
return Fragments.append(Decl->getName(),
287+
DeclarationFragments::FragmentKind::Keyword);
288+
}
289+
290+
return Fragments.append(
291+
Decl->getName(), DeclarationFragments::FragmentKind::TypeIdentifier,
292+
USR, TypedefResolver.getUnderlyingTypeDecl(QualType(T, 0)));
293+
}
294+
255295
// Declaration fragments of a pointer type is the declaration fragments of
256296
// the pointee type followed by a `*`,
257297
if (T->isPointerType() && !T->isFunctionPointerType())
@@ -333,7 +373,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
333373
// qualified name, e.g., `N::M::type`, or both.
334374
if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) {
335375
ElaboratedTypeKeyword Keyword = ET->getKeyword();
336-
if (Keyword != ETK_None) {
376+
if (Keyword != ElaboratedTypeKeyword::ETK_None) {
337377
Fragments
338378
.append(ElaboratedType::getKeywordName(Keyword),
339379
DeclarationFragments::FragmentKind::Keyword)

clang/test/ExtractAPI/typedef.c

Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@
1616
//--- input.h
1717
typedef int MyInt;
1818

19+
typedef struct Bar *BarPtr;
20+
21+
void foo(BarPtr value);
22+
23+
void baz(BarPtr *value);
24+
1925
//--- reference.output.json.in
2026
{
2127
"metadata": {
@@ -43,6 +49,208 @@ typedef int MyInt;
4349
},
4450
"relationships": [],
4551
"symbols": [
52+
{
53+
"accessLevel": "public",
54+
"declarationFragments": [
55+
{
56+
"kind": "typeIdentifier",
57+
"preciseIdentifier": "c:v",
58+
"spelling": "void"
59+
},
60+
{
61+
"kind": "text",
62+
"spelling": " "
63+
},
64+
{
65+
"kind": "identifier",
66+
"spelling": "foo"
67+
},
68+
{
69+
"kind": "text",
70+
"spelling": "("
71+
},
72+
{
73+
"kind": "typeIdentifier",
74+
"preciseIdentifier": "c:input.h@T@BarPtr",
75+
"spelling": "BarPtr"
76+
},
77+
{
78+
"kind": "text",
79+
"spelling": " "
80+
},
81+
{
82+
"kind": "internalParam",
83+
"spelling": "value"
84+
},
85+
{
86+
"kind": "text",
87+
"spelling": ");"
88+
}
89+
],
90+
"functionSignature": {
91+
"parameters": [
92+
{
93+
"declarationFragments": [
94+
{
95+
"kind": "typeIdentifier",
96+
"preciseIdentifier": "c:input.h@T@BarPtr",
97+
"spelling": "BarPtr"
98+
},
99+
{
100+
"kind": "text",
101+
"spelling": " "
102+
},
103+
{
104+
"kind": "internalParam",
105+
"spelling": "value"
106+
}
107+
],
108+
"name": "value"
109+
}
110+
],
111+
"returns": [
112+
{
113+
"kind": "typeIdentifier",
114+
"preciseIdentifier": "c:v",
115+
"spelling": "void"
116+
}
117+
]
118+
},
119+
"identifier": {
120+
"interfaceLanguage": "objective-c",
121+
"precise": "c:@F@foo"
122+
},
123+
"kind": {
124+
"displayName": "Function",
125+
"identifier": "objective-c.func"
126+
},
127+
"location": {
128+
"position": {
129+
"character": 5,
130+
"line": 4
131+
},
132+
"uri": "file://INPUT_DIR/input.h"
133+
},
134+
"names": {
135+
"navigator": [
136+
{
137+
"kind": "identifier",
138+
"spelling": "foo"
139+
}
140+
],
141+
"subHeading": [
142+
{
143+
"kind": "identifier",
144+
"spelling": "foo"
145+
}
146+
],
147+
"title": "foo"
148+
},
149+
"pathComponents": [
150+
"foo"
151+
]
152+
},
153+
{
154+
"accessLevel": "public",
155+
"declarationFragments": [
156+
{
157+
"kind": "typeIdentifier",
158+
"preciseIdentifier": "c:v",
159+
"spelling": "void"
160+
},
161+
{
162+
"kind": "text",
163+
"spelling": " "
164+
},
165+
{
166+
"kind": "identifier",
167+
"spelling": "baz"
168+
},
169+
{
170+
"kind": "text",
171+
"spelling": "("
172+
},
173+
{
174+
"kind": "typeIdentifier",
175+
"preciseIdentifier": "c:input.h@T@BarPtr",
176+
"spelling": "BarPtr"
177+
},
178+
{
179+
"kind": "text",
180+
"spelling": " * "
181+
},
182+
{
183+
"kind": "internalParam",
184+
"spelling": "value"
185+
},
186+
{
187+
"kind": "text",
188+
"spelling": ");"
189+
}
190+
],
191+
"functionSignature": {
192+
"parameters": [
193+
{
194+
"declarationFragments": [
195+
{
196+
"kind": "typeIdentifier",
197+
"preciseIdentifier": "c:input.h@T@BarPtr",
198+
"spelling": "BarPtr"
199+
},
200+
{
201+
"kind": "text",
202+
"spelling": " * "
203+
},
204+
{
205+
"kind": "internalParam",
206+
"spelling": "value"
207+
}
208+
],
209+
"name": "value"
210+
}
211+
],
212+
"returns": [
213+
{
214+
"kind": "typeIdentifier",
215+
"preciseIdentifier": "c:v",
216+
"spelling": "void"
217+
}
218+
]
219+
},
220+
"identifier": {
221+
"interfaceLanguage": "objective-c",
222+
"precise": "c:@F@baz"
223+
},
224+
"kind": {
225+
"displayName": "Function",
226+
"identifier": "objective-c.func"
227+
},
228+
"location": {
229+
"position": {
230+
"character": 5,
231+
"line": 6
232+
},
233+
"uri": "file://INPUT_DIR/input.h"
234+
},
235+
"names": {
236+
"navigator": [
237+
{
238+
"kind": "identifier",
239+
"spelling": "baz"
240+
}
241+
],
242+
"subHeading": [
243+
{
244+
"kind": "identifier",
245+
"spelling": "baz"
246+
}
247+
],
248+
"title": "baz"
249+
},
250+
"pathComponents": [
251+
"baz"
252+
]
253+
},
46254
{
47255
"accessLevel": "public",
48256
"declarationFragments": [
@@ -106,6 +314,78 @@ typedef int MyInt;
106314
"MyInt"
107315
],
108316
"type": "c:I"
317+
},
318+
{
319+
"accessLevel": "public",
320+
"declarationFragments": [
321+
{
322+
"kind": "keyword",
323+
"spelling": "typedef"
324+
},
325+
{
326+
"kind": "text",
327+
"spelling": " "
328+
},
329+
{
330+
"kind": "keyword",
331+
"spelling": "struct"
332+
},
333+
{
334+
"kind": "text",
335+
"spelling": " "
336+
},
337+
{
338+
"kind": "typeIdentifier",
339+
"preciseIdentifier": "c:@S@Bar",
340+
"spelling": "Bar"
341+
},
342+
{
343+
"kind": "text",
344+
"spelling": " * "
345+
},
346+
{
347+
"kind": "identifier",
348+
"spelling": "BarPtr"
349+
},
350+
{
351+
"kind": "text",
352+
"spelling": ";"
353+
}
354+
],
355+
"identifier": {
356+
"interfaceLanguage": "objective-c",
357+
"precise": "c:input.h@T@BarPtr"
358+
},
359+
"kind": {
360+
"displayName": "Type Alias",
361+
"identifier": "objective-c.typealias"
362+
},
363+
"location": {
364+
"position": {
365+
"character": 20,
366+
"line": 2
367+
},
368+
"uri": "file://INPUT_DIR/input.h"
369+
},
370+
"names": {
371+
"navigator": [
372+
{
373+
"kind": "identifier",
374+
"spelling": "BarPtr"
375+
}
376+
],
377+
"subHeading": [
378+
{
379+
"kind": "identifier",
380+
"spelling": "BarPtr"
381+
}
382+
],
383+
"title": "BarPtr"
384+
},
385+
"pathComponents": [
386+
"BarPtr"
387+
],
388+
"type": "c:*$@S@Bar"
109389
}
110390
]
111391
}

0 commit comments

Comments
 (0)