1//===--- NSAPI.h - NSFoundation APIs ----------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef LLVM_CLANG_AST_NSAPI_H
11#define LLVM_CLANG_AST_NSAPI_H
12
13#include "clang/Basic/IdentifierTable.h"
14#include "llvm/ADT/ArrayRef.h"
15#include "llvm/ADT/Optional.h"
16
17namespace clang {
18  class ASTContext;
19  class ObjCInterfaceDecl;
20  class QualType;
21  class Expr;
22
23// \brief Provides info and caches identifiers/selectors for NSFoundation API.
24class NSAPI {
25public:
26  explicit NSAPI(ASTContext &Ctx);
27
28  ASTContext &getASTContext() const { return Ctx; }
29
30  enum NSClassIdKindKind {
31    ClassId_NSObject,
32    ClassId_NSString,
33    ClassId_NSArray,
34    ClassId_NSMutableArray,
35    ClassId_NSDictionary,
36    ClassId_NSMutableDictionary,
37    ClassId_NSNumber,
38    ClassId_NSMutableSet,
39    ClassId_NSMutableOrderedSet,
40    ClassId_NSValue
41  };
42  static const unsigned NumClassIds = 10;
43
44  enum NSStringMethodKind {
45    NSStr_stringWithString,
46    NSStr_stringWithUTF8String,
47    NSStr_stringWithCStringEncoding,
48    NSStr_stringWithCString,
49    NSStr_initWithString,
50    NSStr_initWithUTF8String
51  };
52  static const unsigned NumNSStringMethods = 5;
53
54  IdentifierInfo *getNSClassId(NSClassIdKindKind K) const;
55
56  /// \brief The Objective-C NSString selectors.
57  Selector getNSStringSelector(NSStringMethodKind MK) const;
58
59  /// \brief Return NSStringMethodKind if \param Sel is such a selector.
60  Optional<NSStringMethodKind> getNSStringMethodKind(Selector Sel) const;
61
62  /// \brief Returns true if the expression \param E is a reference of
63  /// "NSUTF8StringEncoding" enum constant.
64  bool isNSUTF8StringEncodingConstant(const Expr *E) const {
65    return isObjCEnumerator(E, "NSUTF8StringEncoding", NSUTF8StringEncodingId);
66  }
67
68  /// \brief Returns true if the expression \param E is a reference of
69  /// "NSASCIIStringEncoding" enum constant.
70  bool isNSASCIIStringEncodingConstant(const Expr *E) const {
71    return isObjCEnumerator(E, "NSASCIIStringEncoding",NSASCIIStringEncodingId);
72  }
73
74  /// \brief Enumerates the NSArray/NSMutableArray methods used to generate
75  /// literals and to apply some checks.
76  enum NSArrayMethodKind {
77    NSArr_array,
78    NSArr_arrayWithArray,
79    NSArr_arrayWithObject,
80    NSArr_arrayWithObjects,
81    NSArr_arrayWithObjectsCount,
82    NSArr_initWithArray,
83    NSArr_initWithObjects,
84    NSArr_objectAtIndex,
85    NSMutableArr_replaceObjectAtIndex,
86    NSMutableArr_addObject,
87    NSMutableArr_insertObjectAtIndex,
88    NSMutableArr_setObjectAtIndexedSubscript
89  };
90  static const unsigned NumNSArrayMethods = 12;
91
92  /// \brief The Objective-C NSArray selectors.
93  Selector getNSArraySelector(NSArrayMethodKind MK) const;
94
95  /// \brief Return NSArrayMethodKind if \p Sel is such a selector.
96  Optional<NSArrayMethodKind> getNSArrayMethodKind(Selector Sel);
97
98  /// \brief Enumerates the NSDictionary/NSMutableDictionary methods used
99  /// to generate literals and to apply some checks.
100  enum NSDictionaryMethodKind {
101    NSDict_dictionary,
102    NSDict_dictionaryWithDictionary,
103    NSDict_dictionaryWithObjectForKey,
104    NSDict_dictionaryWithObjectsForKeys,
105    NSDict_dictionaryWithObjectsForKeysCount,
106    NSDict_dictionaryWithObjectsAndKeys,
107    NSDict_initWithDictionary,
108    NSDict_initWithObjectsAndKeys,
109    NSDict_initWithObjectsForKeys,
110    NSDict_objectForKey,
111    NSMutableDict_setObjectForKey,
112    NSMutableDict_setObjectForKeyedSubscript,
113    NSMutableDict_setValueForKey
114  };
115  static const unsigned NumNSDictionaryMethods = 14;
116
117  /// \brief The Objective-C NSDictionary selectors.
118  Selector getNSDictionarySelector(NSDictionaryMethodKind MK) const;
119
120  /// \brief Return NSDictionaryMethodKind if \p Sel is such a selector.
121  Optional<NSDictionaryMethodKind> getNSDictionaryMethodKind(Selector Sel);
122
123  /// \brief Enumerates the NSMutableSet/NSOrderedSet methods used
124  /// to apply some checks.
125  enum NSSetMethodKind {
126    NSMutableSet_addObject,
127    NSOrderedSet_insertObjectAtIndex,
128    NSOrderedSet_setObjectAtIndex,
129    NSOrderedSet_setObjectAtIndexedSubscript,
130    NSOrderedSet_replaceObjectAtIndexWithObject
131  };
132  static const unsigned NumNSSetMethods = 5;
133
134  /// \brief The Objective-C NSSet selectors.
135  Selector getNSSetSelector(NSSetMethodKind MK) const;
136
137  /// \brief Return NSSetMethodKind if \p Sel is such a selector.
138  Optional<NSSetMethodKind> getNSSetMethodKind(Selector Sel);
139
140  /// \brief Returns selector for "objectForKeyedSubscript:".
141  Selector getObjectForKeyedSubscriptSelector() const {
142    return getOrInitSelector(StringRef("objectForKeyedSubscript"),
143                             objectForKeyedSubscriptSel);
144  }
145
146  /// \brief Returns selector for "objectAtIndexedSubscript:".
147  Selector getObjectAtIndexedSubscriptSelector() const {
148    return getOrInitSelector(StringRef("objectAtIndexedSubscript"),
149                             objectAtIndexedSubscriptSel);
150  }
151
152  /// \brief Returns selector for "setObject:forKeyedSubscript".
153  Selector getSetObjectForKeyedSubscriptSelector() const {
154    StringRef Ids[] = { "setObject", "forKeyedSubscript" };
155    return getOrInitSelector(Ids, setObjectForKeyedSubscriptSel);
156  }
157
158  /// \brief Returns selector for "setObject:atIndexedSubscript".
159  Selector getSetObjectAtIndexedSubscriptSelector() const {
160    StringRef Ids[] = { "setObject", "atIndexedSubscript" };
161    return getOrInitSelector(Ids, setObjectAtIndexedSubscriptSel);
162  }
163
164  /// \brief Returns selector for "isEqual:".
165  Selector getIsEqualSelector() const {
166    return getOrInitSelector(StringRef("isEqual"), isEqualSel);
167  }
168
169  /// \brief Enumerates the NSNumber methods used to generate literals.
170  enum NSNumberLiteralMethodKind {
171    NSNumberWithChar,
172    NSNumberWithUnsignedChar,
173    NSNumberWithShort,
174    NSNumberWithUnsignedShort,
175    NSNumberWithInt,
176    NSNumberWithUnsignedInt,
177    NSNumberWithLong,
178    NSNumberWithUnsignedLong,
179    NSNumberWithLongLong,
180    NSNumberWithUnsignedLongLong,
181    NSNumberWithFloat,
182    NSNumberWithDouble,
183    NSNumberWithBool,
184    NSNumberWithInteger,
185    NSNumberWithUnsignedInteger
186  };
187  static const unsigned NumNSNumberLiteralMethods = 15;
188
189  /// \brief The Objective-C NSNumber selectors used to create NSNumber literals.
190  /// \param Instance if true it will return the selector for the init* method
191  /// otherwise it will return the selector for the number* method.
192  Selector getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
193                                      bool Instance) const;
194
195  bool isNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
196                                 Selector Sel) const {
197    return Sel == getNSNumberLiteralSelector(MK, false) ||
198           Sel == getNSNumberLiteralSelector(MK, true);
199  }
200
201  /// \brief Return NSNumberLiteralMethodKind if \p Sel is such a selector.
202  Optional<NSNumberLiteralMethodKind>
203      getNSNumberLiteralMethodKind(Selector Sel) const;
204
205  /// \brief Determine the appropriate NSNumber factory method kind for a
206  /// literal of the given type.
207  Optional<NSNumberLiteralMethodKind>
208      getNSNumberFactoryMethodKind(QualType T) const;
209
210  /// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
211  bool isObjCBOOLType(QualType T) const;
212  /// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
213  bool isObjCNSIntegerType(QualType T) const;
214  /// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
215  bool isObjCNSUIntegerType(QualType T) const;
216  /// \brief Returns one of NSIntegral typedef names if \param T is a typedef
217  /// of that name in objective-c.
218  StringRef GetNSIntegralKind(QualType T) const;
219
220  /// \brief Returns \c true if \p Id is currently defined as a macro.
221  bool isMacroDefined(StringRef Id) const;
222
223  /// \brief Returns \c true if \p InterfaceDecl is subclass of \p NSClassKind
224  bool isSubclassOfNSClass(ObjCInterfaceDecl *InterfaceDecl,
225                           NSClassIdKindKind NSClassKind) const;
226
227private:
228  bool isObjCTypedef(QualType T, StringRef name, IdentifierInfo *&II) const;
229  bool isObjCEnumerator(const Expr *E,
230                        StringRef name, IdentifierInfo *&II) const;
231  Selector getOrInitSelector(ArrayRef<StringRef> Ids, Selector &Sel) const;
232
233  ASTContext &Ctx;
234
235  mutable IdentifierInfo *ClassIds[NumClassIds];
236
237  mutable Selector NSStringSelectors[NumNSStringMethods];
238
239  /// \brief The selectors for Objective-C NSArray methods.
240  mutable Selector NSArraySelectors[NumNSArrayMethods];
241
242  /// \brief The selectors for Objective-C NSDictionary methods.
243  mutable Selector NSDictionarySelectors[NumNSDictionaryMethods];
244
245  /// \brief The selectors for Objective-C NSSet methods.
246  mutable Selector NSSetSelectors[NumNSSetMethods];
247
248  /// \brief The Objective-C NSNumber selectors used to create NSNumber literals.
249  mutable Selector NSNumberClassSelectors[NumNSNumberLiteralMethods];
250  mutable Selector NSNumberInstanceSelectors[NumNSNumberLiteralMethods];
251
252  mutable Selector objectForKeyedSubscriptSel, objectAtIndexedSubscriptSel,
253                   setObjectForKeyedSubscriptSel,setObjectAtIndexedSubscriptSel,
254                   isEqualSel;
255
256  mutable IdentifierInfo *BOOLId, *NSIntegerId, *NSUIntegerId;
257  mutable IdentifierInfo *NSASCIIStringEncodingId, *NSUTF8StringEncodingId;
258};
259
260}  // end namespace clang
261
262#endif // LLVM_CLANG_AST_NSAPI_H
263