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