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 llvm::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))
78 return llvm::Optional<NSStringMethodKind>();
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 llvm::Optional<NSAPI::NSArrayMethodKind>
130 NSAPI::getNSArrayMethodKind(Selector Sel) {
131 for (unsigned i = 0; i != NumNSArrayMethods; ++i) {
132 NSArrayMethodKind MK = NSArrayMethodKind(i);
133 if (Sel == getNSArraySelector(MK))
137 return llvm::Optional<NSArrayMethodKind>();
140 Selector NSAPI::getNSDictionarySelector(
141 NSDictionaryMethodKind MK) const {
142 if (NSDictionarySelectors[MK].isNull()) {
145 case NSDict_dictionary:
146 Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));
148 case NSDict_dictionaryWithDictionary:
149 Sel = Ctx.Selectors.getUnarySelector(
150 &Ctx.Idents.get("dictionaryWithDictionary"));
152 case NSDict_dictionaryWithObjectForKey: {
153 IdentifierInfo *KeyIdents[] = {
154 &Ctx.Idents.get("dictionaryWithObject"),
155 &Ctx.Idents.get("forKey")
157 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
160 case NSDict_dictionaryWithObjectsForKeys: {
161 IdentifierInfo *KeyIdents[] = {
162 &Ctx.Idents.get("dictionaryWithObjects"),
163 &Ctx.Idents.get("forKeys")
165 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
168 case NSDict_dictionaryWithObjectsForKeysCount: {
169 IdentifierInfo *KeyIdents[] = {
170 &Ctx.Idents.get("dictionaryWithObjects"),
171 &Ctx.Idents.get("forKeys"),
172 &Ctx.Idents.get("count")
174 Sel = Ctx.Selectors.getSelector(3, KeyIdents);
177 case NSDict_dictionaryWithObjectsAndKeys:
178 Sel = Ctx.Selectors.getUnarySelector(
179 &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));
181 case NSDict_initWithDictionary:
182 Sel = Ctx.Selectors.getUnarySelector(
183 &Ctx.Idents.get("initWithDictionary"));
185 case NSDict_initWithObjectsAndKeys:
186 Sel = Ctx.Selectors.getUnarySelector(
187 &Ctx.Idents.get("initWithObjectsAndKeys"));
189 case NSDict_objectForKey:
190 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
192 case NSMutableDict_setObjectForKey: {
193 IdentifierInfo *KeyIdents[] = {
194 &Ctx.Idents.get("setObject"),
195 &Ctx.Idents.get("forKey")
197 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
201 return (NSDictionarySelectors[MK] = Sel);
204 return NSDictionarySelectors[MK];
207 llvm::Optional<NSAPI::NSDictionaryMethodKind>
208 NSAPI::getNSDictionaryMethodKind(Selector Sel) {
209 for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
210 NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
211 if (Sel == getNSDictionarySelector(MK))
215 return llvm::Optional<NSDictionaryMethodKind>();
218 Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
219 bool Instance) const {
220 static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
222 "numberWithUnsignedChar",
224 "numberWithUnsignedShort",
226 "numberWithUnsignedInt",
228 "numberWithUnsignedLong",
229 "numberWithLongLong",
230 "numberWithUnsignedLongLong",
235 "numberWithUnsignedInteger"
237 static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
239 "initWithUnsignedChar",
241 "initWithUnsignedShort",
243 "initWithUnsignedInt",
245 "initWithUnsignedLong",
247 "initWithUnsignedLongLong",
252 "initWithUnsignedInteger"
258 Sels = NSNumberInstanceSelectors;
259 Names = InstanceSelectorName;
261 Sels = NSNumberClassSelectors;
262 Names = ClassSelectorName;
265 if (Sels[MK].isNull())
266 Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
270 llvm::Optional<NSAPI::NSNumberLiteralMethodKind>
271 NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
272 for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
273 NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
274 if (isNSNumberLiteralSelector(MK, Sel))
278 return llvm::Optional<NSNumberLiteralMethodKind>();
281 llvm::Optional<NSAPI::NSNumberLiteralMethodKind>
282 NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
283 const BuiltinType *BT = T->getAs<BuiltinType>();
285 return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>();
287 const TypedefType *TDT = T->getAs<TypedefType>();
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;
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;
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 case BuiltinType::BuiltinFn:
351 return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>();
354 /// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
355 bool NSAPI::isObjCBOOLType(QualType T) const {
356 return isObjCTypedef(T, "BOOL", BOOLId);
358 /// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
359 bool NSAPI::isObjCNSIntegerType(QualType T) const {
360 return isObjCTypedef(T, "NSInteger", NSIntegerId);
362 /// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
363 bool NSAPI::isObjCNSUIntegerType(QualType T) const {
364 return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
367 bool NSAPI::isObjCTypedef(QualType T,
368 StringRef name, IdentifierInfo *&II) const {
369 if (!Ctx.getLangOpts().ObjC1)
375 II = &Ctx.Idents.get(name);
377 while (const TypedefType *TDT = T->getAs<TypedefType>()) {
378 if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
386 bool NSAPI::isObjCEnumerator(const Expr *E,
387 StringRef name, IdentifierInfo *&II) const {
388 if (!Ctx.getLangOpts().ObjC1)
394 II = &Ctx.Idents.get(name);
396 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
397 if (const EnumConstantDecl *
398 EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl()))
399 return EnumD->getIdentifier() == II;
404 Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
405 Selector &Sel) const {
407 SmallVector<IdentifierInfo *, 4> Idents;
408 for (ArrayRef<StringRef>::const_iterator
409 I = Ids.begin(), E = Ids.end(); I != E; ++I)
410 Idents.push_back(&Ctx.Idents.get(*I));
411 Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data());