1 //===--- NSAPI.cpp - NSFoundation APIs ------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "clang/AST/NSAPI.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/AST/Expr.h"
14 using namespace clang;
16 NSAPI::NSAPI(ASTContext &ctx)
17 : Ctx(ctx), ClassIds(), BOOLId(0), NSIntegerId(0), NSUIntegerId(0),
18 NSASCIIStringEncodingId(0), NSUTF8StringEncodingId(0) {
21 IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
22 static const char *ClassName[NumClassIds] = {
28 "NSMutableDictionary",
33 return (ClassIds[K] = &Ctx.Idents.get(ClassName[K]));
38 Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const {
39 if (NSStringSelectors[MK].isNull()) {
42 case NSStr_stringWithString:
43 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString"));
45 case NSStr_stringWithUTF8String:
46 Sel = Ctx.Selectors.getUnarySelector(
47 &Ctx.Idents.get("stringWithUTF8String"));
49 case NSStr_stringWithCStringEncoding: {
50 IdentifierInfo *KeyIdents[] = {
51 &Ctx.Idents.get("stringWithCString"),
52 &Ctx.Idents.get("encoding")
54 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
57 case NSStr_stringWithCString:
58 Sel= Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithCString"));
60 case NSStr_initWithString:
61 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString"));
64 return (NSStringSelectors[MK] = Sel);
67 return NSStringSelectors[MK];
70 Optional<NSAPI::NSStringMethodKind>
71 NSAPI::getNSStringMethodKind(Selector Sel) const {
72 for (unsigned i = 0; i != NumNSStringMethods; ++i) {
73 NSStringMethodKind MK = NSStringMethodKind(i);
74 if (Sel == getNSStringSelector(MK))
81 Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {
82 if (NSArraySelectors[MK].isNull()) {
86 Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("array"));
88 case NSArr_arrayWithArray:
89 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithArray"));
91 case NSArr_arrayWithObject:
92 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObject"));
94 case NSArr_arrayWithObjects:
95 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects"));
97 case NSArr_arrayWithObjectsCount: {
98 IdentifierInfo *KeyIdents[] = {
99 &Ctx.Idents.get("arrayWithObjects"),
100 &Ctx.Idents.get("count")
102 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
105 case NSArr_initWithArray:
106 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithArray"));
108 case NSArr_initWithObjects:
109 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithObjects"));
111 case NSArr_objectAtIndex:
112 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex"));
114 case NSMutableArr_replaceObjectAtIndex: {
115 IdentifierInfo *KeyIdents[] = {
116 &Ctx.Idents.get("replaceObjectAtIndex"),
117 &Ctx.Idents.get("withObject")
119 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
123 return (NSArraySelectors[MK] = Sel);
126 return NSArraySelectors[MK];
129 Optional<NSAPI::NSArrayMethodKind> NSAPI::getNSArrayMethodKind(Selector Sel) {
130 for (unsigned i = 0; i != NumNSArrayMethods; ++i) {
131 NSArrayMethodKind MK = NSArrayMethodKind(i);
132 if (Sel == getNSArraySelector(MK))
139 Selector NSAPI::getNSDictionarySelector(
140 NSDictionaryMethodKind MK) const {
141 if (NSDictionarySelectors[MK].isNull()) {
144 case NSDict_dictionary:
145 Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));
147 case NSDict_dictionaryWithDictionary:
148 Sel = Ctx.Selectors.getUnarySelector(
149 &Ctx.Idents.get("dictionaryWithDictionary"));
151 case NSDict_dictionaryWithObjectForKey: {
152 IdentifierInfo *KeyIdents[] = {
153 &Ctx.Idents.get("dictionaryWithObject"),
154 &Ctx.Idents.get("forKey")
156 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
159 case NSDict_dictionaryWithObjectsForKeys: {
160 IdentifierInfo *KeyIdents[] = {
161 &Ctx.Idents.get("dictionaryWithObjects"),
162 &Ctx.Idents.get("forKeys")
164 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
167 case NSDict_dictionaryWithObjectsForKeysCount: {
168 IdentifierInfo *KeyIdents[] = {
169 &Ctx.Idents.get("dictionaryWithObjects"),
170 &Ctx.Idents.get("forKeys"),
171 &Ctx.Idents.get("count")
173 Sel = Ctx.Selectors.getSelector(3, KeyIdents);
176 case NSDict_dictionaryWithObjectsAndKeys:
177 Sel = Ctx.Selectors.getUnarySelector(
178 &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));
180 case NSDict_initWithDictionary:
181 Sel = Ctx.Selectors.getUnarySelector(
182 &Ctx.Idents.get("initWithDictionary"));
184 case NSDict_initWithObjectsAndKeys:
185 Sel = Ctx.Selectors.getUnarySelector(
186 &Ctx.Idents.get("initWithObjectsAndKeys"));
188 case NSDict_initWithObjectsForKeys: {
189 IdentifierInfo *KeyIdents[] = {
190 &Ctx.Idents.get("initWithObjects"),
191 &Ctx.Idents.get("forKeys")
193 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
196 case NSDict_objectForKey:
197 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
199 case NSMutableDict_setObjectForKey: {
200 IdentifierInfo *KeyIdents[] = {
201 &Ctx.Idents.get("setObject"),
202 &Ctx.Idents.get("forKey")
204 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
208 return (NSDictionarySelectors[MK] = Sel);
211 return NSDictionarySelectors[MK];
214 Optional<NSAPI::NSDictionaryMethodKind>
215 NSAPI::getNSDictionaryMethodKind(Selector Sel) {
216 for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
217 NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
218 if (Sel == getNSDictionarySelector(MK))
225 Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
226 bool Instance) const {
227 static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
229 "numberWithUnsignedChar",
231 "numberWithUnsignedShort",
233 "numberWithUnsignedInt",
235 "numberWithUnsignedLong",
236 "numberWithLongLong",
237 "numberWithUnsignedLongLong",
242 "numberWithUnsignedInteger"
244 static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
246 "initWithUnsignedChar",
248 "initWithUnsignedShort",
250 "initWithUnsignedInt",
252 "initWithUnsignedLong",
254 "initWithUnsignedLongLong",
259 "initWithUnsignedInteger"
265 Sels = NSNumberInstanceSelectors;
266 Names = InstanceSelectorName;
268 Sels = NSNumberClassSelectors;
269 Names = ClassSelectorName;
272 if (Sels[MK].isNull())
273 Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
277 Optional<NSAPI::NSNumberLiteralMethodKind>
278 NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
279 for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
280 NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
281 if (isNSNumberLiteralSelector(MK, Sel))
288 Optional<NSAPI::NSNumberLiteralMethodKind>
289 NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
290 const BuiltinType *BT = T->getAs<BuiltinType>();
294 const TypedefType *TDT = T->getAs<TypedefType>();
296 QualType TDTTy = QualType(TDT, 0);
297 if (isObjCBOOLType(TDTTy))
298 return NSAPI::NSNumberWithBool;
299 if (isObjCNSIntegerType(TDTTy))
300 return NSAPI::NSNumberWithInteger;
301 if (isObjCNSUIntegerType(TDTTy))
302 return NSAPI::NSNumberWithUnsignedInteger;
305 switch (BT->getKind()) {
306 case BuiltinType::Char_S:
307 case BuiltinType::SChar:
308 return NSAPI::NSNumberWithChar;
309 case BuiltinType::Char_U:
310 case BuiltinType::UChar:
311 return NSAPI::NSNumberWithUnsignedChar;
312 case BuiltinType::Short:
313 return NSAPI::NSNumberWithShort;
314 case BuiltinType::UShort:
315 return NSAPI::NSNumberWithUnsignedShort;
316 case BuiltinType::Int:
317 return NSAPI::NSNumberWithInt;
318 case BuiltinType::UInt:
319 return NSAPI::NSNumberWithUnsignedInt;
320 case BuiltinType::Long:
321 return NSAPI::NSNumberWithLong;
322 case BuiltinType::ULong:
323 return NSAPI::NSNumberWithUnsignedLong;
324 case BuiltinType::LongLong:
325 return NSAPI::NSNumberWithLongLong;
326 case BuiltinType::ULongLong:
327 return NSAPI::NSNumberWithUnsignedLongLong;
328 case BuiltinType::Float:
329 return NSAPI::NSNumberWithFloat;
330 case BuiltinType::Double:
331 return NSAPI::NSNumberWithDouble;
332 case BuiltinType::Bool:
333 return NSAPI::NSNumberWithBool;
335 case BuiltinType::Void:
336 case BuiltinType::WChar_U:
337 case BuiltinType::WChar_S:
338 case BuiltinType::Char16:
339 case BuiltinType::Char32:
340 case BuiltinType::Int128:
341 case BuiltinType::LongDouble:
342 case BuiltinType::UInt128:
343 case BuiltinType::NullPtr:
344 case BuiltinType::ObjCClass:
345 case BuiltinType::ObjCId:
346 case BuiltinType::ObjCSel:
347 case BuiltinType::OCLImage1d:
348 case BuiltinType::OCLImage1dArray:
349 case BuiltinType::OCLImage1dBuffer:
350 case BuiltinType::OCLImage2d:
351 case BuiltinType::OCLImage2dArray:
352 case BuiltinType::OCLImage3d:
353 case BuiltinType::OCLSampler:
354 case BuiltinType::OCLEvent:
355 case BuiltinType::BoundMember:
356 case BuiltinType::Dependent:
357 case BuiltinType::Overload:
358 case BuiltinType::UnknownAny:
359 case BuiltinType::ARCUnbridgedCast:
360 case BuiltinType::Half:
361 case BuiltinType::PseudoObject:
362 case BuiltinType::BuiltinFn:
369 /// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
370 bool NSAPI::isObjCBOOLType(QualType T) const {
371 return isObjCTypedef(T, "BOOL", BOOLId);
373 /// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
374 bool NSAPI::isObjCNSIntegerType(QualType T) const {
375 return isObjCTypedef(T, "NSInteger", NSIntegerId);
377 /// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
378 bool NSAPI::isObjCNSUIntegerType(QualType T) const {
379 return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
382 bool NSAPI::isObjCTypedef(QualType T,
383 StringRef name, IdentifierInfo *&II) const {
384 if (!Ctx.getLangOpts().ObjC1)
390 II = &Ctx.Idents.get(name);
392 while (const TypedefType *TDT = T->getAs<TypedefType>()) {
393 if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
401 bool NSAPI::isObjCEnumerator(const Expr *E,
402 StringRef name, IdentifierInfo *&II) const {
403 if (!Ctx.getLangOpts().ObjC1)
409 II = &Ctx.Idents.get(name);
411 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
412 if (const EnumConstantDecl *
413 EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl()))
414 return EnumD->getIdentifier() == II;
419 Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
420 Selector &Sel) const {
422 SmallVector<IdentifierInfo *, 4> Idents;
423 for (ArrayRef<StringRef>::const_iterator
424 I = Ids.begin(), E = Ids.end(); I != E; ++I)
425 Idents.push_back(&Ctx.Idents.get(*I));
426 Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data());