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 
17 namespace clang {
18   class ASTContext;
19   class ObjCInterfaceDecl;
20   class QualType;
21   class Expr;
22 
23 // Provides info and caches identifiers/selectors for NSFoundation API.
24 class NSAPI {
25 public:
26   explicit NSAPI(ASTContext &Ctx);
27 
getASTContext()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 = 6;
53 
54   IdentifierInfo *getNSClassId(NSClassIdKindKind K) const;
55 
56   /// The Objective-C NSString selectors.
57   Selector getNSStringSelector(NSStringMethodKind MK) const;
58 
59   /// Return NSStringMethodKind if \param Sel is such a selector.
60   Optional<NSStringMethodKind> getNSStringMethodKind(Selector Sel) const;
61 
62   /// Returns true if the expression \param E is a reference of
63   /// "NSUTF8StringEncoding" enum constant.
isNSUTF8StringEncodingConstant(const Expr * E)64   bool isNSUTF8StringEncodingConstant(const Expr *E) const {
65     return isObjCEnumerator(E, "NSUTF8StringEncoding", NSUTF8StringEncodingId);
66   }
67 
68   /// Returns true if the expression \param E is a reference of
69   /// "NSASCIIStringEncoding" enum constant.
isNSASCIIStringEncodingConstant(const Expr * E)70   bool isNSASCIIStringEncodingConstant(const Expr *E) const {
71     return isObjCEnumerator(E, "NSASCIIStringEncoding",NSASCIIStringEncodingId);
72   }
73 
74   /// 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   /// The Objective-C NSArray selectors.
93   Selector getNSArraySelector(NSArrayMethodKind MK) const;
94 
95   /// Return NSArrayMethodKind if \p Sel is such a selector.
96   Optional<NSArrayMethodKind> getNSArrayMethodKind(Selector Sel);
97 
98   /// 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 = 13;
116 
117   /// The Objective-C NSDictionary selectors.
118   Selector getNSDictionarySelector(NSDictionaryMethodKind MK) const;
119 
120   /// Return NSDictionaryMethodKind if \p Sel is such a selector.
121   Optional<NSDictionaryMethodKind> getNSDictionaryMethodKind(Selector Sel);
122 
123   /// 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   /// The Objective-C NSSet selectors.
135   Selector getNSSetSelector(NSSetMethodKind MK) const;
136 
137   /// Return NSSetMethodKind if \p Sel is such a selector.
138   Optional<NSSetMethodKind> getNSSetMethodKind(Selector Sel);
139 
140   /// Returns selector for "objectForKeyedSubscript:".
getObjectForKeyedSubscriptSelector()141   Selector getObjectForKeyedSubscriptSelector() const {
142     return getOrInitSelector(StringRef("objectForKeyedSubscript"),
143                              objectForKeyedSubscriptSel);
144   }
145 
146   /// Returns selector for "objectAtIndexedSubscript:".
getObjectAtIndexedSubscriptSelector()147   Selector getObjectAtIndexedSubscriptSelector() const {
148     return getOrInitSelector(StringRef("objectAtIndexedSubscript"),
149                              objectAtIndexedSubscriptSel);
150   }
151 
152   /// Returns selector for "setObject:forKeyedSubscript".
getSetObjectForKeyedSubscriptSelector()153   Selector getSetObjectForKeyedSubscriptSelector() const {
154     StringRef Ids[] = { "setObject", "forKeyedSubscript" };
155     return getOrInitSelector(Ids, setObjectForKeyedSubscriptSel);
156   }
157 
158   /// Returns selector for "setObject:atIndexedSubscript".
getSetObjectAtIndexedSubscriptSelector()159   Selector getSetObjectAtIndexedSubscriptSelector() const {
160     StringRef Ids[] = { "setObject", "atIndexedSubscript" };
161     return getOrInitSelector(Ids, setObjectAtIndexedSubscriptSel);
162   }
163 
164   /// Returns selector for "isEqual:".
getIsEqualSelector()165   Selector getIsEqualSelector() const {
166     return getOrInitSelector(StringRef("isEqual"), isEqualSel);
167   }
168 
getNewSelector()169   Selector getNewSelector() const {
170     return getOrInitNullarySelector("new", NewSel);
171   }
172 
getInitSelector()173   Selector getInitSelector() const {
174     return getOrInitNullarySelector("init", InitSel);
175   }
176 
177   /// Enumerates the NSNumber methods used to generate literals.
178   enum NSNumberLiteralMethodKind {
179     NSNumberWithChar,
180     NSNumberWithUnsignedChar,
181     NSNumberWithShort,
182     NSNumberWithUnsignedShort,
183     NSNumberWithInt,
184     NSNumberWithUnsignedInt,
185     NSNumberWithLong,
186     NSNumberWithUnsignedLong,
187     NSNumberWithLongLong,
188     NSNumberWithUnsignedLongLong,
189     NSNumberWithFloat,
190     NSNumberWithDouble,
191     NSNumberWithBool,
192     NSNumberWithInteger,
193     NSNumberWithUnsignedInteger
194   };
195   static const unsigned NumNSNumberLiteralMethods = 15;
196 
197   /// The Objective-C NSNumber selectors used to create NSNumber literals.
198   /// \param Instance if true it will return the selector for the init* method
199   /// otherwise it will return the selector for the number* method.
200   Selector getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
201                                       bool Instance) const;
202 
isNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,Selector Sel)203   bool isNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
204                                  Selector Sel) const {
205     return Sel == getNSNumberLiteralSelector(MK, false) ||
206            Sel == getNSNumberLiteralSelector(MK, true);
207   }
208 
209   /// Return NSNumberLiteralMethodKind if \p Sel is such a selector.
210   Optional<NSNumberLiteralMethodKind>
211       getNSNumberLiteralMethodKind(Selector Sel) const;
212 
213   /// Determine the appropriate NSNumber factory method kind for a
214   /// literal of the given type.
215   Optional<NSNumberLiteralMethodKind>
216       getNSNumberFactoryMethodKind(QualType T) const;
217 
218   /// Returns true if \param T is a typedef of "BOOL" in objective-c.
219   bool isObjCBOOLType(QualType T) const;
220   /// Returns true if \param T is a typedef of "NSInteger" in objective-c.
221   bool isObjCNSIntegerType(QualType T) const;
222   /// Returns true if \param T is a typedef of "NSUInteger" in objective-c.
223   bool isObjCNSUIntegerType(QualType T) const;
224   /// Returns one of NSIntegral typedef names if \param T is a typedef
225   /// of that name in objective-c.
226   StringRef GetNSIntegralKind(QualType T) const;
227 
228   /// Returns \c true if \p Id is currently defined as a macro.
229   bool isMacroDefined(StringRef Id) const;
230 
231   /// Returns \c true if \p InterfaceDecl is subclass of \p NSClassKind
232   bool isSubclassOfNSClass(ObjCInterfaceDecl *InterfaceDecl,
233                            NSClassIdKindKind NSClassKind) const;
234 
235 private:
236   bool isObjCTypedef(QualType T, StringRef name, IdentifierInfo *&II) const;
237   bool isObjCEnumerator(const Expr *E,
238                         StringRef name, IdentifierInfo *&II) const;
239   Selector getOrInitSelector(ArrayRef<StringRef> Ids, Selector &Sel) const;
240   Selector getOrInitNullarySelector(StringRef Id, Selector &Sel) const;
241 
242   ASTContext &Ctx;
243 
244   mutable IdentifierInfo *ClassIds[NumClassIds];
245 
246   mutable Selector NSStringSelectors[NumNSStringMethods];
247 
248   /// The selectors for Objective-C NSArray methods.
249   mutable Selector NSArraySelectors[NumNSArrayMethods];
250 
251   /// The selectors for Objective-C NSDictionary methods.
252   mutable Selector NSDictionarySelectors[NumNSDictionaryMethods];
253 
254   /// The selectors for Objective-C NSSet methods.
255   mutable Selector NSSetSelectors[NumNSSetMethods];
256 
257   /// The Objective-C NSNumber selectors used to create NSNumber literals.
258   mutable Selector NSNumberClassSelectors[NumNSNumberLiteralMethods];
259   mutable Selector NSNumberInstanceSelectors[NumNSNumberLiteralMethods];
260 
261   mutable Selector objectForKeyedSubscriptSel, objectAtIndexedSubscriptSel,
262                    setObjectForKeyedSubscriptSel,setObjectAtIndexedSubscriptSel,
263                    isEqualSel, InitSel, NewSel;
264 
265   mutable IdentifierInfo *BOOLId, *NSIntegerId, *NSUIntegerId;
266   mutable IdentifierInfo *NSASCIIStringEncodingId, *NSUTF8StringEncodingId;
267 };
268 
269 }  // end namespace clang
270 
271 #endif // LLVM_CLANG_AST_NSAPI_H
272