xref: /openbsd-src/gnu/llvm/clang/lib/AST/NSAPI.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick //===--- NSAPI.cpp - NSFoundation APIs ------------------------------------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick 
9e5dd7070Spatrick #include "clang/AST/NSAPI.h"
10e5dd7070Spatrick #include "clang/AST/ASTContext.h"
11e5dd7070Spatrick #include "clang/AST/DeclObjC.h"
12e5dd7070Spatrick #include "clang/AST/Expr.h"
13e5dd7070Spatrick #include "llvm/ADT/StringSwitch.h"
14*12c85518Srobert #include <optional>
15e5dd7070Spatrick 
16e5dd7070Spatrick using namespace clang;
17e5dd7070Spatrick 
NSAPI(ASTContext & ctx)18e5dd7070Spatrick NSAPI::NSAPI(ASTContext &ctx)
19e5dd7070Spatrick   : Ctx(ctx), ClassIds(), BOOLId(nullptr), NSIntegerId(nullptr),
20e5dd7070Spatrick     NSUIntegerId(nullptr), NSASCIIStringEncodingId(nullptr),
21e5dd7070Spatrick     NSUTF8StringEncodingId(nullptr) {}
22e5dd7070Spatrick 
getNSClassId(NSClassIdKindKind K) const23e5dd7070Spatrick IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
24e5dd7070Spatrick   static const char *ClassName[NumClassIds] = {
25e5dd7070Spatrick     "NSObject",
26e5dd7070Spatrick     "NSString",
27e5dd7070Spatrick     "NSArray",
28e5dd7070Spatrick     "NSMutableArray",
29e5dd7070Spatrick     "NSDictionary",
30e5dd7070Spatrick     "NSMutableDictionary",
31e5dd7070Spatrick     "NSNumber",
32e5dd7070Spatrick     "NSMutableSet",
33e5dd7070Spatrick     "NSMutableOrderedSet",
34e5dd7070Spatrick     "NSValue"
35e5dd7070Spatrick   };
36e5dd7070Spatrick 
37e5dd7070Spatrick   if (!ClassIds[K])
38e5dd7070Spatrick     return (ClassIds[K] = &Ctx.Idents.get(ClassName[K]));
39e5dd7070Spatrick 
40e5dd7070Spatrick   return ClassIds[K];
41e5dd7070Spatrick }
42e5dd7070Spatrick 
getNSStringSelector(NSStringMethodKind MK) const43e5dd7070Spatrick Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const {
44e5dd7070Spatrick   if (NSStringSelectors[MK].isNull()) {
45e5dd7070Spatrick     Selector Sel;
46e5dd7070Spatrick     switch (MK) {
47e5dd7070Spatrick     case NSStr_stringWithString:
48e5dd7070Spatrick       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString"));
49e5dd7070Spatrick       break;
50e5dd7070Spatrick     case NSStr_stringWithUTF8String:
51e5dd7070Spatrick       Sel = Ctx.Selectors.getUnarySelector(
52e5dd7070Spatrick                                        &Ctx.Idents.get("stringWithUTF8String"));
53e5dd7070Spatrick       break;
54e5dd7070Spatrick     case NSStr_initWithUTF8String:
55e5dd7070Spatrick       Sel = Ctx.Selectors.getUnarySelector(
56e5dd7070Spatrick                                        &Ctx.Idents.get("initWithUTF8String"));
57e5dd7070Spatrick       break;
58e5dd7070Spatrick     case NSStr_stringWithCStringEncoding: {
59e5dd7070Spatrick       IdentifierInfo *KeyIdents[] = {
60e5dd7070Spatrick         &Ctx.Idents.get("stringWithCString"),
61e5dd7070Spatrick         &Ctx.Idents.get("encoding")
62e5dd7070Spatrick       };
63e5dd7070Spatrick       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
64e5dd7070Spatrick       break;
65e5dd7070Spatrick     }
66e5dd7070Spatrick     case NSStr_stringWithCString:
67e5dd7070Spatrick       Sel= Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithCString"));
68e5dd7070Spatrick       break;
69e5dd7070Spatrick     case NSStr_initWithString:
70e5dd7070Spatrick       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString"));
71e5dd7070Spatrick       break;
72e5dd7070Spatrick     }
73e5dd7070Spatrick     return (NSStringSelectors[MK] = Sel);
74e5dd7070Spatrick   }
75e5dd7070Spatrick 
76e5dd7070Spatrick   return NSStringSelectors[MK];
77e5dd7070Spatrick }
78e5dd7070Spatrick 
getNSArraySelector(NSArrayMethodKind MK) const79e5dd7070Spatrick Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {
80e5dd7070Spatrick   if (NSArraySelectors[MK].isNull()) {
81e5dd7070Spatrick     Selector Sel;
82e5dd7070Spatrick     switch (MK) {
83e5dd7070Spatrick     case NSArr_array:
84e5dd7070Spatrick       Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("array"));
85e5dd7070Spatrick       break;
86e5dd7070Spatrick     case NSArr_arrayWithArray:
87e5dd7070Spatrick       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithArray"));
88e5dd7070Spatrick       break;
89e5dd7070Spatrick     case NSArr_arrayWithObject:
90e5dd7070Spatrick       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObject"));
91e5dd7070Spatrick       break;
92e5dd7070Spatrick     case NSArr_arrayWithObjects:
93e5dd7070Spatrick       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects"));
94e5dd7070Spatrick       break;
95e5dd7070Spatrick     case NSArr_arrayWithObjectsCount: {
96e5dd7070Spatrick       IdentifierInfo *KeyIdents[] = {
97e5dd7070Spatrick         &Ctx.Idents.get("arrayWithObjects"),
98e5dd7070Spatrick         &Ctx.Idents.get("count")
99e5dd7070Spatrick       };
100e5dd7070Spatrick       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
101e5dd7070Spatrick       break;
102e5dd7070Spatrick     }
103e5dd7070Spatrick     case NSArr_initWithArray:
104e5dd7070Spatrick       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithArray"));
105e5dd7070Spatrick       break;
106e5dd7070Spatrick     case NSArr_initWithObjects:
107e5dd7070Spatrick       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithObjects"));
108e5dd7070Spatrick       break;
109e5dd7070Spatrick     case NSArr_objectAtIndex:
110e5dd7070Spatrick       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex"));
111e5dd7070Spatrick       break;
112e5dd7070Spatrick     case NSMutableArr_replaceObjectAtIndex: {
113e5dd7070Spatrick       IdentifierInfo *KeyIdents[] = {
114e5dd7070Spatrick         &Ctx.Idents.get("replaceObjectAtIndex"),
115e5dd7070Spatrick         &Ctx.Idents.get("withObject")
116e5dd7070Spatrick       };
117e5dd7070Spatrick       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
118e5dd7070Spatrick       break;
119e5dd7070Spatrick     }
120e5dd7070Spatrick     case NSMutableArr_addObject:
121e5dd7070Spatrick       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));
122e5dd7070Spatrick       break;
123e5dd7070Spatrick     case NSMutableArr_insertObjectAtIndex: {
124e5dd7070Spatrick       IdentifierInfo *KeyIdents[] = {
125e5dd7070Spatrick         &Ctx.Idents.get("insertObject"),
126e5dd7070Spatrick         &Ctx.Idents.get("atIndex")
127e5dd7070Spatrick       };
128e5dd7070Spatrick       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
129e5dd7070Spatrick       break;
130e5dd7070Spatrick     }
131e5dd7070Spatrick     case NSMutableArr_setObjectAtIndexedSubscript: {
132e5dd7070Spatrick       IdentifierInfo *KeyIdents[] = {
133e5dd7070Spatrick         &Ctx.Idents.get("setObject"),
134e5dd7070Spatrick         &Ctx.Idents.get("atIndexedSubscript")
135e5dd7070Spatrick       };
136e5dd7070Spatrick       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
137e5dd7070Spatrick       break;
138e5dd7070Spatrick     }
139e5dd7070Spatrick     }
140e5dd7070Spatrick     return (NSArraySelectors[MK] = Sel);
141e5dd7070Spatrick   }
142e5dd7070Spatrick 
143e5dd7070Spatrick   return NSArraySelectors[MK];
144e5dd7070Spatrick }
145e5dd7070Spatrick 
146*12c85518Srobert std::optional<NSAPI::NSArrayMethodKind>
getNSArrayMethodKind(Selector Sel)147*12c85518Srobert NSAPI::getNSArrayMethodKind(Selector Sel) {
148e5dd7070Spatrick   for (unsigned i = 0; i != NumNSArrayMethods; ++i) {
149e5dd7070Spatrick     NSArrayMethodKind MK = NSArrayMethodKind(i);
150e5dd7070Spatrick     if (Sel == getNSArraySelector(MK))
151e5dd7070Spatrick       return MK;
152e5dd7070Spatrick   }
153e5dd7070Spatrick 
154*12c85518Srobert   return std::nullopt;
155e5dd7070Spatrick }
156e5dd7070Spatrick 
getNSDictionarySelector(NSDictionaryMethodKind MK) const157e5dd7070Spatrick Selector NSAPI::getNSDictionarySelector(
158e5dd7070Spatrick                                        NSDictionaryMethodKind MK) const {
159e5dd7070Spatrick   if (NSDictionarySelectors[MK].isNull()) {
160e5dd7070Spatrick     Selector Sel;
161e5dd7070Spatrick     switch (MK) {
162e5dd7070Spatrick     case NSDict_dictionary:
163e5dd7070Spatrick       Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));
164e5dd7070Spatrick       break;
165e5dd7070Spatrick     case NSDict_dictionaryWithDictionary:
166e5dd7070Spatrick       Sel = Ctx.Selectors.getUnarySelector(
167e5dd7070Spatrick                                    &Ctx.Idents.get("dictionaryWithDictionary"));
168e5dd7070Spatrick       break;
169e5dd7070Spatrick     case NSDict_dictionaryWithObjectForKey: {
170e5dd7070Spatrick       IdentifierInfo *KeyIdents[] = {
171e5dd7070Spatrick         &Ctx.Idents.get("dictionaryWithObject"),
172e5dd7070Spatrick         &Ctx.Idents.get("forKey")
173e5dd7070Spatrick       };
174e5dd7070Spatrick       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
175e5dd7070Spatrick       break;
176e5dd7070Spatrick     }
177e5dd7070Spatrick     case NSDict_dictionaryWithObjectsForKeys: {
178e5dd7070Spatrick       IdentifierInfo *KeyIdents[] = {
179e5dd7070Spatrick         &Ctx.Idents.get("dictionaryWithObjects"),
180e5dd7070Spatrick         &Ctx.Idents.get("forKeys")
181e5dd7070Spatrick       };
182e5dd7070Spatrick       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
183e5dd7070Spatrick       break;
184e5dd7070Spatrick     }
185e5dd7070Spatrick     case NSDict_dictionaryWithObjectsForKeysCount: {
186e5dd7070Spatrick       IdentifierInfo *KeyIdents[] = {
187e5dd7070Spatrick         &Ctx.Idents.get("dictionaryWithObjects"),
188e5dd7070Spatrick         &Ctx.Idents.get("forKeys"),
189e5dd7070Spatrick         &Ctx.Idents.get("count")
190e5dd7070Spatrick       };
191e5dd7070Spatrick       Sel = Ctx.Selectors.getSelector(3, KeyIdents);
192e5dd7070Spatrick       break;
193e5dd7070Spatrick     }
194e5dd7070Spatrick     case NSDict_dictionaryWithObjectsAndKeys:
195e5dd7070Spatrick       Sel = Ctx.Selectors.getUnarySelector(
196e5dd7070Spatrick                                &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));
197e5dd7070Spatrick       break;
198e5dd7070Spatrick     case NSDict_initWithDictionary:
199e5dd7070Spatrick       Sel = Ctx.Selectors.getUnarySelector(
200e5dd7070Spatrick                                          &Ctx.Idents.get("initWithDictionary"));
201e5dd7070Spatrick       break;
202e5dd7070Spatrick     case NSDict_initWithObjectsAndKeys:
203e5dd7070Spatrick       Sel = Ctx.Selectors.getUnarySelector(
204e5dd7070Spatrick                                      &Ctx.Idents.get("initWithObjectsAndKeys"));
205e5dd7070Spatrick       break;
206e5dd7070Spatrick     case NSDict_initWithObjectsForKeys: {
207e5dd7070Spatrick       IdentifierInfo *KeyIdents[] = {
208e5dd7070Spatrick         &Ctx.Idents.get("initWithObjects"),
209e5dd7070Spatrick         &Ctx.Idents.get("forKeys")
210e5dd7070Spatrick       };
211e5dd7070Spatrick       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
212e5dd7070Spatrick       break;
213e5dd7070Spatrick     }
214e5dd7070Spatrick     case NSDict_objectForKey:
215e5dd7070Spatrick       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
216e5dd7070Spatrick       break;
217e5dd7070Spatrick     case NSMutableDict_setObjectForKey: {
218e5dd7070Spatrick       IdentifierInfo *KeyIdents[] = {
219e5dd7070Spatrick         &Ctx.Idents.get("setObject"),
220e5dd7070Spatrick         &Ctx.Idents.get("forKey")
221e5dd7070Spatrick       };
222e5dd7070Spatrick       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
223e5dd7070Spatrick       break;
224e5dd7070Spatrick     }
225e5dd7070Spatrick     case NSMutableDict_setObjectForKeyedSubscript: {
226e5dd7070Spatrick       IdentifierInfo *KeyIdents[] = {
227e5dd7070Spatrick         &Ctx.Idents.get("setObject"),
228e5dd7070Spatrick         &Ctx.Idents.get("forKeyedSubscript")
229e5dd7070Spatrick       };
230e5dd7070Spatrick       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
231e5dd7070Spatrick       break;
232e5dd7070Spatrick     }
233e5dd7070Spatrick     case NSMutableDict_setValueForKey: {
234e5dd7070Spatrick       IdentifierInfo *KeyIdents[] = {
235e5dd7070Spatrick         &Ctx.Idents.get("setValue"),
236e5dd7070Spatrick         &Ctx.Idents.get("forKey")
237e5dd7070Spatrick       };
238e5dd7070Spatrick       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
239e5dd7070Spatrick       break;
240e5dd7070Spatrick     }
241e5dd7070Spatrick     }
242e5dd7070Spatrick     return (NSDictionarySelectors[MK] = Sel);
243e5dd7070Spatrick   }
244e5dd7070Spatrick 
245e5dd7070Spatrick   return NSDictionarySelectors[MK];
246e5dd7070Spatrick }
247e5dd7070Spatrick 
248*12c85518Srobert std::optional<NSAPI::NSDictionaryMethodKind>
getNSDictionaryMethodKind(Selector Sel)249e5dd7070Spatrick NSAPI::getNSDictionaryMethodKind(Selector Sel) {
250e5dd7070Spatrick   for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
251e5dd7070Spatrick     NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
252e5dd7070Spatrick     if (Sel == getNSDictionarySelector(MK))
253e5dd7070Spatrick       return MK;
254e5dd7070Spatrick   }
255e5dd7070Spatrick 
256*12c85518Srobert   return std::nullopt;
257e5dd7070Spatrick }
258e5dd7070Spatrick 
getNSSetSelector(NSSetMethodKind MK) const259e5dd7070Spatrick Selector NSAPI::getNSSetSelector(NSSetMethodKind MK) const {
260e5dd7070Spatrick   if (NSSetSelectors[MK].isNull()) {
261e5dd7070Spatrick     Selector Sel;
262e5dd7070Spatrick     switch (MK) {
263e5dd7070Spatrick     case NSMutableSet_addObject:
264e5dd7070Spatrick       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));
265e5dd7070Spatrick       break;
266e5dd7070Spatrick     case NSOrderedSet_insertObjectAtIndex: {
267e5dd7070Spatrick       IdentifierInfo *KeyIdents[] = {
268e5dd7070Spatrick         &Ctx.Idents.get("insertObject"),
269e5dd7070Spatrick         &Ctx.Idents.get("atIndex")
270e5dd7070Spatrick       };
271e5dd7070Spatrick       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
272e5dd7070Spatrick       break;
273e5dd7070Spatrick     }
274e5dd7070Spatrick     case NSOrderedSet_setObjectAtIndex: {
275e5dd7070Spatrick       IdentifierInfo *KeyIdents[] = {
276e5dd7070Spatrick         &Ctx.Idents.get("setObject"),
277e5dd7070Spatrick         &Ctx.Idents.get("atIndex")
278e5dd7070Spatrick       };
279e5dd7070Spatrick       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
280e5dd7070Spatrick       break;
281e5dd7070Spatrick     }
282e5dd7070Spatrick     case NSOrderedSet_setObjectAtIndexedSubscript: {
283e5dd7070Spatrick       IdentifierInfo *KeyIdents[] = {
284e5dd7070Spatrick         &Ctx.Idents.get("setObject"),
285e5dd7070Spatrick         &Ctx.Idents.get("atIndexedSubscript")
286e5dd7070Spatrick       };
287e5dd7070Spatrick       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
288e5dd7070Spatrick       break;
289e5dd7070Spatrick     }
290e5dd7070Spatrick     case NSOrderedSet_replaceObjectAtIndexWithObject: {
291e5dd7070Spatrick       IdentifierInfo *KeyIdents[] = {
292e5dd7070Spatrick         &Ctx.Idents.get("replaceObjectAtIndex"),
293e5dd7070Spatrick         &Ctx.Idents.get("withObject")
294e5dd7070Spatrick       };
295e5dd7070Spatrick       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
296e5dd7070Spatrick       break;
297e5dd7070Spatrick     }
298e5dd7070Spatrick     }
299e5dd7070Spatrick     return (NSSetSelectors[MK] = Sel);
300e5dd7070Spatrick   }
301e5dd7070Spatrick 
302e5dd7070Spatrick   return NSSetSelectors[MK];
303e5dd7070Spatrick }
304e5dd7070Spatrick 
getNSSetMethodKind(Selector Sel)305*12c85518Srobert std::optional<NSAPI::NSSetMethodKind> NSAPI::getNSSetMethodKind(Selector Sel) {
306e5dd7070Spatrick   for (unsigned i = 0; i != NumNSSetMethods; ++i) {
307e5dd7070Spatrick     NSSetMethodKind MK = NSSetMethodKind(i);
308e5dd7070Spatrick     if (Sel == getNSSetSelector(MK))
309e5dd7070Spatrick       return MK;
310e5dd7070Spatrick   }
311e5dd7070Spatrick 
312*12c85518Srobert   return std::nullopt;
313e5dd7070Spatrick }
314e5dd7070Spatrick 
getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,bool Instance) const315e5dd7070Spatrick Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
316e5dd7070Spatrick                                            bool Instance) const {
317e5dd7070Spatrick   static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
318e5dd7070Spatrick     "numberWithChar",
319e5dd7070Spatrick     "numberWithUnsignedChar",
320e5dd7070Spatrick     "numberWithShort",
321e5dd7070Spatrick     "numberWithUnsignedShort",
322e5dd7070Spatrick     "numberWithInt",
323e5dd7070Spatrick     "numberWithUnsignedInt",
324e5dd7070Spatrick     "numberWithLong",
325e5dd7070Spatrick     "numberWithUnsignedLong",
326e5dd7070Spatrick     "numberWithLongLong",
327e5dd7070Spatrick     "numberWithUnsignedLongLong",
328e5dd7070Spatrick     "numberWithFloat",
329e5dd7070Spatrick     "numberWithDouble",
330e5dd7070Spatrick     "numberWithBool",
331e5dd7070Spatrick     "numberWithInteger",
332e5dd7070Spatrick     "numberWithUnsignedInteger"
333e5dd7070Spatrick   };
334e5dd7070Spatrick   static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
335e5dd7070Spatrick     "initWithChar",
336e5dd7070Spatrick     "initWithUnsignedChar",
337e5dd7070Spatrick     "initWithShort",
338e5dd7070Spatrick     "initWithUnsignedShort",
339e5dd7070Spatrick     "initWithInt",
340e5dd7070Spatrick     "initWithUnsignedInt",
341e5dd7070Spatrick     "initWithLong",
342e5dd7070Spatrick     "initWithUnsignedLong",
343e5dd7070Spatrick     "initWithLongLong",
344e5dd7070Spatrick     "initWithUnsignedLongLong",
345e5dd7070Spatrick     "initWithFloat",
346e5dd7070Spatrick     "initWithDouble",
347e5dd7070Spatrick     "initWithBool",
348e5dd7070Spatrick     "initWithInteger",
349e5dd7070Spatrick     "initWithUnsignedInteger"
350e5dd7070Spatrick   };
351e5dd7070Spatrick 
352e5dd7070Spatrick   Selector *Sels;
353e5dd7070Spatrick   const char **Names;
354e5dd7070Spatrick   if (Instance) {
355e5dd7070Spatrick     Sels = NSNumberInstanceSelectors;
356e5dd7070Spatrick     Names = InstanceSelectorName;
357e5dd7070Spatrick   } else {
358e5dd7070Spatrick     Sels = NSNumberClassSelectors;
359e5dd7070Spatrick     Names = ClassSelectorName;
360e5dd7070Spatrick   }
361e5dd7070Spatrick 
362e5dd7070Spatrick   if (Sels[MK].isNull())
363e5dd7070Spatrick     Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
364e5dd7070Spatrick   return Sels[MK];
365e5dd7070Spatrick }
366e5dd7070Spatrick 
367*12c85518Srobert std::optional<NSAPI::NSNumberLiteralMethodKind>
getNSNumberLiteralMethodKind(Selector Sel) const368e5dd7070Spatrick NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
369e5dd7070Spatrick   for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
370e5dd7070Spatrick     NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
371e5dd7070Spatrick     if (isNSNumberLiteralSelector(MK, Sel))
372e5dd7070Spatrick       return MK;
373e5dd7070Spatrick   }
374e5dd7070Spatrick 
375*12c85518Srobert   return std::nullopt;
376e5dd7070Spatrick }
377e5dd7070Spatrick 
378*12c85518Srobert std::optional<NSAPI::NSNumberLiteralMethodKind>
getNSNumberFactoryMethodKind(QualType T) const379e5dd7070Spatrick NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
380e5dd7070Spatrick   const BuiltinType *BT = T->getAs<BuiltinType>();
381e5dd7070Spatrick   if (!BT)
382*12c85518Srobert     return std::nullopt;
383e5dd7070Spatrick 
384e5dd7070Spatrick   const TypedefType *TDT = T->getAs<TypedefType>();
385e5dd7070Spatrick   if (TDT) {
386e5dd7070Spatrick     QualType TDTTy = QualType(TDT, 0);
387e5dd7070Spatrick     if (isObjCBOOLType(TDTTy))
388e5dd7070Spatrick       return NSAPI::NSNumberWithBool;
389e5dd7070Spatrick     if (isObjCNSIntegerType(TDTTy))
390e5dd7070Spatrick       return NSAPI::NSNumberWithInteger;
391e5dd7070Spatrick     if (isObjCNSUIntegerType(TDTTy))
392e5dd7070Spatrick       return NSAPI::NSNumberWithUnsignedInteger;
393e5dd7070Spatrick   }
394e5dd7070Spatrick 
395e5dd7070Spatrick   switch (BT->getKind()) {
396e5dd7070Spatrick   case BuiltinType::Char_S:
397e5dd7070Spatrick   case BuiltinType::SChar:
398e5dd7070Spatrick     return NSAPI::NSNumberWithChar;
399e5dd7070Spatrick   case BuiltinType::Char_U:
400e5dd7070Spatrick   case BuiltinType::UChar:
401e5dd7070Spatrick     return NSAPI::NSNumberWithUnsignedChar;
402e5dd7070Spatrick   case BuiltinType::Short:
403e5dd7070Spatrick     return NSAPI::NSNumberWithShort;
404e5dd7070Spatrick   case BuiltinType::UShort:
405e5dd7070Spatrick     return NSAPI::NSNumberWithUnsignedShort;
406e5dd7070Spatrick   case BuiltinType::Int:
407e5dd7070Spatrick     return NSAPI::NSNumberWithInt;
408e5dd7070Spatrick   case BuiltinType::UInt:
409e5dd7070Spatrick     return NSAPI::NSNumberWithUnsignedInt;
410e5dd7070Spatrick   case BuiltinType::Long:
411e5dd7070Spatrick     return NSAPI::NSNumberWithLong;
412e5dd7070Spatrick   case BuiltinType::ULong:
413e5dd7070Spatrick     return NSAPI::NSNumberWithUnsignedLong;
414e5dd7070Spatrick   case BuiltinType::LongLong:
415e5dd7070Spatrick     return NSAPI::NSNumberWithLongLong;
416e5dd7070Spatrick   case BuiltinType::ULongLong:
417e5dd7070Spatrick     return NSAPI::NSNumberWithUnsignedLongLong;
418e5dd7070Spatrick   case BuiltinType::Float:
419e5dd7070Spatrick     return NSAPI::NSNumberWithFloat;
420e5dd7070Spatrick   case BuiltinType::Double:
421e5dd7070Spatrick     return NSAPI::NSNumberWithDouble;
422e5dd7070Spatrick   case BuiltinType::Bool:
423e5dd7070Spatrick     return NSAPI::NSNumberWithBool;
424e5dd7070Spatrick 
425e5dd7070Spatrick   case BuiltinType::Void:
426e5dd7070Spatrick   case BuiltinType::WChar_U:
427e5dd7070Spatrick   case BuiltinType::WChar_S:
428e5dd7070Spatrick   case BuiltinType::Char8:
429e5dd7070Spatrick   case BuiltinType::Char16:
430e5dd7070Spatrick   case BuiltinType::Char32:
431e5dd7070Spatrick   case BuiltinType::Int128:
432e5dd7070Spatrick   case BuiltinType::LongDouble:
433e5dd7070Spatrick   case BuiltinType::ShortAccum:
434e5dd7070Spatrick   case BuiltinType::Accum:
435e5dd7070Spatrick   case BuiltinType::LongAccum:
436e5dd7070Spatrick   case BuiltinType::UShortAccum:
437e5dd7070Spatrick   case BuiltinType::UAccum:
438e5dd7070Spatrick   case BuiltinType::ULongAccum:
439e5dd7070Spatrick   case BuiltinType::ShortFract:
440e5dd7070Spatrick   case BuiltinType::Fract:
441e5dd7070Spatrick   case BuiltinType::LongFract:
442e5dd7070Spatrick   case BuiltinType::UShortFract:
443e5dd7070Spatrick   case BuiltinType::UFract:
444e5dd7070Spatrick   case BuiltinType::ULongFract:
445e5dd7070Spatrick   case BuiltinType::SatShortAccum:
446e5dd7070Spatrick   case BuiltinType::SatAccum:
447e5dd7070Spatrick   case BuiltinType::SatLongAccum:
448e5dd7070Spatrick   case BuiltinType::SatUShortAccum:
449e5dd7070Spatrick   case BuiltinType::SatUAccum:
450e5dd7070Spatrick   case BuiltinType::SatULongAccum:
451e5dd7070Spatrick   case BuiltinType::SatShortFract:
452e5dd7070Spatrick   case BuiltinType::SatFract:
453e5dd7070Spatrick   case BuiltinType::SatLongFract:
454e5dd7070Spatrick   case BuiltinType::SatUShortFract:
455e5dd7070Spatrick   case BuiltinType::SatUFract:
456e5dd7070Spatrick   case BuiltinType::SatULongFract:
457e5dd7070Spatrick   case BuiltinType::UInt128:
458e5dd7070Spatrick   case BuiltinType::Float16:
459e5dd7070Spatrick   case BuiltinType::Float128:
460*12c85518Srobert   case BuiltinType::Ibm128:
461e5dd7070Spatrick   case BuiltinType::NullPtr:
462e5dd7070Spatrick   case BuiltinType::ObjCClass:
463e5dd7070Spatrick   case BuiltinType::ObjCId:
464e5dd7070Spatrick   case BuiltinType::ObjCSel:
465e5dd7070Spatrick #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
466e5dd7070Spatrick   case BuiltinType::Id:
467e5dd7070Spatrick #include "clang/Basic/OpenCLImageTypes.def"
468e5dd7070Spatrick #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
469e5dd7070Spatrick   case BuiltinType::Id:
470e5dd7070Spatrick #include "clang/Basic/OpenCLExtensionTypes.def"
471e5dd7070Spatrick   case BuiltinType::OCLSampler:
472e5dd7070Spatrick   case BuiltinType::OCLEvent:
473e5dd7070Spatrick   case BuiltinType::OCLClkEvent:
474e5dd7070Spatrick   case BuiltinType::OCLQueue:
475e5dd7070Spatrick   case BuiltinType::OCLReserveID:
476e5dd7070Spatrick #define SVE_TYPE(Name, Id, SingletonId) \
477e5dd7070Spatrick   case BuiltinType::Id:
478e5dd7070Spatrick #include "clang/Basic/AArch64SVEACLETypes.def"
479a9ac8606Spatrick #define PPC_VECTOR_TYPE(Name, Id, Size) \
480a9ac8606Spatrick   case BuiltinType::Id:
481a9ac8606Spatrick #include "clang/Basic/PPCTypes.def"
482a9ac8606Spatrick #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
483a9ac8606Spatrick #include "clang/Basic/RISCVVTypes.def"
484e5dd7070Spatrick   case BuiltinType::BoundMember:
485e5dd7070Spatrick   case BuiltinType::Dependent:
486e5dd7070Spatrick   case BuiltinType::Overload:
487e5dd7070Spatrick   case BuiltinType::UnknownAny:
488e5dd7070Spatrick   case BuiltinType::ARCUnbridgedCast:
489e5dd7070Spatrick   case BuiltinType::Half:
490e5dd7070Spatrick   case BuiltinType::PseudoObject:
491e5dd7070Spatrick   case BuiltinType::BuiltinFn:
492ec727ea7Spatrick   case BuiltinType::IncompleteMatrixIdx:
493e5dd7070Spatrick   case BuiltinType::OMPArraySection:
494ec727ea7Spatrick   case BuiltinType::OMPArrayShaping:
495ec727ea7Spatrick   case BuiltinType::OMPIterator:
496ec727ea7Spatrick   case BuiltinType::BFloat16:
497e5dd7070Spatrick     break;
498e5dd7070Spatrick   }
499e5dd7070Spatrick 
500*12c85518Srobert   return std::nullopt;
501e5dd7070Spatrick }
502e5dd7070Spatrick 
503e5dd7070Spatrick /// Returns true if \param T is a typedef of "BOOL" in objective-c.
isObjCBOOLType(QualType T) const504e5dd7070Spatrick bool NSAPI::isObjCBOOLType(QualType T) const {
505e5dd7070Spatrick   return isObjCTypedef(T, "BOOL", BOOLId);
506e5dd7070Spatrick }
507e5dd7070Spatrick /// Returns true if \param T is a typedef of "NSInteger" in objective-c.
isObjCNSIntegerType(QualType T) const508e5dd7070Spatrick bool NSAPI::isObjCNSIntegerType(QualType T) const {
509e5dd7070Spatrick   return isObjCTypedef(T, "NSInteger", NSIntegerId);
510e5dd7070Spatrick }
511e5dd7070Spatrick /// Returns true if \param T is a typedef of "NSUInteger" in objective-c.
isObjCNSUIntegerType(QualType T) const512e5dd7070Spatrick bool NSAPI::isObjCNSUIntegerType(QualType T) const {
513e5dd7070Spatrick   return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
514e5dd7070Spatrick }
515e5dd7070Spatrick 
GetNSIntegralKind(QualType T) const516e5dd7070Spatrick StringRef NSAPI::GetNSIntegralKind(QualType T) const {
517e5dd7070Spatrick   if (!Ctx.getLangOpts().ObjC || T.isNull())
518e5dd7070Spatrick     return StringRef();
519e5dd7070Spatrick 
520e5dd7070Spatrick   while (const TypedefType *TDT = T->getAs<TypedefType>()) {
521e5dd7070Spatrick     StringRef NSIntegralResust =
522e5dd7070Spatrick       llvm::StringSwitch<StringRef>(
523e5dd7070Spatrick         TDT->getDecl()->getDeclName().getAsIdentifierInfo()->getName())
524e5dd7070Spatrick     .Case("int8_t", "int8_t")
525e5dd7070Spatrick     .Case("int16_t", "int16_t")
526e5dd7070Spatrick     .Case("int32_t", "int32_t")
527e5dd7070Spatrick     .Case("NSInteger", "NSInteger")
528e5dd7070Spatrick     .Case("int64_t", "int64_t")
529e5dd7070Spatrick     .Case("uint8_t", "uint8_t")
530e5dd7070Spatrick     .Case("uint16_t", "uint16_t")
531e5dd7070Spatrick     .Case("uint32_t", "uint32_t")
532e5dd7070Spatrick     .Case("NSUInteger", "NSUInteger")
533e5dd7070Spatrick     .Case("uint64_t", "uint64_t")
534e5dd7070Spatrick     .Default(StringRef());
535e5dd7070Spatrick     if (!NSIntegralResust.empty())
536e5dd7070Spatrick       return NSIntegralResust;
537e5dd7070Spatrick     T = TDT->desugar();
538e5dd7070Spatrick   }
539e5dd7070Spatrick   return StringRef();
540e5dd7070Spatrick }
541e5dd7070Spatrick 
isMacroDefined(StringRef Id) const542e5dd7070Spatrick bool NSAPI::isMacroDefined(StringRef Id) const {
543e5dd7070Spatrick   // FIXME: Check whether the relevant module macros are visible.
544e5dd7070Spatrick   return Ctx.Idents.get(Id).hasMacroDefinition();
545e5dd7070Spatrick }
546e5dd7070Spatrick 
isSubclassOfNSClass(ObjCInterfaceDecl * InterfaceDecl,NSClassIdKindKind NSClassKind) const547e5dd7070Spatrick bool NSAPI::isSubclassOfNSClass(ObjCInterfaceDecl *InterfaceDecl,
548e5dd7070Spatrick                                 NSClassIdKindKind NSClassKind) const {
549e5dd7070Spatrick   if (!InterfaceDecl) {
550e5dd7070Spatrick     return false;
551e5dd7070Spatrick   }
552e5dd7070Spatrick 
553e5dd7070Spatrick   IdentifierInfo *NSClassID = getNSClassId(NSClassKind);
554e5dd7070Spatrick 
555e5dd7070Spatrick   bool IsSubclass = false;
556e5dd7070Spatrick   do {
557e5dd7070Spatrick     IsSubclass = NSClassID == InterfaceDecl->getIdentifier();
558e5dd7070Spatrick 
559e5dd7070Spatrick     if (IsSubclass) {
560e5dd7070Spatrick       break;
561e5dd7070Spatrick     }
562e5dd7070Spatrick   } while ((InterfaceDecl = InterfaceDecl->getSuperClass()));
563e5dd7070Spatrick 
564e5dd7070Spatrick   return IsSubclass;
565e5dd7070Spatrick }
566e5dd7070Spatrick 
isObjCTypedef(QualType T,StringRef name,IdentifierInfo * & II) const567e5dd7070Spatrick bool NSAPI::isObjCTypedef(QualType T,
568e5dd7070Spatrick                           StringRef name, IdentifierInfo *&II) const {
569e5dd7070Spatrick   if (!Ctx.getLangOpts().ObjC)
570e5dd7070Spatrick     return false;
571e5dd7070Spatrick   if (T.isNull())
572e5dd7070Spatrick     return false;
573e5dd7070Spatrick 
574e5dd7070Spatrick   if (!II)
575e5dd7070Spatrick     II = &Ctx.Idents.get(name);
576e5dd7070Spatrick 
577e5dd7070Spatrick   while (const TypedefType *TDT = T->getAs<TypedefType>()) {
578e5dd7070Spatrick     if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
579e5dd7070Spatrick       return true;
580e5dd7070Spatrick     T = TDT->desugar();
581e5dd7070Spatrick   }
582e5dd7070Spatrick 
583e5dd7070Spatrick   return false;
584e5dd7070Spatrick }
585e5dd7070Spatrick 
isObjCEnumerator(const Expr * E,StringRef name,IdentifierInfo * & II) const586e5dd7070Spatrick bool NSAPI::isObjCEnumerator(const Expr *E,
587e5dd7070Spatrick                              StringRef name, IdentifierInfo *&II) const {
588e5dd7070Spatrick   if (!Ctx.getLangOpts().ObjC)
589e5dd7070Spatrick     return false;
590e5dd7070Spatrick   if (!E)
591e5dd7070Spatrick     return false;
592e5dd7070Spatrick 
593e5dd7070Spatrick   if (!II)
594e5dd7070Spatrick     II = &Ctx.Idents.get(name);
595e5dd7070Spatrick 
596e5dd7070Spatrick   if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
597e5dd7070Spatrick     if (const EnumConstantDecl *
598e5dd7070Spatrick           EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl()))
599e5dd7070Spatrick       return EnumD->getIdentifier() == II;
600e5dd7070Spatrick 
601e5dd7070Spatrick   return false;
602e5dd7070Spatrick }
603e5dd7070Spatrick 
getOrInitSelector(ArrayRef<StringRef> Ids,Selector & Sel) const604e5dd7070Spatrick Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
605e5dd7070Spatrick                                   Selector &Sel) const {
606e5dd7070Spatrick   if (Sel.isNull()) {
607e5dd7070Spatrick     SmallVector<IdentifierInfo *, 4> Idents;
608e5dd7070Spatrick     for (ArrayRef<StringRef>::const_iterator
609e5dd7070Spatrick            I = Ids.begin(), E = Ids.end(); I != E; ++I)
610e5dd7070Spatrick       Idents.push_back(&Ctx.Idents.get(*I));
611e5dd7070Spatrick     Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data());
612e5dd7070Spatrick   }
613e5dd7070Spatrick   return Sel;
614e5dd7070Spatrick }
615e5dd7070Spatrick 
getOrInitNullarySelector(StringRef Id,Selector & Sel) const616e5dd7070Spatrick Selector NSAPI::getOrInitNullarySelector(StringRef Id, Selector &Sel) const {
617e5dd7070Spatrick   if (Sel.isNull()) {
618e5dd7070Spatrick     IdentifierInfo *Ident = &Ctx.Idents.get(Id);
619e5dd7070Spatrick     Sel = Ctx.Selectors.getSelector(0, &Ident);
620e5dd7070Spatrick   }
621e5dd7070Spatrick   return Sel;
622e5dd7070Spatrick }
623