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"
13 #include "llvm/ADT/StringSwitch.h"
15 using namespace clang
;
17 NSAPI::NSAPI(ASTContext
&ctx
)
18 : Ctx(ctx
), ClassIds(), BOOLId(nullptr), NSIntegerId(nullptr),
19 NSUIntegerId(nullptr), NSASCIIStringEncodingId(nullptr),
20 NSUTF8StringEncodingId(nullptr) {}
22 IdentifierInfo
*NSAPI::getNSClassId(NSClassIdKindKind K
) const {
23 static const char *ClassName
[NumClassIds
] = {
29 "NSMutableDictionary",
34 return (ClassIds
[K
] = &Ctx
.Idents
.get(ClassName
[K
]));
39 Selector
NSAPI::getNSStringSelector(NSStringMethodKind MK
) const {
40 if (NSStringSelectors
[MK
].isNull()) {
43 case NSStr_stringWithString
:
44 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("stringWithString"));
46 case NSStr_stringWithUTF8String
:
47 Sel
= Ctx
.Selectors
.getUnarySelector(
48 &Ctx
.Idents
.get("stringWithUTF8String"));
50 case NSStr_initWithUTF8String
:
51 Sel
= Ctx
.Selectors
.getUnarySelector(
52 &Ctx
.Idents
.get("initWithUTF8String"));
54 case NSStr_stringWithCStringEncoding
: {
55 IdentifierInfo
*KeyIdents
[] = {
56 &Ctx
.Idents
.get("stringWithCString"),
57 &Ctx
.Idents
.get("encoding")
59 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
62 case NSStr_stringWithCString
:
63 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("stringWithCString"));
65 case NSStr_initWithString
:
66 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("initWithString"));
69 return (NSStringSelectors
[MK
] = Sel
);
72 return NSStringSelectors
[MK
];
75 Optional
<NSAPI::NSStringMethodKind
>
76 NSAPI::getNSStringMethodKind(Selector Sel
) const {
77 for (unsigned i
= 0; i
!= NumNSStringMethods
; ++i
) {
78 NSStringMethodKind MK
= NSStringMethodKind(i
);
79 if (Sel
== getNSStringSelector(MK
))
86 Selector
NSAPI::getNSArraySelector(NSArrayMethodKind MK
) const {
87 if (NSArraySelectors
[MK
].isNull()) {
91 Sel
= Ctx
.Selectors
.getNullarySelector(&Ctx
.Idents
.get("array"));
93 case NSArr_arrayWithArray
:
94 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("arrayWithArray"));
96 case NSArr_arrayWithObject
:
97 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("arrayWithObject"));
99 case NSArr_arrayWithObjects
:
100 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("arrayWithObjects"));
102 case NSArr_arrayWithObjectsCount
: {
103 IdentifierInfo
*KeyIdents
[] = {
104 &Ctx
.Idents
.get("arrayWithObjects"),
105 &Ctx
.Idents
.get("count")
107 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
110 case NSArr_initWithArray
:
111 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("initWithArray"));
113 case NSArr_initWithObjects
:
114 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("initWithObjects"));
116 case NSArr_objectAtIndex
:
117 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("objectAtIndex"));
119 case NSMutableArr_replaceObjectAtIndex
: {
120 IdentifierInfo
*KeyIdents
[] = {
121 &Ctx
.Idents
.get("replaceObjectAtIndex"),
122 &Ctx
.Idents
.get("withObject")
124 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
128 return (NSArraySelectors
[MK
] = Sel
);
131 return NSArraySelectors
[MK
];
134 Optional
<NSAPI::NSArrayMethodKind
> NSAPI::getNSArrayMethodKind(Selector Sel
) {
135 for (unsigned i
= 0; i
!= NumNSArrayMethods
; ++i
) {
136 NSArrayMethodKind MK
= NSArrayMethodKind(i
);
137 if (Sel
== getNSArraySelector(MK
))
144 Selector
NSAPI::getNSDictionarySelector(
145 NSDictionaryMethodKind MK
) const {
146 if (NSDictionarySelectors
[MK
].isNull()) {
149 case NSDict_dictionary
:
150 Sel
= Ctx
.Selectors
.getNullarySelector(&Ctx
.Idents
.get("dictionary"));
152 case NSDict_dictionaryWithDictionary
:
153 Sel
= Ctx
.Selectors
.getUnarySelector(
154 &Ctx
.Idents
.get("dictionaryWithDictionary"));
156 case NSDict_dictionaryWithObjectForKey
: {
157 IdentifierInfo
*KeyIdents
[] = {
158 &Ctx
.Idents
.get("dictionaryWithObject"),
159 &Ctx
.Idents
.get("forKey")
161 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
164 case NSDict_dictionaryWithObjectsForKeys
: {
165 IdentifierInfo
*KeyIdents
[] = {
166 &Ctx
.Idents
.get("dictionaryWithObjects"),
167 &Ctx
.Idents
.get("forKeys")
169 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
172 case NSDict_dictionaryWithObjectsForKeysCount
: {
173 IdentifierInfo
*KeyIdents
[] = {
174 &Ctx
.Idents
.get("dictionaryWithObjects"),
175 &Ctx
.Idents
.get("forKeys"),
176 &Ctx
.Idents
.get("count")
178 Sel
= Ctx
.Selectors
.getSelector(3, KeyIdents
);
181 case NSDict_dictionaryWithObjectsAndKeys
:
182 Sel
= Ctx
.Selectors
.getUnarySelector(
183 &Ctx
.Idents
.get("dictionaryWithObjectsAndKeys"));
185 case NSDict_initWithDictionary
:
186 Sel
= Ctx
.Selectors
.getUnarySelector(
187 &Ctx
.Idents
.get("initWithDictionary"));
189 case NSDict_initWithObjectsAndKeys
:
190 Sel
= Ctx
.Selectors
.getUnarySelector(
191 &Ctx
.Idents
.get("initWithObjectsAndKeys"));
193 case NSDict_initWithObjectsForKeys
: {
194 IdentifierInfo
*KeyIdents
[] = {
195 &Ctx
.Idents
.get("initWithObjects"),
196 &Ctx
.Idents
.get("forKeys")
198 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
201 case NSDict_objectForKey
:
202 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("objectForKey"));
204 case NSMutableDict_setObjectForKey
: {
205 IdentifierInfo
*KeyIdents
[] = {
206 &Ctx
.Idents
.get("setObject"),
207 &Ctx
.Idents
.get("forKey")
209 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
213 return (NSDictionarySelectors
[MK
] = Sel
);
216 return NSDictionarySelectors
[MK
];
219 Optional
<NSAPI::NSDictionaryMethodKind
>
220 NSAPI::getNSDictionaryMethodKind(Selector Sel
) {
221 for (unsigned i
= 0; i
!= NumNSDictionaryMethods
; ++i
) {
222 NSDictionaryMethodKind MK
= NSDictionaryMethodKind(i
);
223 if (Sel
== getNSDictionarySelector(MK
))
230 Selector
NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK
,
231 bool Instance
) const {
232 static const char *ClassSelectorName
[NumNSNumberLiteralMethods
] = {
234 "numberWithUnsignedChar",
236 "numberWithUnsignedShort",
238 "numberWithUnsignedInt",
240 "numberWithUnsignedLong",
241 "numberWithLongLong",
242 "numberWithUnsignedLongLong",
247 "numberWithUnsignedInteger"
249 static const char *InstanceSelectorName
[NumNSNumberLiteralMethods
] = {
251 "initWithUnsignedChar",
253 "initWithUnsignedShort",
255 "initWithUnsignedInt",
257 "initWithUnsignedLong",
259 "initWithUnsignedLongLong",
264 "initWithUnsignedInteger"
270 Sels
= NSNumberInstanceSelectors
;
271 Names
= InstanceSelectorName
;
273 Sels
= NSNumberClassSelectors
;
274 Names
= ClassSelectorName
;
277 if (Sels
[MK
].isNull())
278 Sels
[MK
] = Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get(Names
[MK
]));
282 Optional
<NSAPI::NSNumberLiteralMethodKind
>
283 NSAPI::getNSNumberLiteralMethodKind(Selector Sel
) const {
284 for (unsigned i
= 0; i
!= NumNSNumberLiteralMethods
; ++i
) {
285 NSNumberLiteralMethodKind MK
= NSNumberLiteralMethodKind(i
);
286 if (isNSNumberLiteralSelector(MK
, Sel
))
293 Optional
<NSAPI::NSNumberLiteralMethodKind
>
294 NSAPI::getNSNumberFactoryMethodKind(QualType T
) const {
295 const BuiltinType
*BT
= T
->getAs
<BuiltinType
>();
299 const TypedefType
*TDT
= T
->getAs
<TypedefType
>();
301 QualType TDTTy
= QualType(TDT
, 0);
302 if (isObjCBOOLType(TDTTy
))
303 return NSAPI::NSNumberWithBool
;
304 if (isObjCNSIntegerType(TDTTy
))
305 return NSAPI::NSNumberWithInteger
;
306 if (isObjCNSUIntegerType(TDTTy
))
307 return NSAPI::NSNumberWithUnsignedInteger
;
310 switch (BT
->getKind()) {
311 case BuiltinType::Char_S
:
312 case BuiltinType::SChar
:
313 return NSAPI::NSNumberWithChar
;
314 case BuiltinType::Char_U
:
315 case BuiltinType::UChar
:
316 return NSAPI::NSNumberWithUnsignedChar
;
317 case BuiltinType::Short
:
318 return NSAPI::NSNumberWithShort
;
319 case BuiltinType::UShort
:
320 return NSAPI::NSNumberWithUnsignedShort
;
321 case BuiltinType::Int
:
322 return NSAPI::NSNumberWithInt
;
323 case BuiltinType::UInt
:
324 return NSAPI::NSNumberWithUnsignedInt
;
325 case BuiltinType::Long
:
326 return NSAPI::NSNumberWithLong
;
327 case BuiltinType::ULong
:
328 return NSAPI::NSNumberWithUnsignedLong
;
329 case BuiltinType::LongLong
:
330 return NSAPI::NSNumberWithLongLong
;
331 case BuiltinType::ULongLong
:
332 return NSAPI::NSNumberWithUnsignedLongLong
;
333 case BuiltinType::Float
:
334 return NSAPI::NSNumberWithFloat
;
335 case BuiltinType::Double
:
336 return NSAPI::NSNumberWithDouble
;
337 case BuiltinType::Bool
:
338 return NSAPI::NSNumberWithBool
;
340 case BuiltinType::Void
:
341 case BuiltinType::WChar_U
:
342 case BuiltinType::WChar_S
:
343 case BuiltinType::Char16
:
344 case BuiltinType::Char32
:
345 case BuiltinType::Int128
:
346 case BuiltinType::LongDouble
:
347 case BuiltinType::UInt128
:
348 case BuiltinType::NullPtr
:
349 case BuiltinType::ObjCClass
:
350 case BuiltinType::ObjCId
:
351 case BuiltinType::ObjCSel
:
352 case BuiltinType::OCLImage1d
:
353 case BuiltinType::OCLImage1dArray
:
354 case BuiltinType::OCLImage1dBuffer
:
355 case BuiltinType::OCLImage2d
:
356 case BuiltinType::OCLImage2dArray
:
357 case BuiltinType::OCLImage3d
:
358 case BuiltinType::OCLSampler
:
359 case BuiltinType::OCLEvent
:
360 case BuiltinType::BoundMember
:
361 case BuiltinType::Dependent
:
362 case BuiltinType::Overload
:
363 case BuiltinType::UnknownAny
:
364 case BuiltinType::ARCUnbridgedCast
:
365 case BuiltinType::Half
:
366 case BuiltinType::PseudoObject
:
367 case BuiltinType::BuiltinFn
:
374 /// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
375 bool NSAPI::isObjCBOOLType(QualType T
) const {
376 return isObjCTypedef(T
, "BOOL", BOOLId
);
378 /// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
379 bool NSAPI::isObjCNSIntegerType(QualType T
) const {
380 return isObjCTypedef(T
, "NSInteger", NSIntegerId
);
382 /// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
383 bool NSAPI::isObjCNSUIntegerType(QualType T
) const {
384 return isObjCTypedef(T
, "NSUInteger", NSUIntegerId
);
387 StringRef
NSAPI::GetNSIntegralKind(QualType T
) const {
388 if (!Ctx
.getLangOpts().ObjC1
|| T
.isNull())
391 while (const TypedefType
*TDT
= T
->getAs
<TypedefType
>()) {
392 StringRef NSIntegralResust
=
393 llvm::StringSwitch
<StringRef
>(
394 TDT
->getDecl()->getDeclName().getAsIdentifierInfo()->getName())
395 .Case("int8_t", "int8_t")
396 .Case("int16_t", "int16_t")
397 .Case("int32_t", "int32_t")
398 .Case("NSInteger", "NSInteger")
399 .Case("int64_t", "int64_t")
400 .Case("uint8_t", "uint8_t")
401 .Case("uint16_t", "uint16_t")
402 .Case("uint32_t", "uint32_t")
403 .Case("NSUInteger", "NSUInteger")
404 .Case("uint64_t", "uint64_t")
405 .Default(StringRef());
406 if (!NSIntegralResust
.empty())
407 return NSIntegralResust
;
413 bool NSAPI::isObjCTypedef(QualType T
,
414 StringRef name
, IdentifierInfo
*&II
) const {
415 if (!Ctx
.getLangOpts().ObjC1
)
421 II
= &Ctx
.Idents
.get(name
);
423 while (const TypedefType
*TDT
= T
->getAs
<TypedefType
>()) {
424 if (TDT
->getDecl()->getDeclName().getAsIdentifierInfo() == II
)
432 bool NSAPI::isObjCEnumerator(const Expr
*E
,
433 StringRef name
, IdentifierInfo
*&II
) const {
434 if (!Ctx
.getLangOpts().ObjC1
)
440 II
= &Ctx
.Idents
.get(name
);
442 if (const DeclRefExpr
*DRE
= dyn_cast
<DeclRefExpr
>(E
->IgnoreParenImpCasts()))
443 if (const EnumConstantDecl
*
444 EnumD
= dyn_cast_or_null
<EnumConstantDecl
>(DRE
->getDecl()))
445 return EnumD
->getIdentifier() == II
;
450 Selector
NSAPI::getOrInitSelector(ArrayRef
<StringRef
> Ids
,
451 Selector
&Sel
) const {
453 SmallVector
<IdentifierInfo
*, 4> Idents
;
454 for (ArrayRef
<StringRef
>::const_iterator
455 I
= Ids
.begin(), E
= Ids
.end(); I
!= E
; ++I
)
456 Idents
.push_back(&Ctx
.Idents
.get(*I
));
457 Sel
= Ctx
.Selectors
.getSelector(Idents
.size(), Idents
.data());