//===--- NSAPI.h - NSFoundation APIs ----------------------------*- C++ -*-===//
 
//
 
// 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
 
//
 
//===----------------------------------------------------------------------===//
 
 
 
#ifndef LLVM_CLANG_AST_NSAPI_H
 
#define LLVM_CLANG_AST_NSAPI_H
 
 
 
#include "clang/Basic/IdentifierTable.h"
 
#include "llvm/ADT/ArrayRef.h"
 
#include <optional>
 
 
 
namespace clang {
 
  class ASTContext;
 
  class ObjCInterfaceDecl;
 
  class QualType;
 
  class Expr;
 
 
 
// Provides info and caches identifiers/selectors for NSFoundation API.
 
class NSAPI {
 
public:
 
  explicit NSAPI(ASTContext &Ctx);
 
 
 
  ASTContext &getASTContext() const { return Ctx; }
 
 
 
  enum NSClassIdKindKind {
 
    ClassId_NSObject,
 
    ClassId_NSString,
 
    ClassId_NSArray,
 
    ClassId_NSMutableArray,
 
    ClassId_NSDictionary,
 
    ClassId_NSMutableDictionary,
 
    ClassId_NSNumber,
 
    ClassId_NSMutableSet,
 
    ClassId_NSMutableOrderedSet,
 
    ClassId_NSValue
 
  };
 
  static const unsigned NumClassIds = 10;
 
 
 
  enum NSStringMethodKind {
 
    NSStr_stringWithString,
 
    NSStr_stringWithUTF8String,
 
    NSStr_stringWithCStringEncoding,
 
    NSStr_stringWithCString,
 
    NSStr_initWithString,
 
    NSStr_initWithUTF8String
 
  };
 
  static const unsigned NumNSStringMethods = 6;
 
 
 
  IdentifierInfo *getNSClassId(NSClassIdKindKind K) const;
 
 
 
  /// The Objective-C NSString selectors.
 
  Selector getNSStringSelector(NSStringMethodKind MK) const;
 
 
 
  /// Returns true if the expression \param E is a reference of
 
  /// "NSUTF8StringEncoding" enum constant.
 
  bool isNSUTF8StringEncodingConstant(const Expr *E) const {
 
    return isObjCEnumerator(E, "NSUTF8StringEncoding", NSUTF8StringEncodingId);
 
  }
 
 
 
  /// Returns true if the expression \param E is a reference of
 
  /// "NSASCIIStringEncoding" enum constant.
 
  bool isNSASCIIStringEncodingConstant(const Expr *E) const {
 
    return isObjCEnumerator(E, "NSASCIIStringEncoding",NSASCIIStringEncodingId);
 
  }
 
 
 
  /// Enumerates the NSArray/NSMutableArray methods used to generate
 
  /// literals and to apply some checks.
 
  enum NSArrayMethodKind {
 
    NSArr_array,
 
    NSArr_arrayWithArray,
 
    NSArr_arrayWithObject,
 
    NSArr_arrayWithObjects,
 
    NSArr_arrayWithObjectsCount,
 
    NSArr_initWithArray,
 
    NSArr_initWithObjects,
 
    NSArr_objectAtIndex,
 
    NSMutableArr_replaceObjectAtIndex,
 
    NSMutableArr_addObject,
 
    NSMutableArr_insertObjectAtIndex,
 
    NSMutableArr_setObjectAtIndexedSubscript
 
  };
 
  static const unsigned NumNSArrayMethods = 12;
 
 
 
  /// The Objective-C NSArray selectors.
 
  Selector getNSArraySelector(NSArrayMethodKind MK) const;
 
 
 
  /// Return NSArrayMethodKind if \p Sel is such a selector.
 
  std::optional<NSArrayMethodKind> getNSArrayMethodKind(Selector Sel);
 
 
 
  /// Enumerates the NSDictionary/NSMutableDictionary methods used
 
  /// to generate literals and to apply some checks.
 
  enum NSDictionaryMethodKind {
 
    NSDict_dictionary,
 
    NSDict_dictionaryWithDictionary,
 
    NSDict_dictionaryWithObjectForKey,
 
    NSDict_dictionaryWithObjectsForKeys,
 
    NSDict_dictionaryWithObjectsForKeysCount,
 
    NSDict_dictionaryWithObjectsAndKeys,
 
    NSDict_initWithDictionary,
 
    NSDict_initWithObjectsAndKeys,
 
    NSDict_initWithObjectsForKeys,
 
    NSDict_objectForKey,
 
    NSMutableDict_setObjectForKey,
 
    NSMutableDict_setObjectForKeyedSubscript,
 
    NSMutableDict_setValueForKey
 
  };
 
  static const unsigned NumNSDictionaryMethods = 13;
 
 
 
  /// The Objective-C NSDictionary selectors.
 
  Selector getNSDictionarySelector(NSDictionaryMethodKind MK) const;
 
 
 
  /// Return NSDictionaryMethodKind if \p Sel is such a selector.
 
  std::optional<NSDictionaryMethodKind> getNSDictionaryMethodKind(Selector Sel);
 
 
 
  /// Enumerates the NSMutableSet/NSOrderedSet methods used
 
  /// to apply some checks.
 
  enum NSSetMethodKind {
 
    NSMutableSet_addObject,
 
    NSOrderedSet_insertObjectAtIndex,
 
    NSOrderedSet_setObjectAtIndex,
 
    NSOrderedSet_setObjectAtIndexedSubscript,
 
    NSOrderedSet_replaceObjectAtIndexWithObject
 
  };
 
  static const unsigned NumNSSetMethods = 5;
 
 
 
  /// The Objective-C NSSet selectors.
 
  Selector getNSSetSelector(NSSetMethodKind MK) const;
 
 
 
  /// Return NSSetMethodKind if \p Sel is such a selector.
 
  std::optional<NSSetMethodKind> getNSSetMethodKind(Selector Sel);
 
 
 
  /// Returns selector for "objectForKeyedSubscript:".
 
  Selector getObjectForKeyedSubscriptSelector() const {
 
    return getOrInitSelector(StringRef("objectForKeyedSubscript"),
 
                             objectForKeyedSubscriptSel);
 
  }
 
 
 
  /// Returns selector for "objectAtIndexedSubscript:".
 
  Selector getObjectAtIndexedSubscriptSelector() const {
 
    return getOrInitSelector(StringRef("objectAtIndexedSubscript"),
 
                             objectAtIndexedSubscriptSel);
 
  }
 
 
 
  /// Returns selector for "setObject:forKeyedSubscript".
 
  Selector getSetObjectForKeyedSubscriptSelector() const {
 
    StringRef Ids[] = { "setObject", "forKeyedSubscript" };
 
    return getOrInitSelector(Ids, setObjectForKeyedSubscriptSel);
 
  }
 
 
 
  /// Returns selector for "setObject:atIndexedSubscript".
 
  Selector getSetObjectAtIndexedSubscriptSelector() const {
 
    StringRef Ids[] = { "setObject", "atIndexedSubscript" };
 
    return getOrInitSelector(Ids, setObjectAtIndexedSubscriptSel);
 
  }
 
 
 
  /// Returns selector for "isEqual:".
 
  Selector getIsEqualSelector() const {
 
    return getOrInitSelector(StringRef("isEqual"), isEqualSel);
 
  }
 
 
 
  Selector getNewSelector() const {
 
    return getOrInitNullarySelector("new", NewSel);
 
  }
 
 
 
  Selector getInitSelector() const {
 
    return getOrInitNullarySelector("init", InitSel);
 
  }
 
 
 
  /// Enumerates the NSNumber methods used to generate literals.
 
  enum NSNumberLiteralMethodKind {
 
    NSNumberWithChar,
 
    NSNumberWithUnsignedChar,
 
    NSNumberWithShort,
 
    NSNumberWithUnsignedShort,
 
    NSNumberWithInt,
 
    NSNumberWithUnsignedInt,
 
    NSNumberWithLong,
 
    NSNumberWithUnsignedLong,
 
    NSNumberWithLongLong,
 
    NSNumberWithUnsignedLongLong,
 
    NSNumberWithFloat,
 
    NSNumberWithDouble,
 
    NSNumberWithBool,
 
    NSNumberWithInteger,
 
    NSNumberWithUnsignedInteger
 
  };
 
  static const unsigned NumNSNumberLiteralMethods = 15;
 
 
 
  /// The Objective-C NSNumber selectors used to create NSNumber literals.
 
  /// \param Instance if true it will return the selector for the init* method
 
  /// otherwise it will return the selector for the number* method.
 
  Selector getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
 
                                      bool Instance) const;
 
 
 
  bool isNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
 
                                 Selector Sel) const {
 
    return Sel == getNSNumberLiteralSelector(MK, false) ||
 
           Sel == getNSNumberLiteralSelector(MK, true);
 
  }
 
 
 
  /// Return NSNumberLiteralMethodKind if \p Sel is such a selector.
 
  std::optional<NSNumberLiteralMethodKind>
 
  getNSNumberLiteralMethodKind(Selector Sel) const;
 
 
 
  /// Determine the appropriate NSNumber factory method kind for a
 
  /// literal of the given type.
 
  std::optional<NSNumberLiteralMethodKind>
 
  getNSNumberFactoryMethodKind(QualType T) const;
 
 
 
  /// Returns true if \param T is a typedef of "BOOL" in objective-c.
 
  bool isObjCBOOLType(QualType T) const;
 
  /// Returns true if \param T is a typedef of "NSInteger" in objective-c.
 
  bool isObjCNSIntegerType(QualType T) const;
 
  /// Returns true if \param T is a typedef of "NSUInteger" in objective-c.
 
  bool isObjCNSUIntegerType(QualType T) const;
 
  /// Returns one of NSIntegral typedef names if \param T is a typedef
 
  /// of that name in objective-c.
 
  StringRef GetNSIntegralKind(QualType T) const;
 
 
 
  /// Returns \c true if \p Id is currently defined as a macro.
 
  bool isMacroDefined(StringRef Id) const;
 
 
 
  /// Returns \c true if \p InterfaceDecl is subclass of \p NSClassKind
 
  bool isSubclassOfNSClass(ObjCInterfaceDecl *InterfaceDecl,
 
                           NSClassIdKindKind NSClassKind) const;
 
 
 
private:
 
  bool isObjCTypedef(QualType T, StringRef name, IdentifierInfo *&II) const;
 
  bool isObjCEnumerator(const Expr *E,
 
                        StringRef name, IdentifierInfo *&II) const;
 
  Selector getOrInitSelector(ArrayRef<StringRef> Ids, Selector &Sel) const;
 
  Selector getOrInitNullarySelector(StringRef Id, Selector &Sel) const;
 
 
 
  ASTContext &Ctx;
 
 
 
  mutable IdentifierInfo *ClassIds[NumClassIds];
 
 
 
  mutable Selector NSStringSelectors[NumNSStringMethods];
 
 
 
  /// The selectors for Objective-C NSArray methods.
 
  mutable Selector NSArraySelectors[NumNSArrayMethods];
 
 
 
  /// The selectors for Objective-C NSDictionary methods.
 
  mutable Selector NSDictionarySelectors[NumNSDictionaryMethods];
 
 
 
  /// The selectors for Objective-C NSSet methods.
 
  mutable Selector NSSetSelectors[NumNSSetMethods];
 
 
 
  /// The Objective-C NSNumber selectors used to create NSNumber literals.
 
  mutable Selector NSNumberClassSelectors[NumNSNumberLiteralMethods];
 
  mutable Selector NSNumberInstanceSelectors[NumNSNumberLiteralMethods];
 
 
 
  mutable Selector objectForKeyedSubscriptSel, objectAtIndexedSubscriptSel,
 
                   setObjectForKeyedSubscriptSel,setObjectAtIndexedSubscriptSel,
 
                   isEqualSel, InitSel, NewSel;
 
 
 
  mutable IdentifierInfo *BOOLId, *NSIntegerId, *NSUIntegerId;
 
  mutable IdentifierInfo *NSASCIIStringEncodingId, *NSUTF8StringEncodingId;
 
};
 
 
 
}  // end namespace clang
 
 
 
#endif // LLVM_CLANG_AST_NSAPI_H