Coverage Report

Created: 2024-01-17 10:31

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