NSAPI.cpp revision 239462
1139731Simp//===--- NSAPI.cpp - NSFoundation APIs ------------------------------------===//
21543Srgrimes//
31543Srgrimes//                     The LLVM Compiler Infrastructure
4247047Skib//
51543Srgrimes// This file is distributed under the University of Illinois Open Source
61543Srgrimes// License. See LICENSE.TXT for details.
71543Srgrimes//
81543Srgrimes//===----------------------------------------------------------------------===//
91543Srgrimes
101543Srgrimes#include "clang/AST/NSAPI.h"
111543Srgrimes#include "clang/AST/ASTContext.h"
121543Srgrimes#include "clang/AST/Expr.h"
131543Srgrimes
141543Srgrimesusing namespace clang;
151543Srgrimes
161543SrgrimesNSAPI::NSAPI(ASTContext &ctx)
171543Srgrimes  : Ctx(ctx), ClassIds(), BOOLId(0), NSIntegerId(0), NSUIntegerId(0),
181543Srgrimes    NSASCIIStringEncodingId(0), NSUTF8StringEncodingId(0) {
191543Srgrimes}
201543Srgrimes
211543SrgrimesIdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
221543Srgrimes  static const char *ClassName[NumClassIds] = {
231543Srgrimes    "NSObject",
241543Srgrimes    "NSString",
251543Srgrimes    "NSArray",
261543Srgrimes    "NSMutableArray",
271543Srgrimes    "NSDictionary",
281543Srgrimes    "NSMutableDictionary",
291543Srgrimes    "NSNumber"
301543Srgrimes  };
3150477Speter
321543Srgrimes  if (!ClassIds[K])
331543Srgrimes    return (ClassIds[K] = &Ctx.Idents.get(ClassName[K]));
34247047Skib
35247047Skib  return ClassIds[K];
362166Spaul}
371543Srgrimes
381543SrgrimesSelector NSAPI::getNSStringSelector(NSStringMethodKind MK) const {
391543Srgrimes  if (NSStringSelectors[MK].isNull()) {
401543Srgrimes    Selector Sel;
41247047Skib    switch (MK) {
42247047Skib    case NSStr_stringWithString:
431543Srgrimes      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString"));
44105014Smike      break;
451543Srgrimes    case NSStr_stringWithUTF8String:
46247047Skib      Sel = Ctx.Selectors.getUnarySelector(
471543Srgrimes                                       &Ctx.Idents.get("stringWithUTF8String"));
48247047Skib      break;
49247047Skib    case NSStr_stringWithCStringEncoding: {
50247047Skib      IdentifierInfo *KeyIdents[] = {
51247047Skib        &Ctx.Idents.get("stringWithCString"),
52247047Skib        &Ctx.Idents.get("encoding")
53247047Skib      };
54247047Skib      Sel = Ctx.Selectors.getSelector(2, KeyIdents);
55247047Skib      break;
56247047Skib    }
57247047Skib    case NSStr_stringWithCString:
58247047Skib      Sel= Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithCString"));
59247047Skib      break;
60247047Skib    case NSStr_initWithString:
61247047Skib      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString"));
62247047Skib      break;
63247047Skib    }
64247047Skib    return (NSStringSelectors[MK] = Sel);
65247047Skib  }
66247047Skib
67247047Skib  return NSStringSelectors[MK];
68247047Skib}
69247047Skib
70247047Skibllvm::Optional<NSAPI::NSStringMethodKind>
71247047SkibNSAPI::getNSStringMethodKind(Selector Sel) const {
72247047Skib  for (unsigned i = 0; i != NumNSStringMethods; ++i) {
73247047Skib    NSStringMethodKind MK = NSStringMethodKind(i);
74247047Skib    if (Sel == getNSStringSelector(MK))
75247047Skib      return MK;
76247047Skib  }
77247047Skib
78247047Skib  return llvm::Optional<NSStringMethodKind>();
79247047Skib}
80247047Skib
81247047SkibSelector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {
82247047Skib  if (NSArraySelectors[MK].isNull()) {
83247047Skib    Selector Sel;
84247047Skib    switch (MK) {
85247047Skib    case NSArr_array:
86247047Skib      Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("array"));
87247047Skib      break;
88247047Skib    case NSArr_arrayWithArray:
89247047Skib      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithArray"));
90247047Skib      break;
91247047Skib    case NSArr_arrayWithObject:
92247047Skib      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObject"));
93247047Skib      break;
94247047Skib    case NSArr_arrayWithObjects:
95247047Skib      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects"));
96247047Skib      break;
97247047Skib    case NSArr_arrayWithObjectsCount: {
98247047Skib      IdentifierInfo *KeyIdents[] = {
99247047Skib        &Ctx.Idents.get("arrayWithObjects"),
100247047Skib        &Ctx.Idents.get("count")
101247047Skib      };
102247047Skib      Sel = Ctx.Selectors.getSelector(2, KeyIdents);
103247047Skib      break;
104247047Skib    }
105247047Skib    case NSArr_initWithArray:
1061543Srgrimes      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithArray"));
1071543Srgrimes      break;
1081543Srgrimes    case NSArr_initWithObjects:
1091543Srgrimes      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithObjects"));
1101543Srgrimes      break;
1111543Srgrimes    case NSArr_objectAtIndex:
112227399Skib      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex"));
113227399Skib      break;
114227399Skib    case NSMutableArr_replaceObjectAtIndex: {
1151543Srgrimes      IdentifierInfo *KeyIdents[] = {
11683047Sobrien        &Ctx.Idents.get("replaceObjectAtIndex"),
117105014Smike        &Ctx.Idents.get("withObject")
118114349Speter      };
119119889Speter      Sel = Ctx.Selectors.getSelector(2, KeyIdents);
120114349Speter      break;
121114349Speter    }
122114349Speter    }
123119889Speter    return (NSArraySelectors[MK] = Sel);
124119889Speter  }
125114349Speter
126119889Speter  return NSArraySelectors[MK];
127119889Speter}
128119889Speter
129119889Speterllvm::Optional<NSAPI::NSArrayMethodKind>
130119889SpeterNSAPI::getNSArrayMethodKind(Selector Sel) {
131119889Speter  for (unsigned i = 0; i != NumNSArrayMethods; ++i) {
132119889Speter    NSArrayMethodKind MK = NSArrayMethodKind(i);
133119889Speter    if (Sel == getNSArraySelector(MK))
134190623Skib      return MK;
135190623Skib  }
136190623Skib
137119889Speter  return llvm::Optional<NSArrayMethodKind>();
138190623Skib}
139190623Skib
140190623SkibSelector NSAPI::getNSDictionarySelector(
141114349Speter                                       NSDictionaryMethodKind MK) const {
142114349Speter  if (NSDictionarySelectors[MK].isNull()) {
143114349Speter    Selector Sel;
144114349Speter    switch (MK) {
145114349Speter    case NSDict_dictionary:
146114349Speter      Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));
147114349Speter      break;
14853108Smarcel    case NSDict_dictionaryWithDictionary:
149227399Skib      Sel = Ctx.Selectors.getUnarySelector(
150227399Skib                                   &Ctx.Idents.get("dictionaryWithDictionary"));
15153108Smarcel      break;
152114349Speter    case NSDict_dictionaryWithObjectForKey: {
153114349Speter      IdentifierInfo *KeyIdents[] = {
154119888Speter        &Ctx.Idents.get("dictionaryWithObject"),
155190623Skib        &Ctx.Idents.get("forKey")
156190623Skib      };
157190623Skib      Sel = Ctx.Selectors.getSelector(2, KeyIdents);
158190623Skib      break;
159230765Skib    }
160230765Skib    case NSDict_dictionaryWithObjectsForKeys: {
161230765Skib      IdentifierInfo *KeyIdents[] = {
162230765Skib        &Ctx.Idents.get("dictionaryWithObjects"),
16351942Smarcel        &Ctx.Idents.get("forKeys")
164105014Smike      };
165247047Skib      Sel = Ctx.Selectors.getSelector(2, KeyIdents);
1669343Sbde      break;
167247047Skib    }
168    case NSDict_dictionaryWithObjectsForKeysCount: {
169      IdentifierInfo *KeyIdents[] = {
170        &Ctx.Idents.get("dictionaryWithObjects"),
171        &Ctx.Idents.get("forKeys"),
172        &Ctx.Idents.get("count")
173      };
174      Sel = Ctx.Selectors.getSelector(3, KeyIdents);
175      break;
176    }
177    case NSDict_dictionaryWithObjectsAndKeys:
178      Sel = Ctx.Selectors.getUnarySelector(
179                               &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));
180      break;
181    case NSDict_initWithDictionary:
182      Sel = Ctx.Selectors.getUnarySelector(
183                                         &Ctx.Idents.get("initWithDictionary"));
184      break;
185    case NSDict_initWithObjectsAndKeys:
186      Sel = Ctx.Selectors.getUnarySelector(
187                                     &Ctx.Idents.get("initWithObjectsAndKeys"));
188      break;
189    case NSDict_objectForKey:
190      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
191      break;
192    case NSMutableDict_setObjectForKey: {
193      IdentifierInfo *KeyIdents[] = {
194        &Ctx.Idents.get("setObject"),
195        &Ctx.Idents.get("forKey")
196      };
197      Sel = Ctx.Selectors.getSelector(2, KeyIdents);
198      break;
199    }
200    }
201    return (NSDictionarySelectors[MK] = Sel);
202  }
203
204  return NSDictionarySelectors[MK];
205}
206
207llvm::Optional<NSAPI::NSDictionaryMethodKind>
208NSAPI::getNSDictionaryMethodKind(Selector Sel) {
209  for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
210    NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
211    if (Sel == getNSDictionarySelector(MK))
212      return MK;
213  }
214
215  return llvm::Optional<NSDictionaryMethodKind>();
216}
217
218Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
219                                           bool Instance) const {
220  static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
221    "numberWithChar",
222    "numberWithUnsignedChar",
223    "numberWithShort",
224    "numberWithUnsignedShort",
225    "numberWithInt",
226    "numberWithUnsignedInt",
227    "numberWithLong",
228    "numberWithUnsignedLong",
229    "numberWithLongLong",
230    "numberWithUnsignedLongLong",
231    "numberWithFloat",
232    "numberWithDouble",
233    "numberWithBool",
234    "numberWithInteger",
235    "numberWithUnsignedInteger"
236  };
237  static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
238    "initWithChar",
239    "initWithUnsignedChar",
240    "initWithShort",
241    "initWithUnsignedShort",
242    "initWithInt",
243    "initWithUnsignedInt",
244    "initWithLong",
245    "initWithUnsignedLong",
246    "initWithLongLong",
247    "initWithUnsignedLongLong",
248    "initWithFloat",
249    "initWithDouble",
250    "initWithBool",
251    "initWithInteger",
252    "initWithUnsignedInteger"
253  };
254
255  Selector *Sels;
256  const char **Names;
257  if (Instance) {
258    Sels = NSNumberInstanceSelectors;
259    Names = InstanceSelectorName;
260  } else {
261    Sels = NSNumberClassSelectors;
262    Names = ClassSelectorName;
263  }
264
265  if (Sels[MK].isNull())
266    Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
267  return Sels[MK];
268}
269
270llvm::Optional<NSAPI::NSNumberLiteralMethodKind>
271NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
272  for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
273    NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
274    if (isNSNumberLiteralSelector(MK, Sel))
275      return MK;
276  }
277
278  return llvm::Optional<NSNumberLiteralMethodKind>();
279}
280
281llvm::Optional<NSAPI::NSNumberLiteralMethodKind>
282NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
283  const BuiltinType *BT = T->getAs<BuiltinType>();
284  if (!BT)
285    return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>();
286
287  const TypedefType *TDT = T->getAs<TypedefType>();
288  if (TDT) {
289    QualType TDTTy = QualType(TDT, 0);
290    if (isObjCBOOLType(TDTTy))
291      return NSAPI::NSNumberWithBool;
292    if (isObjCNSIntegerType(TDTTy))
293      return NSAPI::NSNumberWithInteger;
294    if (isObjCNSUIntegerType(TDTTy))
295      return NSAPI::NSNumberWithUnsignedInteger;
296  }
297
298  switch (BT->getKind()) {
299  case BuiltinType::Char_S:
300  case BuiltinType::SChar:
301    return NSAPI::NSNumberWithChar;
302  case BuiltinType::Char_U:
303  case BuiltinType::UChar:
304    return NSAPI::NSNumberWithUnsignedChar;
305  case BuiltinType::Short:
306    return NSAPI::NSNumberWithShort;
307  case BuiltinType::UShort:
308    return NSAPI::NSNumberWithUnsignedShort;
309  case BuiltinType::Int:
310    return NSAPI::NSNumberWithInt;
311  case BuiltinType::UInt:
312    return NSAPI::NSNumberWithUnsignedInt;
313  case BuiltinType::Long:
314    return NSAPI::NSNumberWithLong;
315  case BuiltinType::ULong:
316    return NSAPI::NSNumberWithUnsignedLong;
317  case BuiltinType::LongLong:
318    return NSAPI::NSNumberWithLongLong;
319  case BuiltinType::ULongLong:
320    return NSAPI::NSNumberWithUnsignedLongLong;
321  case BuiltinType::Float:
322    return NSAPI::NSNumberWithFloat;
323  case BuiltinType::Double:
324    return NSAPI::NSNumberWithDouble;
325  case BuiltinType::Bool:
326    return NSAPI::NSNumberWithBool;
327
328  case BuiltinType::Void:
329  case BuiltinType::WChar_U:
330  case BuiltinType::WChar_S:
331  case BuiltinType::Char16:
332  case BuiltinType::Char32:
333  case BuiltinType::Int128:
334  case BuiltinType::LongDouble:
335  case BuiltinType::UInt128:
336  case BuiltinType::NullPtr:
337  case BuiltinType::ObjCClass:
338  case BuiltinType::ObjCId:
339  case BuiltinType::ObjCSel:
340  case BuiltinType::BoundMember:
341  case BuiltinType::Dependent:
342  case BuiltinType::Overload:
343  case BuiltinType::UnknownAny:
344  case BuiltinType::ARCUnbridgedCast:
345  case BuiltinType::Half:
346  case BuiltinType::PseudoObject:
347    break;
348  }
349
350  return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>();
351}
352
353/// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
354bool NSAPI::isObjCBOOLType(QualType T) const {
355  return isObjCTypedef(T, "BOOL", BOOLId);
356}
357/// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
358bool NSAPI::isObjCNSIntegerType(QualType T) const {
359  return isObjCTypedef(T, "NSInteger", NSIntegerId);
360}
361/// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
362bool NSAPI::isObjCNSUIntegerType(QualType T) const {
363  return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
364}
365
366bool NSAPI::isObjCTypedef(QualType T,
367                          StringRef name, IdentifierInfo *&II) const {
368  if (!Ctx.getLangOpts().ObjC1)
369    return false;
370  if (T.isNull())
371    return false;
372
373  if (!II)
374    II = &Ctx.Idents.get(name);
375
376  while (const TypedefType *TDT = T->getAs<TypedefType>()) {
377    if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
378      return true;
379    T = TDT->desugar();
380  }
381
382  return false;
383}
384
385bool NSAPI::isObjCEnumerator(const Expr *E,
386                             StringRef name, IdentifierInfo *&II) const {
387  if (!Ctx.getLangOpts().ObjC1)
388    return false;
389  if (!E)
390    return false;
391
392  if (!II)
393    II = &Ctx.Idents.get(name);
394
395  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
396    if (const EnumConstantDecl *
397          EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl()))
398      return EnumD->getIdentifier() == II;
399
400  return false;
401}
402
403Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
404                                  Selector &Sel) const {
405  if (Sel.isNull()) {
406    SmallVector<IdentifierInfo *, 4> Idents;
407    for (ArrayRef<StringRef>::const_iterator
408           I = Ids.begin(), E = Ids.end(); I != E; ++I)
409      Idents.push_back(&Ctx.Idents.get(*I));
410    Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data());
411  }
412  return Sel;
413}
414