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