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