brintos

brintos / llvm-project-archived public Read only

0
0
Text · 19.0 KiB · 17f5ee5 Raw
600 lines · cpp
1//===--- NSAPI.cpp - NSFoundation APIs ------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "clang/AST/NSAPI.h"10#include "clang/AST/ASTContext.h"11#include "clang/AST/DeclObjC.h"12#include "clang/AST/Expr.h"13#include "llvm/ADT/StringSwitch.h"14#include <optional>15 16using namespace clang;17 18NSAPI::NSAPI(ASTContext &ctx)19  : Ctx(ctx), ClassIds(), BOOLId(nullptr), NSIntegerId(nullptr),20    NSUIntegerId(nullptr), NSASCIIStringEncodingId(nullptr),21    NSUTF8StringEncodingId(nullptr) {}22 23IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {24  static const char *ClassName[NumClassIds] = {25    "NSObject",26    "NSString",27    "NSArray",28    "NSMutableArray",29    "NSDictionary",30    "NSMutableDictionary",31    "NSNumber",32    "NSMutableSet",33    "NSMutableOrderedSet",34    "NSValue"35  };36 37  if (!ClassIds[K])38    return (ClassIds[K] = &Ctx.Idents.get(ClassName[K]));39 40  return ClassIds[K];41}42 43Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const {44  if (NSStringSelectors[MK].isNull()) {45    Selector Sel;46    switch (MK) {47    case NSStr_stringWithString:48      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString"));49      break;50    case NSStr_stringWithUTF8String:51      Sel = Ctx.Selectors.getUnarySelector(52                                       &Ctx.Idents.get("stringWithUTF8String"));53      break;54    case NSStr_initWithUTF8String:55      Sel = Ctx.Selectors.getUnarySelector(56                                       &Ctx.Idents.get("initWithUTF8String"));57      break;58    case NSStr_stringWithCStringEncoding: {59      const IdentifierInfo *KeyIdents[] = {&Ctx.Idents.get("stringWithCString"),60                                           &Ctx.Idents.get("encoding")};61      Sel = Ctx.Selectors.getSelector(2, KeyIdents);62      break;63    }64    case NSStr_stringWithCString:65      Sel= Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithCString"));66      break;67    case NSStr_initWithString:68      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString"));69      break;70    }71    return (NSStringSelectors[MK] = Sel);72  }73 74  return NSStringSelectors[MK];75}76 77Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {78  if (NSArraySelectors[MK].isNull()) {79    Selector Sel;80    switch (MK) {81    case NSArr_array:82      Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("array"));83      break;84    case NSArr_arrayWithArray:85      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithArray"));86      break;87    case NSArr_arrayWithObject:88      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObject"));89      break;90    case NSArr_arrayWithObjects:91      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects"));92      break;93    case NSArr_arrayWithObjectsCount: {94      const IdentifierInfo *KeyIdents[] = {&Ctx.Idents.get("arrayWithObjects"),95                                           &Ctx.Idents.get("count")};96      Sel = Ctx.Selectors.getSelector(2, KeyIdents);97      break;98    }99    case NSArr_initWithArray:100      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithArray"));101      break;102    case NSArr_initWithObjects:103      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithObjects"));104      break;105    case NSArr_objectAtIndex:106      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex"));107      break;108    case NSMutableArr_replaceObjectAtIndex: {109      const IdentifierInfo *KeyIdents[] = {110          &Ctx.Idents.get("replaceObjectAtIndex"),111          &Ctx.Idents.get("withObject")};112      Sel = Ctx.Selectors.getSelector(2, KeyIdents);113      break;114    }115    case NSMutableArr_addObject:116      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));117      break;118    case NSMutableArr_insertObjectAtIndex: {119      const IdentifierInfo *KeyIdents[] = {&Ctx.Idents.get("insertObject"),120                                           &Ctx.Idents.get("atIndex")};121      Sel = Ctx.Selectors.getSelector(2, KeyIdents);122      break;123    }124    case NSMutableArr_setObjectAtIndexedSubscript: {125      const IdentifierInfo *KeyIdents[] = {126          &Ctx.Idents.get("setObject"), &Ctx.Idents.get("atIndexedSubscript")};127      Sel = Ctx.Selectors.getSelector(2, KeyIdents);128      break;129    }130    }131    return (NSArraySelectors[MK] = Sel);132  }133 134  return NSArraySelectors[MK];135}136 137std::optional<NSAPI::NSArrayMethodKind>138NSAPI::getNSArrayMethodKind(Selector Sel) {139  for (unsigned i = 0; i != NumNSArrayMethods; ++i) {140    NSArrayMethodKind MK = NSArrayMethodKind(i);141    if (Sel == getNSArraySelector(MK))142      return MK;143  }144 145  return std::nullopt;146}147 148Selector NSAPI::getNSDictionarySelector(149                                       NSDictionaryMethodKind MK) const {150  if (NSDictionarySelectors[MK].isNull()) {151    Selector Sel;152    switch (MK) {153    case NSDict_dictionary:154      Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));155      break;156    case NSDict_dictionaryWithDictionary:157      Sel = Ctx.Selectors.getUnarySelector(158                                   &Ctx.Idents.get("dictionaryWithDictionary"));159      break;160    case NSDict_dictionaryWithObjectForKey: {161      const IdentifierInfo *KeyIdents[] = {162          &Ctx.Idents.get("dictionaryWithObject"), &Ctx.Idents.get("forKey")};163      Sel = Ctx.Selectors.getSelector(2, KeyIdents);164      break;165    }166    case NSDict_dictionaryWithObjectsForKeys: {167      const IdentifierInfo *KeyIdents[] = {168          &Ctx.Idents.get("dictionaryWithObjects"), &Ctx.Idents.get("forKeys")};169      Sel = Ctx.Selectors.getSelector(2, KeyIdents);170      break;171    }172    case NSDict_dictionaryWithObjectsForKeysCount: {173      const IdentifierInfo *KeyIdents[] = {174          &Ctx.Idents.get("dictionaryWithObjects"), &Ctx.Idents.get("forKeys"),175          &Ctx.Idents.get("count")};176      Sel = Ctx.Selectors.getSelector(3, KeyIdents);177      break;178    }179    case NSDict_dictionaryWithObjectsAndKeys:180      Sel = Ctx.Selectors.getUnarySelector(181                               &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));182      break;183    case NSDict_initWithDictionary:184      Sel = Ctx.Selectors.getUnarySelector(185                                         &Ctx.Idents.get("initWithDictionary"));186      break;187    case NSDict_initWithObjectsAndKeys:188      Sel = Ctx.Selectors.getUnarySelector(189                                     &Ctx.Idents.get("initWithObjectsAndKeys"));190      break;191    case NSDict_initWithObjectsForKeys: {192      const IdentifierInfo *KeyIdents[] = {&Ctx.Idents.get("initWithObjects"),193                                           &Ctx.Idents.get("forKeys")};194      Sel = Ctx.Selectors.getSelector(2, KeyIdents);195      break;196    }197    case NSDict_objectForKey:198      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));199      break;200    case NSMutableDict_setObjectForKey: {201      const IdentifierInfo *KeyIdents[] = {&Ctx.Idents.get("setObject"),202                                           &Ctx.Idents.get("forKey")};203      Sel = Ctx.Selectors.getSelector(2, KeyIdents);204      break;205    }206    case NSMutableDict_setObjectForKeyedSubscript: {207      const IdentifierInfo *KeyIdents[] = {208          &Ctx.Idents.get("setObject"), &Ctx.Idents.get("forKeyedSubscript")};209      Sel = Ctx.Selectors.getSelector(2, KeyIdents);210      break;211    }212    case NSMutableDict_setValueForKey: {213      const IdentifierInfo *KeyIdents[] = {&Ctx.Idents.get("setValue"),214                                           &Ctx.Idents.get("forKey")};215      Sel = Ctx.Selectors.getSelector(2, KeyIdents);216      break;217    }218    }219    return (NSDictionarySelectors[MK] = Sel);220  }221 222  return NSDictionarySelectors[MK];223}224 225std::optional<NSAPI::NSDictionaryMethodKind>226NSAPI::getNSDictionaryMethodKind(Selector Sel) {227  for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {228    NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);229    if (Sel == getNSDictionarySelector(MK))230      return MK;231  }232 233  return std::nullopt;234}235 236Selector NSAPI::getNSSetSelector(NSSetMethodKind MK) const {237  if (NSSetSelectors[MK].isNull()) {238    Selector Sel;239    switch (MK) {240    case NSMutableSet_addObject:241      Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));242      break;243    case NSOrderedSet_insertObjectAtIndex: {244      const IdentifierInfo *KeyIdents[] = {&Ctx.Idents.get("insertObject"),245                                           &Ctx.Idents.get("atIndex")};246      Sel = Ctx.Selectors.getSelector(2, KeyIdents);247      break;248    }249    case NSOrderedSet_setObjectAtIndex: {250      const IdentifierInfo *KeyIdents[] = {&Ctx.Idents.get("setObject"),251                                           &Ctx.Idents.get("atIndex")};252      Sel = Ctx.Selectors.getSelector(2, KeyIdents);253      break;254    }255    case NSOrderedSet_setObjectAtIndexedSubscript: {256      const IdentifierInfo *KeyIdents[] = {257          &Ctx.Idents.get("setObject"), &Ctx.Idents.get("atIndexedSubscript")};258      Sel = Ctx.Selectors.getSelector(2, KeyIdents);259      break;260    }261    case NSOrderedSet_replaceObjectAtIndexWithObject: {262      const IdentifierInfo *KeyIdents[] = {263          &Ctx.Idents.get("replaceObjectAtIndex"),264          &Ctx.Idents.get("withObject")};265      Sel = Ctx.Selectors.getSelector(2, KeyIdents);266      break;267    }268    }269    return (NSSetSelectors[MK] = Sel);270  }271 272  return NSSetSelectors[MK];273}274 275std::optional<NSAPI::NSSetMethodKind> NSAPI::getNSSetMethodKind(Selector Sel) {276  for (unsigned i = 0; i != NumNSSetMethods; ++i) {277    NSSetMethodKind MK = NSSetMethodKind(i);278    if (Sel == getNSSetSelector(MK))279      return MK;280  }281 282  return std::nullopt;283}284 285Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,286                                           bool Instance) const {287  static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {288    "numberWithChar",289    "numberWithUnsignedChar",290    "numberWithShort",291    "numberWithUnsignedShort",292    "numberWithInt",293    "numberWithUnsignedInt",294    "numberWithLong",295    "numberWithUnsignedLong",296    "numberWithLongLong",297    "numberWithUnsignedLongLong",298    "numberWithFloat",299    "numberWithDouble",300    "numberWithBool",301    "numberWithInteger",302    "numberWithUnsignedInteger"303  };304  static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {305    "initWithChar",306    "initWithUnsignedChar",307    "initWithShort",308    "initWithUnsignedShort",309    "initWithInt",310    "initWithUnsignedInt",311    "initWithLong",312    "initWithUnsignedLong",313    "initWithLongLong",314    "initWithUnsignedLongLong",315    "initWithFloat",316    "initWithDouble",317    "initWithBool",318    "initWithInteger",319    "initWithUnsignedInteger"320  };321 322  Selector *Sels;323  const char **Names;324  if (Instance) {325    Sels = NSNumberInstanceSelectors;326    Names = InstanceSelectorName;327  } else {328    Sels = NSNumberClassSelectors;329    Names = ClassSelectorName;330  }331 332  if (Sels[MK].isNull())333    Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));334  return Sels[MK];335}336 337std::optional<NSAPI::NSNumberLiteralMethodKind>338NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {339  for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {340    NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);341    if (isNSNumberLiteralSelector(MK, Sel))342      return MK;343  }344 345  return std::nullopt;346}347 348std::optional<NSAPI::NSNumberLiteralMethodKind>349NSAPI::getNSNumberFactoryMethodKind(QualType T) const {350  const BuiltinType *BT = T->getAs<BuiltinType>();351  if (!BT)352    return std::nullopt;353 354  const TypedefType *TDT = T->getAs<TypedefType>();355  if (TDT) {356    QualType TDTTy = QualType(TDT, 0);357    if (isObjCBOOLType(TDTTy))358      return NSAPI::NSNumberWithBool;359    if (isObjCNSIntegerType(TDTTy))360      return NSAPI::NSNumberWithInteger;361    if (isObjCNSUIntegerType(TDTTy))362      return NSAPI::NSNumberWithUnsignedInteger;363  }364 365  switch (BT->getKind()) {366  case BuiltinType::Char_S:367  case BuiltinType::SChar:368    return NSAPI::NSNumberWithChar;369  case BuiltinType::Char_U:370  case BuiltinType::UChar:371    return NSAPI::NSNumberWithUnsignedChar;372  case BuiltinType::Short:373    return NSAPI::NSNumberWithShort;374  case BuiltinType::UShort:375    return NSAPI::NSNumberWithUnsignedShort;376  case BuiltinType::Int:377    return NSAPI::NSNumberWithInt;378  case BuiltinType::UInt:379    return NSAPI::NSNumberWithUnsignedInt;380  case BuiltinType::Long:381    return NSAPI::NSNumberWithLong;382  case BuiltinType::ULong:383    return NSAPI::NSNumberWithUnsignedLong;384  case BuiltinType::LongLong:385    return NSAPI::NSNumberWithLongLong;386  case BuiltinType::ULongLong:387    return NSAPI::NSNumberWithUnsignedLongLong;388  case BuiltinType::Float:389    return NSAPI::NSNumberWithFloat;390  case BuiltinType::Double:391    return NSAPI::NSNumberWithDouble;392  case BuiltinType::Bool:393    return NSAPI::NSNumberWithBool;394 395  case BuiltinType::Void:396  case BuiltinType::WChar_U:397  case BuiltinType::WChar_S:398  case BuiltinType::Char8:399  case BuiltinType::Char16:400  case BuiltinType::Char32:401  case BuiltinType::Int128:402  case BuiltinType::LongDouble:403  case BuiltinType::ShortAccum:404  case BuiltinType::Accum:405  case BuiltinType::LongAccum:406  case BuiltinType::UShortAccum:407  case BuiltinType::UAccum:408  case BuiltinType::ULongAccum:409  case BuiltinType::ShortFract:410  case BuiltinType::Fract:411  case BuiltinType::LongFract:412  case BuiltinType::UShortFract:413  case BuiltinType::UFract:414  case BuiltinType::ULongFract:415  case BuiltinType::SatShortAccum:416  case BuiltinType::SatAccum:417  case BuiltinType::SatLongAccum:418  case BuiltinType::SatUShortAccum:419  case BuiltinType::SatUAccum:420  case BuiltinType::SatULongAccum:421  case BuiltinType::SatShortFract:422  case BuiltinType::SatFract:423  case BuiltinType::SatLongFract:424  case BuiltinType::SatUShortFract:425  case BuiltinType::SatUFract:426  case BuiltinType::SatULongFract:427  case BuiltinType::UInt128:428  case BuiltinType::Float16:429  case BuiltinType::Float128:430  case BuiltinType::Ibm128:431  case BuiltinType::NullPtr:432  case BuiltinType::ObjCClass:433  case BuiltinType::ObjCId:434  case BuiltinType::ObjCSel:435#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \436  case BuiltinType::Id:437#include "clang/Basic/OpenCLImageTypes.def"438#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \439  case BuiltinType::Id:440#include "clang/Basic/OpenCLExtensionTypes.def"441  case BuiltinType::OCLSampler:442  case BuiltinType::OCLEvent:443  case BuiltinType::OCLClkEvent:444  case BuiltinType::OCLQueue:445  case BuiltinType::OCLReserveID:446#define SVE_TYPE(Name, Id, SingletonId) \447  case BuiltinType::Id:448#include "clang/Basic/AArch64ACLETypes.def"449#define PPC_VECTOR_TYPE(Name, Id, Size) \450  case BuiltinType::Id:451#include "clang/Basic/PPCTypes.def"452#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:453#include "clang/Basic/RISCVVTypes.def"454#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:455#include "clang/Basic/WebAssemblyReferenceTypes.def"456#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) case BuiltinType::Id:457#include "clang/Basic/AMDGPUTypes.def"458#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:459#include "clang/Basic/HLSLIntangibleTypes.def"460  case BuiltinType::BoundMember:461  case BuiltinType::UnresolvedTemplate:462  case BuiltinType::Dependent:463  case BuiltinType::Overload:464  case BuiltinType::UnknownAny:465  case BuiltinType::ARCUnbridgedCast:466  case BuiltinType::Half:467  case BuiltinType::PseudoObject:468  case BuiltinType::BuiltinFn:469  case BuiltinType::IncompleteMatrixIdx:470  case BuiltinType::ArraySection:471  case BuiltinType::OMPArrayShaping:472  case BuiltinType::OMPIterator:473  case BuiltinType::BFloat16:474    break;475  }476 477  return std::nullopt;478}479 480/// Returns true if \param T is a typedef of "BOOL" in objective-c.481bool NSAPI::isObjCBOOLType(QualType T) const {482  return isObjCTypedef(T, "BOOL", BOOLId);483}484/// Returns true if \param T is a typedef of "NSInteger" in objective-c.485bool NSAPI::isObjCNSIntegerType(QualType T) const {486  return isObjCTypedef(T, "NSInteger", NSIntegerId);487}488/// Returns true if \param T is a typedef of "NSUInteger" in objective-c.489bool NSAPI::isObjCNSUIntegerType(QualType T) const {490  return isObjCTypedef(T, "NSUInteger", NSUIntegerId);491}492 493StringRef NSAPI::GetNSIntegralKind(QualType T) const {494  if (!Ctx.getLangOpts().ObjC || T.isNull())495    return StringRef();496 497  while (const TypedefType *TDT = T->getAs<TypedefType>()) {498    StringRef NSIntegralResust =499      llvm::StringSwitch<StringRef>(500        TDT->getDecl()->getDeclName().getAsIdentifierInfo()->getName())501    .Case("int8_t", "int8_t")502    .Case("int16_t", "int16_t")503    .Case("int32_t", "int32_t")504    .Case("NSInteger", "NSInteger")505    .Case("int64_t", "int64_t")506    .Case("uint8_t", "uint8_t")507    .Case("uint16_t", "uint16_t")508    .Case("uint32_t", "uint32_t")509    .Case("NSUInteger", "NSUInteger")510    .Case("uint64_t", "uint64_t")511    .Default(StringRef());512    if (!NSIntegralResust.empty())513      return NSIntegralResust;514    T = TDT->desugar();515  }516  return StringRef();517}518 519bool NSAPI::isMacroDefined(StringRef Id) const {520  // FIXME: Check whether the relevant module macros are visible.521  return Ctx.Idents.get(Id).hasMacroDefinition();522}523 524bool NSAPI::isSubclassOfNSClass(ObjCInterfaceDecl *InterfaceDecl,525                                NSClassIdKindKind NSClassKind) const {526  if (!InterfaceDecl) {527    return false;528  }529 530  IdentifierInfo *NSClassID = getNSClassId(NSClassKind);531 532  bool IsSubclass = false;533  do {534    IsSubclass = NSClassID == InterfaceDecl->getIdentifier();535 536    if (IsSubclass) {537      break;538    }539  } while ((InterfaceDecl = InterfaceDecl->getSuperClass()));540 541  return IsSubclass;542}543 544bool NSAPI::isObjCTypedef(QualType T,545                          StringRef name, IdentifierInfo *&II) const {546  if (!Ctx.getLangOpts().ObjC)547    return false;548  if (T.isNull())549    return false;550 551  if (!II)552    II = &Ctx.Idents.get(name);553 554  while (const TypedefType *TDT = T->getAs<TypedefType>()) {555    if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)556      return true;557    T = TDT->desugar();558  }559 560  return false;561}562 563bool NSAPI::isObjCEnumerator(const Expr *E,564                             StringRef name, IdentifierInfo *&II) const {565  if (!Ctx.getLangOpts().ObjC)566    return false;567  if (!E)568    return false;569 570  if (!II)571    II = &Ctx.Idents.get(name);572 573  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))574    if (const EnumConstantDecl *575          EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl()))576      return EnumD->getIdentifier() == II;577 578  return false;579}580 581Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,582                                  Selector &Sel) const {583  if (Sel.isNull()) {584    SmallVector<const IdentifierInfo *, 4> Idents;585    for (ArrayRef<StringRef>::const_iterator586           I = Ids.begin(), E = Ids.end(); I != E; ++I)587      Idents.push_back(&Ctx.Idents.get(*I));588    Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data());589  }590  return Sel;591}592 593Selector NSAPI::getOrInitNullarySelector(StringRef Id, Selector &Sel) const {594  if (Sel.isNull()) {595    const IdentifierInfo *Ident = &Ctx.Idents.get(Id);596    Sel = Ctx.Selectors.getSelector(0, &Ident);597  }598  return Sel;599}600