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 // \brief 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 = 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.
isNSUTF8StringEncodingConstant(const Expr * E)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.
isNSASCIIStringEncodingConstant(const Expr * E)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:".
getObjectForKeyedSubscriptSelector()141   Selector getObjectForKeyedSubscriptSelector() const {
142     return getOrInitSelector(StringRef("objectForKeyedSubscript"),
143                              objectForKeyedSubscriptSel);
144   }
145 
146   /// \brief Returns selector for "objectAtIndexedSubscript:".
getObjectAtIndexedSubscriptSelector()147   Selector getObjectAtIndexedSubscriptSelector() const {
148     return getOrInitSelector(StringRef("objectAtIndexedSubscript"),
149                              objectAtIndexedSubscriptSel);
150   }
151 
152   /// \brief Returns selector for "setObject:forKeyedSubscript".
getSetObjectForKeyedSubscriptSelector()153   Selector getSetObjectForKeyedSubscriptSelector() const {
154     StringRef Ids[] = { "setObject", "forKeyedSubscript" };
155     return getOrInitSelector(Ids, setObjectForKeyedSubscriptSel);
156   }
157 
158   /// \brief Returns selector for "setObject:atIndexedSubscript".
getSetObjectAtIndexedSubscriptSelector()159   Selector getSetObjectAtIndexedSubscriptSelector() const {
160     StringRef Ids[] = { "setObject", "atIndexedSubscript" };
161     return getOrInitSelector(Ids, setObjectAtIndexedSubscriptSel);
162   }
163 
164   /// \brief Returns selector for "isEqual:".
getIsEqualSelector()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 
isNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,Selector Sel)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 
227 private:
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