612 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			612 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===--- NSAPI.cpp - NSFoundation APIs ------------------------------------===//
 | |
| //
 | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | |
| // See https://llvm.org/LICENSE.txt for license information.
 | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "clang/AST/NSAPI.h"
 | |
| #include "clang/AST/ASTContext.h"
 | |
| #include "clang/AST/DeclObjC.h"
 | |
| #include "clang/AST/Expr.h"
 | |
| #include "llvm/ADT/StringSwitch.h"
 | |
| 
 | |
| using namespace clang;
 | |
| 
 | |
| NSAPI::NSAPI(ASTContext &ctx)
 | |
|   : Ctx(ctx), ClassIds(), BOOLId(nullptr), NSIntegerId(nullptr),
 | |
|     NSUIntegerId(nullptr), NSASCIIStringEncodingId(nullptr),
 | |
|     NSUTF8StringEncodingId(nullptr) {}
 | |
| 
 | |
| IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
 | |
|   static const char *ClassName[NumClassIds] = {
 | |
|     "NSObject",
 | |
|     "NSString",
 | |
|     "NSArray",
 | |
|     "NSMutableArray",
 | |
|     "NSDictionary",
 | |
|     "NSMutableDictionary",
 | |
|     "NSNumber",
 | |
|     "NSMutableSet",
 | |
|     "NSMutableOrderedSet",
 | |
|     "NSValue"
 | |
|   };
 | |
| 
 | |
|   if (!ClassIds[K])
 | |
|     return (ClassIds[K] = &Ctx.Idents.get(ClassName[K]));
 | |
| 
 | |
|   return ClassIds[K];
 | |
| }
 | |
| 
 | |
| Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const {
 | |
|   if (NSStringSelectors[MK].isNull()) {
 | |
|     Selector Sel;
 | |
|     switch (MK) {
 | |
|     case NSStr_stringWithString:
 | |
|       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString"));
 | |
|       break;
 | |
|     case NSStr_stringWithUTF8String:
 | |
|       Sel = Ctx.Selectors.getUnarySelector(
 | |
|                                        &Ctx.Idents.get("stringWithUTF8String"));
 | |
|       break;
 | |
|     case NSStr_initWithUTF8String:
 | |
|       Sel = Ctx.Selectors.getUnarySelector(
 | |
|                                        &Ctx.Idents.get("initWithUTF8String"));
 | |
|       break;
 | |
|     case NSStr_stringWithCStringEncoding: {
 | |
|       IdentifierInfo *KeyIdents[] = {
 | |
|         &Ctx.Idents.get("stringWithCString"),
 | |
|         &Ctx.Idents.get("encoding")
 | |
|       };
 | |
|       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
 | |
|       break;
 | |
|     }
 | |
|     case NSStr_stringWithCString:
 | |
|       Sel= Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithCString"));
 | |
|       break;
 | |
|     case NSStr_initWithString:
 | |
|       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString"));
 | |
|       break;
 | |
|     }
 | |
|     return (NSStringSelectors[MK] = Sel);
 | |
|   }
 | |
| 
 | |
|   return NSStringSelectors[MK];
 | |
| }
 | |
| 
 | |
| Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {
 | |
|   if (NSArraySelectors[MK].isNull()) {
 | |
|     Selector Sel;
 | |
|     switch (MK) {
 | |
|     case NSArr_array:
 | |
|       Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("array"));
 | |
|       break;
 | |
|     case NSArr_arrayWithArray:
 | |
|       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithArray"));
 | |
|       break;
 | |
|     case NSArr_arrayWithObject:
 | |
|       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObject"));
 | |
|       break;
 | |
|     case NSArr_arrayWithObjects:
 | |
|       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects"));
 | |
|       break;
 | |
|     case NSArr_arrayWithObjectsCount: {
 | |
|       IdentifierInfo *KeyIdents[] = {
 | |
|         &Ctx.Idents.get("arrayWithObjects"),
 | |
|         &Ctx.Idents.get("count")
 | |
|       };
 | |
|       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
 | |
|       break;
 | |
|     }
 | |
|     case NSArr_initWithArray:
 | |
|       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithArray"));
 | |
|       break;
 | |
|     case NSArr_initWithObjects:
 | |
|       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithObjects"));
 | |
|       break;
 | |
|     case NSArr_objectAtIndex:
 | |
|       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex"));
 | |
|       break;
 | |
|     case NSMutableArr_replaceObjectAtIndex: {
 | |
|       IdentifierInfo *KeyIdents[] = {
 | |
|         &Ctx.Idents.get("replaceObjectAtIndex"),
 | |
|         &Ctx.Idents.get("withObject")
 | |
|       };
 | |
|       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
 | |
|       break;
 | |
|     }
 | |
|     case NSMutableArr_addObject:
 | |
|       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));
 | |
|       break;
 | |
|     case NSMutableArr_insertObjectAtIndex: {
 | |
|       IdentifierInfo *KeyIdents[] = {
 | |
|         &Ctx.Idents.get("insertObject"),
 | |
|         &Ctx.Idents.get("atIndex")
 | |
|       };
 | |
|       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
 | |
|       break;
 | |
|     }
 | |
|     case NSMutableArr_setObjectAtIndexedSubscript: {
 | |
|       IdentifierInfo *KeyIdents[] = {
 | |
|         &Ctx.Idents.get("setObject"),
 | |
|         &Ctx.Idents.get("atIndexedSubscript")
 | |
|       };
 | |
|       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
 | |
|       break;
 | |
|     }
 | |
|     }
 | |
|     return (NSArraySelectors[MK] = Sel);
 | |
|   }
 | |
| 
 | |
|   return NSArraySelectors[MK];
 | |
| }
 | |
| 
 | |
| Optional<NSAPI::NSArrayMethodKind> NSAPI::getNSArrayMethodKind(Selector Sel) {
 | |
|   for (unsigned i = 0; i != NumNSArrayMethods; ++i) {
 | |
|     NSArrayMethodKind MK = NSArrayMethodKind(i);
 | |
|     if (Sel == getNSArraySelector(MK))
 | |
|       return MK;
 | |
|   }
 | |
| 
 | |
|   return None;
 | |
| }
 | |
| 
 | |
| Selector NSAPI::getNSDictionarySelector(
 | |
|                                        NSDictionaryMethodKind MK) const {
 | |
|   if (NSDictionarySelectors[MK].isNull()) {
 | |
|     Selector Sel;
 | |
|     switch (MK) {
 | |
|     case NSDict_dictionary:
 | |
|       Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));
 | |
|       break;
 | |
|     case NSDict_dictionaryWithDictionary:
 | |
|       Sel = Ctx.Selectors.getUnarySelector(
 | |
|                                    &Ctx.Idents.get("dictionaryWithDictionary"));
 | |
|       break;
 | |
|     case NSDict_dictionaryWithObjectForKey: {
 | |
|       IdentifierInfo *KeyIdents[] = {
 | |
|         &Ctx.Idents.get("dictionaryWithObject"),
 | |
|         &Ctx.Idents.get("forKey")
 | |
|       };
 | |
|       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
 | |
|       break;
 | |
|     }
 | |
|     case NSDict_dictionaryWithObjectsForKeys: {
 | |
|       IdentifierInfo *KeyIdents[] = {
 | |
|         &Ctx.Idents.get("dictionaryWithObjects"),
 | |
|         &Ctx.Idents.get("forKeys")
 | |
|       };
 | |
|       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
 | |
|       break;
 | |
|     }
 | |
|     case NSDict_dictionaryWithObjectsForKeysCount: {
 | |
|       IdentifierInfo *KeyIdents[] = {
 | |
|         &Ctx.Idents.get("dictionaryWithObjects"),
 | |
|         &Ctx.Idents.get("forKeys"),
 | |
|         &Ctx.Idents.get("count")
 | |
|       };
 | |
|       Sel = Ctx.Selectors.getSelector(3, KeyIdents);
 | |
|       break;
 | |
|     }
 | |
|     case NSDict_dictionaryWithObjectsAndKeys:
 | |
|       Sel = Ctx.Selectors.getUnarySelector(
 | |
|                                &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));
 | |
|       break;
 | |
|     case NSDict_initWithDictionary:
 | |
|       Sel = Ctx.Selectors.getUnarySelector(
 | |
|                                          &Ctx.Idents.get("initWithDictionary"));
 | |
|       break;
 | |
|     case NSDict_initWithObjectsAndKeys:
 | |
|       Sel = Ctx.Selectors.getUnarySelector(
 | |
|                                      &Ctx.Idents.get("initWithObjectsAndKeys"));
 | |
|       break;
 | |
|     case NSDict_initWithObjectsForKeys: {
 | |
|       IdentifierInfo *KeyIdents[] = {
 | |
|         &Ctx.Idents.get("initWithObjects"),
 | |
|         &Ctx.Idents.get("forKeys")
 | |
|       };
 | |
|       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
 | |
|       break;
 | |
|     }
 | |
|     case NSDict_objectForKey:
 | |
|       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
 | |
|       break;
 | |
|     case NSMutableDict_setObjectForKey: {
 | |
|       IdentifierInfo *KeyIdents[] = {
 | |
|         &Ctx.Idents.get("setObject"),
 | |
|         &Ctx.Idents.get("forKey")
 | |
|       };
 | |
|       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
 | |
|       break;
 | |
|     }
 | |
|     case NSMutableDict_setObjectForKeyedSubscript: {
 | |
|       IdentifierInfo *KeyIdents[] = {
 | |
|         &Ctx.Idents.get("setObject"),
 | |
|         &Ctx.Idents.get("forKeyedSubscript")
 | |
|       };
 | |
|       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
 | |
|       break;
 | |
|     }
 | |
|     case NSMutableDict_setValueForKey: {
 | |
|       IdentifierInfo *KeyIdents[] = {
 | |
|         &Ctx.Idents.get("setValue"),
 | |
|         &Ctx.Idents.get("forKey")
 | |
|       };
 | |
|       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
 | |
|       break;
 | |
|     }
 | |
|     }
 | |
|     return (NSDictionarySelectors[MK] = Sel);
 | |
|   }
 | |
| 
 | |
|   return NSDictionarySelectors[MK];
 | |
| }
 | |
| 
 | |
| Optional<NSAPI::NSDictionaryMethodKind>
 | |
| NSAPI::getNSDictionaryMethodKind(Selector Sel) {
 | |
|   for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
 | |
|     NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
 | |
|     if (Sel == getNSDictionarySelector(MK))
 | |
|       return MK;
 | |
|   }
 | |
| 
 | |
|   return None;
 | |
| }
 | |
| 
 | |
| Selector NSAPI::getNSSetSelector(NSSetMethodKind MK) const {
 | |
|   if (NSSetSelectors[MK].isNull()) {
 | |
|     Selector Sel;
 | |
|     switch (MK) {
 | |
|     case NSMutableSet_addObject:
 | |
|       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));
 | |
|       break;
 | |
|     case NSOrderedSet_insertObjectAtIndex: {
 | |
|       IdentifierInfo *KeyIdents[] = {
 | |
|         &Ctx.Idents.get("insertObject"),
 | |
|         &Ctx.Idents.get("atIndex")
 | |
|       };
 | |
|       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
 | |
|       break;
 | |
|     }
 | |
|     case NSOrderedSet_setObjectAtIndex: {
 | |
|       IdentifierInfo *KeyIdents[] = {
 | |
|         &Ctx.Idents.get("setObject"),
 | |
|         &Ctx.Idents.get("atIndex")
 | |
|       };
 | |
|       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
 | |
|       break;
 | |
|     }
 | |
|     case NSOrderedSet_setObjectAtIndexedSubscript: {
 | |
|       IdentifierInfo *KeyIdents[] = {
 | |
|         &Ctx.Idents.get("setObject"),
 | |
|         &Ctx.Idents.get("atIndexedSubscript")
 | |
|       };
 | |
|       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
 | |
|       break;
 | |
|     }
 | |
|     case NSOrderedSet_replaceObjectAtIndexWithObject: {
 | |
|       IdentifierInfo *KeyIdents[] = {
 | |
|         &Ctx.Idents.get("replaceObjectAtIndex"),
 | |
|         &Ctx.Idents.get("withObject")
 | |
|       };
 | |
|       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
 | |
|       break;
 | |
|     }
 | |
|     }
 | |
|     return (NSSetSelectors[MK] = Sel);
 | |
|   }
 | |
| 
 | |
|   return NSSetSelectors[MK];
 | |
| }
 | |
| 
 | |
| Optional<NSAPI::NSSetMethodKind>
 | |
| NSAPI::getNSSetMethodKind(Selector Sel) {
 | |
|   for (unsigned i = 0; i != NumNSSetMethods; ++i) {
 | |
|     NSSetMethodKind MK = NSSetMethodKind(i);
 | |
|     if (Sel == getNSSetSelector(MK))
 | |
|       return MK;
 | |
|   }
 | |
| 
 | |
|   return None;
 | |
| }
 | |
| 
 | |
| Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
 | |
|                                            bool Instance) const {
 | |
|   static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
 | |
|     "numberWithChar",
 | |
|     "numberWithUnsignedChar",
 | |
|     "numberWithShort",
 | |
|     "numberWithUnsignedShort",
 | |
|     "numberWithInt",
 | |
|     "numberWithUnsignedInt",
 | |
|     "numberWithLong",
 | |
|     "numberWithUnsignedLong",
 | |
|     "numberWithLongLong",
 | |
|     "numberWithUnsignedLongLong",
 | |
|     "numberWithFloat",
 | |
|     "numberWithDouble",
 | |
|     "numberWithBool",
 | |
|     "numberWithInteger",
 | |
|     "numberWithUnsignedInteger"
 | |
|   };
 | |
|   static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
 | |
|     "initWithChar",
 | |
|     "initWithUnsignedChar",
 | |
|     "initWithShort",
 | |
|     "initWithUnsignedShort",
 | |
|     "initWithInt",
 | |
|     "initWithUnsignedInt",
 | |
|     "initWithLong",
 | |
|     "initWithUnsignedLong",
 | |
|     "initWithLongLong",
 | |
|     "initWithUnsignedLongLong",
 | |
|     "initWithFloat",
 | |
|     "initWithDouble",
 | |
|     "initWithBool",
 | |
|     "initWithInteger",
 | |
|     "initWithUnsignedInteger"
 | |
|   };
 | |
| 
 | |
|   Selector *Sels;
 | |
|   const char **Names;
 | |
|   if (Instance) {
 | |
|     Sels = NSNumberInstanceSelectors;
 | |
|     Names = InstanceSelectorName;
 | |
|   } else {
 | |
|     Sels = NSNumberClassSelectors;
 | |
|     Names = ClassSelectorName;
 | |
|   }
 | |
| 
 | |
|   if (Sels[MK].isNull())
 | |
|     Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
 | |
|   return Sels[MK];
 | |
| }
 | |
| 
 | |
| Optional<NSAPI::NSNumberLiteralMethodKind>
 | |
| NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
 | |
|   for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
 | |
|     NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
 | |
|     if (isNSNumberLiteralSelector(MK, Sel))
 | |
|       return MK;
 | |
|   }
 | |
| 
 | |
|   return None;
 | |
| }
 | |
| 
 | |
| Optional<NSAPI::NSNumberLiteralMethodKind>
 | |
| NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
 | |
|   const BuiltinType *BT = T->getAs<BuiltinType>();
 | |
|   if (!BT)
 | |
|     return None;
 | |
| 
 | |
|   const TypedefType *TDT = T->getAs<TypedefType>();
 | |
|   if (TDT) {
 | |
|     QualType TDTTy = QualType(TDT, 0);
 | |
|     if (isObjCBOOLType(TDTTy))
 | |
|       return NSAPI::NSNumberWithBool;
 | |
|     if (isObjCNSIntegerType(TDTTy))
 | |
|       return NSAPI::NSNumberWithInteger;
 | |
|     if (isObjCNSUIntegerType(TDTTy))
 | |
|       return NSAPI::NSNumberWithUnsignedInteger;
 | |
|   }
 | |
| 
 | |
|   switch (BT->getKind()) {
 | |
|   case BuiltinType::Char_S:
 | |
|   case BuiltinType::SChar:
 | |
|     return NSAPI::NSNumberWithChar;
 | |
|   case BuiltinType::Char_U:
 | |
|   case BuiltinType::UChar:
 | |
|     return NSAPI::NSNumberWithUnsignedChar;
 | |
|   case BuiltinType::Short:
 | |
|     return NSAPI::NSNumberWithShort;
 | |
|   case BuiltinType::UShort:
 | |
|     return NSAPI::NSNumberWithUnsignedShort;
 | |
|   case BuiltinType::Int:
 | |
|     return NSAPI::NSNumberWithInt;
 | |
|   case BuiltinType::UInt:
 | |
|     return NSAPI::NSNumberWithUnsignedInt;
 | |
|   case BuiltinType::Long:
 | |
|     return NSAPI::NSNumberWithLong;
 | |
|   case BuiltinType::ULong:
 | |
|     return NSAPI::NSNumberWithUnsignedLong;
 | |
|   case BuiltinType::LongLong:
 | |
|     return NSAPI::NSNumberWithLongLong;
 | |
|   case BuiltinType::ULongLong:
 | |
|     return NSAPI::NSNumberWithUnsignedLongLong;
 | |
|   case BuiltinType::Float:
 | |
|     return NSAPI::NSNumberWithFloat;
 | |
|   case BuiltinType::Double:
 | |
|     return NSAPI::NSNumberWithDouble;
 | |
|   case BuiltinType::Bool:
 | |
|     return NSAPI::NSNumberWithBool;
 | |
| 
 | |
|   case BuiltinType::Void:
 | |
|   case BuiltinType::WChar_U:
 | |
|   case BuiltinType::WChar_S:
 | |
|   case BuiltinType::Char8:
 | |
|   case BuiltinType::Char16:
 | |
|   case BuiltinType::Char32:
 | |
|   case BuiltinType::Int128:
 | |
|   case BuiltinType::LongDouble:
 | |
|   case BuiltinType::ShortAccum:
 | |
|   case BuiltinType::Accum:
 | |
|   case BuiltinType::LongAccum:
 | |
|   case BuiltinType::UShortAccum:
 | |
|   case BuiltinType::UAccum:
 | |
|   case BuiltinType::ULongAccum:
 | |
|   case BuiltinType::ShortFract:
 | |
|   case BuiltinType::Fract:
 | |
|   case BuiltinType::LongFract:
 | |
|   case BuiltinType::UShortFract:
 | |
|   case BuiltinType::UFract:
 | |
|   case BuiltinType::ULongFract:
 | |
|   case BuiltinType::SatShortAccum:
 | |
|   case BuiltinType::SatAccum:
 | |
|   case BuiltinType::SatLongAccum:
 | |
|   case BuiltinType::SatUShortAccum:
 | |
|   case BuiltinType::SatUAccum:
 | |
|   case BuiltinType::SatULongAccum:
 | |
|   case BuiltinType::SatShortFract:
 | |
|   case BuiltinType::SatFract:
 | |
|   case BuiltinType::SatLongFract:
 | |
|   case BuiltinType::SatUShortFract:
 | |
|   case BuiltinType::SatUFract:
 | |
|   case BuiltinType::SatULongFract:
 | |
|   case BuiltinType::UInt128:
 | |
|   case BuiltinType::Float16:
 | |
|   case BuiltinType::Float128:
 | |
|   case BuiltinType::NullPtr:
 | |
|   case BuiltinType::ObjCClass:
 | |
|   case BuiltinType::ObjCId:
 | |
|   case BuiltinType::ObjCSel:
 | |
| #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
 | |
|   case BuiltinType::Id:
 | |
| #include "clang/Basic/OpenCLImageTypes.def"
 | |
| #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
 | |
|   case BuiltinType::Id:
 | |
| #include "clang/Basic/OpenCLExtensionTypes.def"
 | |
|   case BuiltinType::OCLSampler:
 | |
|   case BuiltinType::OCLEvent:
 | |
|   case BuiltinType::OCLClkEvent:
 | |
|   case BuiltinType::OCLQueue:
 | |
|   case BuiltinType::OCLReserveID:
 | |
| #define SVE_TYPE(Name, Id, SingletonId) \
 | |
|   case BuiltinType::Id:
 | |
| #include "clang/Basic/AArch64SVEACLETypes.def"
 | |
|   case BuiltinType::BoundMember:
 | |
|   case BuiltinType::Dependent:
 | |
|   case BuiltinType::Overload:
 | |
|   case BuiltinType::UnknownAny:
 | |
|   case BuiltinType::ARCUnbridgedCast:
 | |
|   case BuiltinType::Half:
 | |
|   case BuiltinType::PseudoObject:
 | |
|   case BuiltinType::BuiltinFn:
 | |
|   case BuiltinType::OMPArraySection:
 | |
|     break;
 | |
|   }
 | |
| 
 | |
|   return None;
 | |
| }
 | |
| 
 | |
| /// Returns true if \param T is a typedef of "BOOL" in objective-c.
 | |
| bool NSAPI::isObjCBOOLType(QualType T) const {
 | |
|   return isObjCTypedef(T, "BOOL", BOOLId);
 | |
| }
 | |
| /// Returns true if \param T is a typedef of "NSInteger" in objective-c.
 | |
| bool NSAPI::isObjCNSIntegerType(QualType T) const {
 | |
|   return isObjCTypedef(T, "NSInteger", NSIntegerId);
 | |
| }
 | |
| /// Returns true if \param T is a typedef of "NSUInteger" in objective-c.
 | |
| bool NSAPI::isObjCNSUIntegerType(QualType T) const {
 | |
|   return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
 | |
| }
 | |
| 
 | |
| StringRef NSAPI::GetNSIntegralKind(QualType T) const {
 | |
|   if (!Ctx.getLangOpts().ObjC || T.isNull())
 | |
|     return StringRef();
 | |
| 
 | |
|   while (const TypedefType *TDT = T->getAs<TypedefType>()) {
 | |
|     StringRef NSIntegralResust =
 | |
|       llvm::StringSwitch<StringRef>(
 | |
|         TDT->getDecl()->getDeclName().getAsIdentifierInfo()->getName())
 | |
|     .Case("int8_t", "int8_t")
 | |
|     .Case("int16_t", "int16_t")
 | |
|     .Case("int32_t", "int32_t")
 | |
|     .Case("NSInteger", "NSInteger")
 | |
|     .Case("int64_t", "int64_t")
 | |
|     .Case("uint8_t", "uint8_t")
 | |
|     .Case("uint16_t", "uint16_t")
 | |
|     .Case("uint32_t", "uint32_t")
 | |
|     .Case("NSUInteger", "NSUInteger")
 | |
|     .Case("uint64_t", "uint64_t")
 | |
|     .Default(StringRef());
 | |
|     if (!NSIntegralResust.empty())
 | |
|       return NSIntegralResust;
 | |
|     T = TDT->desugar();
 | |
|   }
 | |
|   return StringRef();
 | |
| }
 | |
| 
 | |
| bool NSAPI::isMacroDefined(StringRef Id) const {
 | |
|   // FIXME: Check whether the relevant module macros are visible.
 | |
|   return Ctx.Idents.get(Id).hasMacroDefinition();
 | |
| }
 | |
| 
 | |
| bool NSAPI::isSubclassOfNSClass(ObjCInterfaceDecl *InterfaceDecl,
 | |
|                                 NSClassIdKindKind NSClassKind) const {
 | |
|   if (!InterfaceDecl) {
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   IdentifierInfo *NSClassID = getNSClassId(NSClassKind);
 | |
| 
 | |
|   bool IsSubclass = false;
 | |
|   do {
 | |
|     IsSubclass = NSClassID == InterfaceDecl->getIdentifier();
 | |
| 
 | |
|     if (IsSubclass) {
 | |
|       break;
 | |
|     }
 | |
|   } while ((InterfaceDecl = InterfaceDecl->getSuperClass()));
 | |
| 
 | |
|   return IsSubclass;
 | |
| }
 | |
| 
 | |
| bool NSAPI::isObjCTypedef(QualType T,
 | |
|                           StringRef name, IdentifierInfo *&II) const {
 | |
|   if (!Ctx.getLangOpts().ObjC)
 | |
|     return false;
 | |
|   if (T.isNull())
 | |
|     return false;
 | |
| 
 | |
|   if (!II)
 | |
|     II = &Ctx.Idents.get(name);
 | |
| 
 | |
|   while (const TypedefType *TDT = T->getAs<TypedefType>()) {
 | |
|     if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
 | |
|       return true;
 | |
|     T = TDT->desugar();
 | |
|   }
 | |
| 
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool NSAPI::isObjCEnumerator(const Expr *E,
 | |
|                              StringRef name, IdentifierInfo *&II) const {
 | |
|   if (!Ctx.getLangOpts().ObjC)
 | |
|     return false;
 | |
|   if (!E)
 | |
|     return false;
 | |
| 
 | |
|   if (!II)
 | |
|     II = &Ctx.Idents.get(name);
 | |
| 
 | |
|   if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
 | |
|     if (const EnumConstantDecl *
 | |
|           EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl()))
 | |
|       return EnumD->getIdentifier() == II;
 | |
| 
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
 | |
|                                   Selector &Sel) const {
 | |
|   if (Sel.isNull()) {
 | |
|     SmallVector<IdentifierInfo *, 4> Idents;
 | |
|     for (ArrayRef<StringRef>::const_iterator
 | |
|            I = Ids.begin(), E = Ids.end(); I != E; ++I)
 | |
|       Idents.push_back(&Ctx.Idents.get(*I));
 | |
|     Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data());
 | |
|   }
 | |
|   return Sel;
 | |
| }
 | |
| 
 | |
| Selector NSAPI::getOrInitNullarySelector(StringRef Id, Selector &Sel) const {
 | |
|   if (Sel.isNull()) {
 | |
|     IdentifierInfo *Ident = &Ctx.Idents.get(Id);
 | |
|     Sel = Ctx.Selectors.getSelector(0, &Ident);
 | |
|   }
 | |
|   return Sel;
 | |
| }
 |