1234287Sdim//===--- NSAPI.cpp - NSFoundation APIs ------------------------------------===//
2234287Sdim//
3234287Sdim//                     The LLVM Compiler Infrastructure
4234287Sdim//
5234287Sdim// This file is distributed under the University of Illinois Open Source
6234287Sdim// License. See LICENSE.TXT for details.
7234287Sdim//
8234287Sdim//===----------------------------------------------------------------------===//
9234287Sdim
10234287Sdim#include "clang/AST/NSAPI.h"
11234287Sdim#include "clang/AST/ASTContext.h"
12239462Sdim#include "clang/AST/Expr.h"
13234287Sdim
14234287Sdimusing namespace clang;
15234287Sdim
16234287SdimNSAPI::NSAPI(ASTContext &ctx)
17239462Sdim  : Ctx(ctx), ClassIds(), BOOLId(0), NSIntegerId(0), NSUIntegerId(0),
18239462Sdim    NSASCIIStringEncodingId(0), NSUTF8StringEncodingId(0) {
19234287Sdim}
20234287Sdim
21234287SdimIdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
22234287Sdim  static const char *ClassName[NumClassIds] = {
23234287Sdim    "NSObject",
24234287Sdim    "NSString",
25234287Sdim    "NSArray",
26234287Sdim    "NSMutableArray",
27234287Sdim    "NSDictionary",
28234287Sdim    "NSMutableDictionary",
29234287Sdim    "NSNumber"
30234287Sdim  };
31234287Sdim
32234287Sdim  if (!ClassIds[K])
33234287Sdim    return (ClassIds[K] = &Ctx.Idents.get(ClassName[K]));
34234287Sdim
35234287Sdim  return ClassIds[K];
36234287Sdim}
37234287Sdim
38234287SdimSelector NSAPI::getNSStringSelector(NSStringMethodKind MK) const {
39234287Sdim  if (NSStringSelectors[MK].isNull()) {
40234287Sdim    Selector Sel;
41234287Sdim    switch (MK) {
42234287Sdim    case NSStr_stringWithString:
43234287Sdim      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString"));
44234287Sdim      break;
45239462Sdim    case NSStr_stringWithUTF8String:
46239462Sdim      Sel = Ctx.Selectors.getUnarySelector(
47239462Sdim                                       &Ctx.Idents.get("stringWithUTF8String"));
48239462Sdim      break;
49239462Sdim    case NSStr_stringWithCStringEncoding: {
50239462Sdim      IdentifierInfo *KeyIdents[] = {
51239462Sdim        &Ctx.Idents.get("stringWithCString"),
52239462Sdim        &Ctx.Idents.get("encoding")
53239462Sdim      };
54239462Sdim      Sel = Ctx.Selectors.getSelector(2, KeyIdents);
55239462Sdim      break;
56239462Sdim    }
57239462Sdim    case NSStr_stringWithCString:
58239462Sdim      Sel= Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithCString"));
59239462Sdim      break;
60234287Sdim    case NSStr_initWithString:
61234287Sdim      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString"));
62234287Sdim      break;
63234287Sdim    }
64234287Sdim    return (NSStringSelectors[MK] = Sel);
65234287Sdim  }
66234287Sdim
67234287Sdim  return NSStringSelectors[MK];
68234287Sdim}
69234287Sdim
70249423SdimOptional<NSAPI::NSStringMethodKind>
71239462SdimNSAPI::getNSStringMethodKind(Selector Sel) const {
72239462Sdim  for (unsigned i = 0; i != NumNSStringMethods; ++i) {
73239462Sdim    NSStringMethodKind MK = NSStringMethodKind(i);
74239462Sdim    if (Sel == getNSStringSelector(MK))
75239462Sdim      return MK;
76239462Sdim  }
77239462Sdim
78249423Sdim  return None;
79239462Sdim}
80239462Sdim
81234287SdimSelector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {
82234287Sdim  if (NSArraySelectors[MK].isNull()) {
83234287Sdim    Selector Sel;
84234287Sdim    switch (MK) {
85234287Sdim    case NSArr_array:
86234287Sdim      Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("array"));
87234287Sdim      break;
88234287Sdim    case NSArr_arrayWithArray:
89234287Sdim      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithArray"));
90234287Sdim      break;
91234287Sdim    case NSArr_arrayWithObject:
92234287Sdim      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObject"));
93234287Sdim      break;
94234287Sdim    case NSArr_arrayWithObjects:
95234287Sdim      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects"));
96234287Sdim      break;
97234287Sdim    case NSArr_arrayWithObjectsCount: {
98234287Sdim      IdentifierInfo *KeyIdents[] = {
99234287Sdim        &Ctx.Idents.get("arrayWithObjects"),
100234287Sdim        &Ctx.Idents.get("count")
101234287Sdim      };
102234287Sdim      Sel = Ctx.Selectors.getSelector(2, KeyIdents);
103234287Sdim      break;
104234287Sdim    }
105234287Sdim    case NSArr_initWithArray:
106234287Sdim      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithArray"));
107234287Sdim      break;
108234287Sdim    case NSArr_initWithObjects:
109234287Sdim      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithObjects"));
110234287Sdim      break;
111234287Sdim    case NSArr_objectAtIndex:
112234287Sdim      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex"));
113234287Sdim      break;
114234287Sdim    case NSMutableArr_replaceObjectAtIndex: {
115234287Sdim      IdentifierInfo *KeyIdents[] = {
116234287Sdim        &Ctx.Idents.get("replaceObjectAtIndex"),
117234287Sdim        &Ctx.Idents.get("withObject")
118234287Sdim      };
119234287Sdim      Sel = Ctx.Selectors.getSelector(2, KeyIdents);
120234287Sdim      break;
121234287Sdim    }
122234287Sdim    }
123234287Sdim    return (NSArraySelectors[MK] = Sel);
124234287Sdim  }
125234287Sdim
126234287Sdim  return NSArraySelectors[MK];
127234287Sdim}
128234287Sdim
129249423SdimOptional<NSAPI::NSArrayMethodKind> NSAPI::getNSArrayMethodKind(Selector Sel) {
130234287Sdim  for (unsigned i = 0; i != NumNSArrayMethods; ++i) {
131234287Sdim    NSArrayMethodKind MK = NSArrayMethodKind(i);
132234287Sdim    if (Sel == getNSArraySelector(MK))
133234287Sdim      return MK;
134234287Sdim  }
135234287Sdim
136249423Sdim  return None;
137234287Sdim}
138234287Sdim
139234287SdimSelector NSAPI::getNSDictionarySelector(
140234287Sdim                                       NSDictionaryMethodKind MK) const {
141234287Sdim  if (NSDictionarySelectors[MK].isNull()) {
142234287Sdim    Selector Sel;
143234287Sdim    switch (MK) {
144234287Sdim    case NSDict_dictionary:
145234287Sdim      Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));
146234287Sdim      break;
147234287Sdim    case NSDict_dictionaryWithDictionary:
148234287Sdim      Sel = Ctx.Selectors.getUnarySelector(
149234287Sdim                                   &Ctx.Idents.get("dictionaryWithDictionary"));
150234287Sdim      break;
151234287Sdim    case NSDict_dictionaryWithObjectForKey: {
152234287Sdim      IdentifierInfo *KeyIdents[] = {
153234287Sdim        &Ctx.Idents.get("dictionaryWithObject"),
154234287Sdim        &Ctx.Idents.get("forKey")
155234287Sdim      };
156234287Sdim      Sel = Ctx.Selectors.getSelector(2, KeyIdents);
157234287Sdim      break;
158234287Sdim    }
159234287Sdim    case NSDict_dictionaryWithObjectsForKeys: {
160234287Sdim      IdentifierInfo *KeyIdents[] = {
161234287Sdim        &Ctx.Idents.get("dictionaryWithObjects"),
162234287Sdim        &Ctx.Idents.get("forKeys")
163234287Sdim      };
164234287Sdim      Sel = Ctx.Selectors.getSelector(2, KeyIdents);
165234287Sdim      break;
166234287Sdim    }
167234287Sdim    case NSDict_dictionaryWithObjectsForKeysCount: {
168234287Sdim      IdentifierInfo *KeyIdents[] = {
169234287Sdim        &Ctx.Idents.get("dictionaryWithObjects"),
170234287Sdim        &Ctx.Idents.get("forKeys"),
171234287Sdim        &Ctx.Idents.get("count")
172234287Sdim      };
173234287Sdim      Sel = Ctx.Selectors.getSelector(3, KeyIdents);
174234287Sdim      break;
175234287Sdim    }
176234287Sdim    case NSDict_dictionaryWithObjectsAndKeys:
177234287Sdim      Sel = Ctx.Selectors.getUnarySelector(
178234287Sdim                               &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));
179234287Sdim      break;
180234287Sdim    case NSDict_initWithDictionary:
181234287Sdim      Sel = Ctx.Selectors.getUnarySelector(
182234287Sdim                                         &Ctx.Idents.get("initWithDictionary"));
183234287Sdim      break;
184234287Sdim    case NSDict_initWithObjectsAndKeys:
185234287Sdim      Sel = Ctx.Selectors.getUnarySelector(
186234287Sdim                                     &Ctx.Idents.get("initWithObjectsAndKeys"));
187234287Sdim      break;
188249423Sdim    case NSDict_initWithObjectsForKeys: {
189249423Sdim      IdentifierInfo *KeyIdents[] = {
190249423Sdim        &Ctx.Idents.get("initWithObjects"),
191249423Sdim        &Ctx.Idents.get("forKeys")
192249423Sdim      };
193249423Sdim      Sel = Ctx.Selectors.getSelector(2, KeyIdents);
194249423Sdim      break;
195249423Sdim    }
196234287Sdim    case NSDict_objectForKey:
197234287Sdim      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
198234287Sdim      break;
199234287Sdim    case NSMutableDict_setObjectForKey: {
200234287Sdim      IdentifierInfo *KeyIdents[] = {
201234287Sdim        &Ctx.Idents.get("setObject"),
202234287Sdim        &Ctx.Idents.get("forKey")
203234287Sdim      };
204234287Sdim      Sel = Ctx.Selectors.getSelector(2, KeyIdents);
205234287Sdim      break;
206234287Sdim    }
207234287Sdim    }
208234287Sdim    return (NSDictionarySelectors[MK] = Sel);
209234287Sdim  }
210234287Sdim
211234287Sdim  return NSDictionarySelectors[MK];
212234287Sdim}
213234287Sdim
214249423SdimOptional<NSAPI::NSDictionaryMethodKind>
215234287SdimNSAPI::getNSDictionaryMethodKind(Selector Sel) {
216234287Sdim  for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
217234287Sdim    NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
218234287Sdim    if (Sel == getNSDictionarySelector(MK))
219234287Sdim      return MK;
220234287Sdim  }
221234287Sdim
222249423Sdim  return None;
223234287Sdim}
224234287Sdim
225234287SdimSelector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
226234287Sdim                                           bool Instance) const {
227234287Sdim  static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
228234287Sdim    "numberWithChar",
229234287Sdim    "numberWithUnsignedChar",
230234287Sdim    "numberWithShort",
231234287Sdim    "numberWithUnsignedShort",
232234287Sdim    "numberWithInt",
233234287Sdim    "numberWithUnsignedInt",
234234287Sdim    "numberWithLong",
235234287Sdim    "numberWithUnsignedLong",
236234287Sdim    "numberWithLongLong",
237234287Sdim    "numberWithUnsignedLongLong",
238234287Sdim    "numberWithFloat",
239234287Sdim    "numberWithDouble",
240234287Sdim    "numberWithBool",
241234287Sdim    "numberWithInteger",
242234287Sdim    "numberWithUnsignedInteger"
243234287Sdim  };
244234287Sdim  static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
245234287Sdim    "initWithChar",
246234287Sdim    "initWithUnsignedChar",
247234287Sdim    "initWithShort",
248234287Sdim    "initWithUnsignedShort",
249234287Sdim    "initWithInt",
250234287Sdim    "initWithUnsignedInt",
251234287Sdim    "initWithLong",
252234287Sdim    "initWithUnsignedLong",
253234287Sdim    "initWithLongLong",
254234287Sdim    "initWithUnsignedLongLong",
255234287Sdim    "initWithFloat",
256234287Sdim    "initWithDouble",
257234287Sdim    "initWithBool",
258234287Sdim    "initWithInteger",
259234287Sdim    "initWithUnsignedInteger"
260234287Sdim  };
261234287Sdim
262234287Sdim  Selector *Sels;
263234287Sdim  const char **Names;
264234287Sdim  if (Instance) {
265234287Sdim    Sels = NSNumberInstanceSelectors;
266234287Sdim    Names = InstanceSelectorName;
267234287Sdim  } else {
268234287Sdim    Sels = NSNumberClassSelectors;
269234287Sdim    Names = ClassSelectorName;
270234287Sdim  }
271234287Sdim
272234287Sdim  if (Sels[MK].isNull())
273234287Sdim    Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
274234287Sdim  return Sels[MK];
275234287Sdim}
276234287Sdim
277249423SdimOptional<NSAPI::NSNumberLiteralMethodKind>
278234287SdimNSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
279234287Sdim  for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
280234287Sdim    NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
281234287Sdim    if (isNSNumberLiteralSelector(MK, Sel))
282234287Sdim      return MK;
283234287Sdim  }
284234287Sdim
285249423Sdim  return None;
286234287Sdim}
287234287Sdim
288249423SdimOptional<NSAPI::NSNumberLiteralMethodKind>
289239462SdimNSAPI::getNSNumberFactoryMethodKind(QualType T) const {
290234287Sdim  const BuiltinType *BT = T->getAs<BuiltinType>();
291234287Sdim  if (!BT)
292249423Sdim    return None;
293239462Sdim
294239462Sdim  const TypedefType *TDT = T->getAs<TypedefType>();
295239462Sdim  if (TDT) {
296239462Sdim    QualType TDTTy = QualType(TDT, 0);
297239462Sdim    if (isObjCBOOLType(TDTTy))
298239462Sdim      return NSAPI::NSNumberWithBool;
299239462Sdim    if (isObjCNSIntegerType(TDTTy))
300239462Sdim      return NSAPI::NSNumberWithInteger;
301239462Sdim    if (isObjCNSUIntegerType(TDTTy))
302239462Sdim      return NSAPI::NSNumberWithUnsignedInteger;
303239462Sdim  }
304239462Sdim
305234287Sdim  switch (BT->getKind()) {
306234287Sdim  case BuiltinType::Char_S:
307234287Sdim  case BuiltinType::SChar:
308234287Sdim    return NSAPI::NSNumberWithChar;
309234287Sdim  case BuiltinType::Char_U:
310234287Sdim  case BuiltinType::UChar:
311234287Sdim    return NSAPI::NSNumberWithUnsignedChar;
312234287Sdim  case BuiltinType::Short:
313234287Sdim    return NSAPI::NSNumberWithShort;
314234287Sdim  case BuiltinType::UShort:
315234287Sdim    return NSAPI::NSNumberWithUnsignedShort;
316234287Sdim  case BuiltinType::Int:
317234287Sdim    return NSAPI::NSNumberWithInt;
318234287Sdim  case BuiltinType::UInt:
319234287Sdim    return NSAPI::NSNumberWithUnsignedInt;
320234287Sdim  case BuiltinType::Long:
321234287Sdim    return NSAPI::NSNumberWithLong;
322234287Sdim  case BuiltinType::ULong:
323234287Sdim    return NSAPI::NSNumberWithUnsignedLong;
324234287Sdim  case BuiltinType::LongLong:
325234287Sdim    return NSAPI::NSNumberWithLongLong;
326234287Sdim  case BuiltinType::ULongLong:
327234287Sdim    return NSAPI::NSNumberWithUnsignedLongLong;
328234287Sdim  case BuiltinType::Float:
329234287Sdim    return NSAPI::NSNumberWithFloat;
330234287Sdim  case BuiltinType::Double:
331234287Sdim    return NSAPI::NSNumberWithDouble;
332234287Sdim  case BuiltinType::Bool:
333234287Sdim    return NSAPI::NSNumberWithBool;
334234287Sdim
335234287Sdim  case BuiltinType::Void:
336234287Sdim  case BuiltinType::WChar_U:
337234287Sdim  case BuiltinType::WChar_S:
338234287Sdim  case BuiltinType::Char16:
339234287Sdim  case BuiltinType::Char32:
340234287Sdim  case BuiltinType::Int128:
341234287Sdim  case BuiltinType::LongDouble:
342234287Sdim  case BuiltinType::UInt128:
343234287Sdim  case BuiltinType::NullPtr:
344234287Sdim  case BuiltinType::ObjCClass:
345234287Sdim  case BuiltinType::ObjCId:
346234287Sdim  case BuiltinType::ObjCSel:
347249423Sdim  case BuiltinType::OCLImage1d:
348249423Sdim  case BuiltinType::OCLImage1dArray:
349249423Sdim  case BuiltinType::OCLImage1dBuffer:
350249423Sdim  case BuiltinType::OCLImage2d:
351249423Sdim  case BuiltinType::OCLImage2dArray:
352249423Sdim  case BuiltinType::OCLImage3d:
353249423Sdim  case BuiltinType::OCLSampler:
354249423Sdim  case BuiltinType::OCLEvent:
355234287Sdim  case BuiltinType::BoundMember:
356234287Sdim  case BuiltinType::Dependent:
357234287Sdim  case BuiltinType::Overload:
358234287Sdim  case BuiltinType::UnknownAny:
359234287Sdim  case BuiltinType::ARCUnbridgedCast:
360234287Sdim  case BuiltinType::Half:
361234287Sdim  case BuiltinType::PseudoObject:
362243830Sdim  case BuiltinType::BuiltinFn:
363234287Sdim    break;
364234287Sdim  }
365234287Sdim
366249423Sdim  return None;
367234287Sdim}
368239462Sdim
369239462Sdim/// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
370239462Sdimbool NSAPI::isObjCBOOLType(QualType T) const {
371239462Sdim  return isObjCTypedef(T, "BOOL", BOOLId);
372239462Sdim}
373239462Sdim/// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
374239462Sdimbool NSAPI::isObjCNSIntegerType(QualType T) const {
375239462Sdim  return isObjCTypedef(T, "NSInteger", NSIntegerId);
376239462Sdim}
377239462Sdim/// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
378239462Sdimbool NSAPI::isObjCNSUIntegerType(QualType T) const {
379239462Sdim  return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
380239462Sdim}
381239462Sdim
382239462Sdimbool NSAPI::isObjCTypedef(QualType T,
383239462Sdim                          StringRef name, IdentifierInfo *&II) const {
384239462Sdim  if (!Ctx.getLangOpts().ObjC1)
385239462Sdim    return false;
386239462Sdim  if (T.isNull())
387239462Sdim    return false;
388239462Sdim
389239462Sdim  if (!II)
390239462Sdim    II = &Ctx.Idents.get(name);
391239462Sdim
392239462Sdim  while (const TypedefType *TDT = T->getAs<TypedefType>()) {
393239462Sdim    if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
394239462Sdim      return true;
395239462Sdim    T = TDT->desugar();
396239462Sdim  }
397239462Sdim
398239462Sdim  return false;
399239462Sdim}
400239462Sdim
401239462Sdimbool NSAPI::isObjCEnumerator(const Expr *E,
402239462Sdim                             StringRef name, IdentifierInfo *&II) const {
403239462Sdim  if (!Ctx.getLangOpts().ObjC1)
404239462Sdim    return false;
405239462Sdim  if (!E)
406239462Sdim    return false;
407239462Sdim
408239462Sdim  if (!II)
409239462Sdim    II = &Ctx.Idents.get(name);
410239462Sdim
411239462Sdim  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
412239462Sdim    if (const EnumConstantDecl *
413239462Sdim          EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl()))
414239462Sdim      return EnumD->getIdentifier() == II;
415239462Sdim
416239462Sdim  return false;
417239462Sdim}
418239462Sdim
419239462SdimSelector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
420239462Sdim                                  Selector &Sel) const {
421239462Sdim  if (Sel.isNull()) {
422239462Sdim    SmallVector<IdentifierInfo *, 4> Idents;
423239462Sdim    for (ArrayRef<StringRef>::const_iterator
424239462Sdim           I = Ids.begin(), E = Ids.end(); I != E; ++I)
425239462Sdim      Idents.push_back(&Ctx.Idents.get(*I));
426239462Sdim    Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data());
427239462Sdim  }
428239462Sdim  return Sel;
429239462Sdim}
430