File: | tools/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp |
Warning: | line 756, column 17 Value stored to 'ErrNode' during its initialization is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //=- LocalizationChecker.cpp -------------------------------------*- 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 | // This file defines a set of checks for localizability including: |
10 | // 1) A checker that warns about uses of non-localized NSStrings passed to |
11 | // UI methods expecting localized strings |
12 | // 2) A syntactic checker that warns against the bad practice of |
13 | // not including a comment in NSLocalizedString macros. |
14 | // |
15 | //===----------------------------------------------------------------------===// |
16 | |
17 | #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" |
18 | #include "clang/AST/Attr.h" |
19 | #include "clang/AST/Decl.h" |
20 | #include "clang/AST/DeclObjC.h" |
21 | #include "clang/AST/RecursiveASTVisitor.h" |
22 | #include "clang/AST/StmtVisitor.h" |
23 | #include "clang/Lex/Lexer.h" |
24 | #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" |
25 | #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" |
26 | #include "clang/StaticAnalyzer/Core/Checker.h" |
27 | #include "clang/StaticAnalyzer/Core/CheckerManager.h" |
28 | #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" |
29 | #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" |
30 | #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" |
31 | #include "llvm/Support/Unicode.h" |
32 | |
33 | using namespace clang; |
34 | using namespace ento; |
35 | |
36 | namespace { |
37 | struct LocalizedState { |
38 | private: |
39 | enum Kind { NonLocalized, Localized } K; |
40 | LocalizedState(Kind InK) : K(InK) {} |
41 | |
42 | public: |
43 | bool isLocalized() const { return K == Localized; } |
44 | bool isNonLocalized() const { return K == NonLocalized; } |
45 | |
46 | static LocalizedState getLocalized() { return LocalizedState(Localized); } |
47 | static LocalizedState getNonLocalized() { |
48 | return LocalizedState(NonLocalized); |
49 | } |
50 | |
51 | // Overload the == operator |
52 | bool operator==(const LocalizedState &X) const { return K == X.K; } |
53 | |
54 | // LLVMs equivalent of a hash function |
55 | void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(K); } |
56 | }; |
57 | |
58 | class NonLocalizedStringChecker |
59 | : public Checker<check::PreCall, check::PostCall, check::PreObjCMessage, |
60 | check::PostObjCMessage, |
61 | check::PostStmt<ObjCStringLiteral>> { |
62 | |
63 | mutable std::unique_ptr<BugType> BT; |
64 | |
65 | // Methods that require a localized string |
66 | mutable llvm::DenseMap<const IdentifierInfo *, |
67 | llvm::DenseMap<Selector, uint8_t>> UIMethods; |
68 | // Methods that return a localized string |
69 | mutable llvm::SmallSet<std::pair<const IdentifierInfo *, Selector>, 12> LSM; |
70 | // C Functions that return a localized string |
71 | mutable llvm::SmallSet<const IdentifierInfo *, 5> LSF; |
72 | |
73 | void initUIMethods(ASTContext &Ctx) const; |
74 | void initLocStringsMethods(ASTContext &Ctx) const; |
75 | |
76 | bool hasNonLocalizedState(SVal S, CheckerContext &C) const; |
77 | bool hasLocalizedState(SVal S, CheckerContext &C) const; |
78 | void setNonLocalizedState(SVal S, CheckerContext &C) const; |
79 | void setLocalizedState(SVal S, CheckerContext &C) const; |
80 | |
81 | bool isAnnotatedAsReturningLocalized(const Decl *D) const; |
82 | bool isAnnotatedAsTakingLocalized(const Decl *D) const; |
83 | void reportLocalizationError(SVal S, const CallEvent &M, CheckerContext &C, |
84 | int argumentNumber = 0) const; |
85 | |
86 | int getLocalizedArgumentForSelector(const IdentifierInfo *Receiver, |
87 | Selector S) const; |
88 | |
89 | public: |
90 | NonLocalizedStringChecker(); |
91 | |
92 | // When this parameter is set to true, the checker assumes all |
93 | // methods that return NSStrings are unlocalized. Thus, more false |
94 | // positives will be reported. |
95 | DefaultBool IsAggressive; |
96 | |
97 | void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const; |
98 | void checkPostObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const; |
99 | void checkPostStmt(const ObjCStringLiteral *SL, CheckerContext &C) const; |
100 | void checkPreCall(const CallEvent &Call, CheckerContext &C) const; |
101 | void checkPostCall(const CallEvent &Call, CheckerContext &C) const; |
102 | }; |
103 | |
104 | } // end anonymous namespace |
105 | |
106 | REGISTER_MAP_WITH_PROGRAMSTATE(LocalizedMemMap, const MemRegion *,namespace { class LocalizedMemMap {}; using LocalizedMemMapTy = llvm::ImmutableMap<const MemRegion *, LocalizedState> ; } namespace clang { namespace ento { template <> struct ProgramStateTrait<LocalizedMemMap> : public ProgramStatePartialTrait <LocalizedMemMapTy> { static void *GDMIndex() { static int Index; return &Index; } }; } } |
107 | LocalizedState)namespace { class LocalizedMemMap {}; using LocalizedMemMapTy = llvm::ImmutableMap<const MemRegion *, LocalizedState> ; } namespace clang { namespace ento { template <> struct ProgramStateTrait<LocalizedMemMap> : public ProgramStatePartialTrait <LocalizedMemMapTy> { static void *GDMIndex() { static int Index; return &Index; } }; } } |
108 | |
109 | NonLocalizedStringChecker::NonLocalizedStringChecker() { |
110 | BT.reset(new BugType(this, "Unlocalizable string", |
111 | "Localizability Issue (Apple)")); |
112 | } |
113 | |
114 | namespace { |
115 | class NonLocalizedStringBRVisitor final : public BugReporterVisitor { |
116 | |
117 | const MemRegion *NonLocalizedString; |
118 | bool Satisfied; |
119 | |
120 | public: |
121 | NonLocalizedStringBRVisitor(const MemRegion *NonLocalizedString) |
122 | : NonLocalizedString(NonLocalizedString), Satisfied(false) { |
123 | assert(NonLocalizedString)((NonLocalizedString) ? static_cast<void> (0) : __assert_fail ("NonLocalizedString", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp" , 123, __PRETTY_FUNCTION__)); |
124 | } |
125 | |
126 | std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *Succ, |
127 | BugReporterContext &BRC, |
128 | BugReport &BR) override; |
129 | |
130 | void Profile(llvm::FoldingSetNodeID &ID) const override { |
131 | ID.Add(NonLocalizedString); |
132 | } |
133 | }; |
134 | } // End anonymous namespace. |
135 | |
136 | #define NEW_RECEIVER(receiver)llvm::DenseMap<Selector, uint8_t> &receiverM = UIMethods .insert({&Ctx.Idents.get("receiver"), llvm::DenseMap<Selector , uint8_t>()}) .first->second; \ |
137 | llvm::DenseMap<Selector, uint8_t> &receiver##M = \ |
138 | UIMethods.insert({&Ctx.Idents.get(#receiver), \ |
139 | llvm::DenseMap<Selector, uint8_t>()}) \ |
140 | .first->second; |
141 | #define ADD_NULLARY_METHOD(receiver, method, argument)receiverM.insert( {Ctx.Selectors.getNullarySelector(&Ctx. Idents.get("method")), argument}); \ |
142 | receiver##M.insert( \ |
143 | {Ctx.Selectors.getNullarySelector(&Ctx.Idents.get(#method)), argument}); |
144 | #define ADD_UNARY_METHOD(receiver, method, argument)receiverM.insert( {Ctx.Selectors.getUnarySelector(&Ctx.Idents .get("method")), argument}); \ |
145 | receiver##M.insert( \ |
146 | {Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(#method)), argument}); |
147 | #define ADD_METHOD(receiver, method_list, count, argument)receiverM.insert({Ctx.Selectors.getSelector(count, method_list ), argument}); \ |
148 | receiver##M.insert({Ctx.Selectors.getSelector(count, method_list), argument}); |
149 | |
150 | /// Initializes a list of methods that require a localized string |
151 | /// Format: {"ClassName", {{"selectorName:", LocStringArg#}, ...}, ...} |
152 | void NonLocalizedStringChecker::initUIMethods(ASTContext &Ctx) const { |
153 | if (!UIMethods.empty()) |
154 | return; |
155 | |
156 | // UI Methods |
157 | NEW_RECEIVER(UISearchDisplayController)llvm::DenseMap<Selector, uint8_t> &UISearchDisplayControllerM = UIMethods.insert({&Ctx.Idents.get("UISearchDisplayController" ), llvm::DenseMap<Selector, uint8_t>()}) .first->second ; |
158 | ADD_UNARY_METHOD(UISearchDisplayController, setSearchResultsTitle, 0)UISearchDisplayControllerM.insert( {Ctx.Selectors.getUnarySelector (&Ctx.Idents.get("setSearchResultsTitle")), 0}); |
159 | |
160 | NEW_RECEIVER(UITabBarItem)llvm::DenseMap<Selector, uint8_t> &UITabBarItemM = UIMethods .insert({&Ctx.Idents.get("UITabBarItem"), llvm::DenseMap< Selector, uint8_t>()}) .first->second; |
161 | IdentifierInfo *initWithTitleUITabBarItemTag[] = { |
162 | &Ctx.Idents.get("initWithTitle"), &Ctx.Idents.get("image"), |
163 | &Ctx.Idents.get("tag")}; |
164 | ADD_METHOD(UITabBarItem, initWithTitleUITabBarItemTag, 3, 0)UITabBarItemM.insert({Ctx.Selectors.getSelector(3, initWithTitleUITabBarItemTag ), 0}); |
165 | IdentifierInfo *initWithTitleUITabBarItemImage[] = { |
166 | &Ctx.Idents.get("initWithTitle"), &Ctx.Idents.get("image"), |
167 | &Ctx.Idents.get("selectedImage")}; |
168 | ADD_METHOD(UITabBarItem, initWithTitleUITabBarItemImage, 3, 0)UITabBarItemM.insert({Ctx.Selectors.getSelector(3, initWithTitleUITabBarItemImage ), 0}); |
169 | |
170 | NEW_RECEIVER(NSDockTile)llvm::DenseMap<Selector, uint8_t> &NSDockTileM = UIMethods .insert({&Ctx.Idents.get("NSDockTile"), llvm::DenseMap< Selector, uint8_t>()}) .first->second; |
171 | ADD_UNARY_METHOD(NSDockTile, setBadgeLabel, 0)NSDockTileM.insert( {Ctx.Selectors.getUnarySelector(&Ctx. Idents.get("setBadgeLabel")), 0}); |
172 | |
173 | NEW_RECEIVER(NSStatusItem)llvm::DenseMap<Selector, uint8_t> &NSStatusItemM = UIMethods .insert({&Ctx.Idents.get("NSStatusItem"), llvm::DenseMap< Selector, uint8_t>()}) .first->second; |
174 | ADD_UNARY_METHOD(NSStatusItem, setTitle, 0)NSStatusItemM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setTitle")), 0}); |
175 | ADD_UNARY_METHOD(NSStatusItem, setToolTip, 0)NSStatusItemM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setToolTip")), 0}); |
176 | |
177 | NEW_RECEIVER(UITableViewRowAction)llvm::DenseMap<Selector, uint8_t> &UITableViewRowActionM = UIMethods.insert({&Ctx.Idents.get("UITableViewRowAction" ), llvm::DenseMap<Selector, uint8_t>()}) .first->second ; |
178 | IdentifierInfo *rowActionWithStyleUITableViewRowAction[] = { |
179 | &Ctx.Idents.get("rowActionWithStyle"), &Ctx.Idents.get("title"), |
180 | &Ctx.Idents.get("handler")}; |
181 | ADD_METHOD(UITableViewRowAction, rowActionWithStyleUITableViewRowAction, 3, 1)UITableViewRowActionM.insert({Ctx.Selectors.getSelector(3, rowActionWithStyleUITableViewRowAction ), 1}); |
182 | ADD_UNARY_METHOD(UITableViewRowAction, setTitle, 0)UITableViewRowActionM.insert( {Ctx.Selectors.getUnarySelector (&Ctx.Idents.get("setTitle")), 0}); |
183 | |
184 | NEW_RECEIVER(NSBox)llvm::DenseMap<Selector, uint8_t> &NSBoxM = UIMethods .insert({&Ctx.Idents.get("NSBox"), llvm::DenseMap<Selector , uint8_t>()}) .first->second; |
185 | ADD_UNARY_METHOD(NSBox, setTitle, 0)NSBoxM.insert( {Ctx.Selectors.getUnarySelector(&Ctx.Idents .get("setTitle")), 0}); |
186 | |
187 | NEW_RECEIVER(NSButton)llvm::DenseMap<Selector, uint8_t> &NSButtonM = UIMethods .insert({&Ctx.Idents.get("NSButton"), llvm::DenseMap<Selector , uint8_t>()}) .first->second; |
188 | ADD_UNARY_METHOD(NSButton, setTitle, 0)NSButtonM.insert( {Ctx.Selectors.getUnarySelector(&Ctx.Idents .get("setTitle")), 0}); |
189 | ADD_UNARY_METHOD(NSButton, setAlternateTitle, 0)NSButtonM.insert( {Ctx.Selectors.getUnarySelector(&Ctx.Idents .get("setAlternateTitle")), 0}); |
190 | IdentifierInfo *radioButtonWithTitleNSButton[] = { |
191 | &Ctx.Idents.get("radioButtonWithTitle"), &Ctx.Idents.get("target"), |
192 | &Ctx.Idents.get("action")}; |
193 | ADD_METHOD(NSButton, radioButtonWithTitleNSButton, 3, 0)NSButtonM.insert({Ctx.Selectors.getSelector(3, radioButtonWithTitleNSButton ), 0}); |
194 | IdentifierInfo *buttonWithTitleNSButtonImage[] = { |
195 | &Ctx.Idents.get("buttonWithTitle"), &Ctx.Idents.get("image"), |
196 | &Ctx.Idents.get("target"), &Ctx.Idents.get("action")}; |
197 | ADD_METHOD(NSButton, buttonWithTitleNSButtonImage, 4, 0)NSButtonM.insert({Ctx.Selectors.getSelector(4, buttonWithTitleNSButtonImage ), 0}); |
198 | IdentifierInfo *checkboxWithTitleNSButton[] = { |
199 | &Ctx.Idents.get("checkboxWithTitle"), &Ctx.Idents.get("target"), |
200 | &Ctx.Idents.get("action")}; |
201 | ADD_METHOD(NSButton, checkboxWithTitleNSButton, 3, 0)NSButtonM.insert({Ctx.Selectors.getSelector(3, checkboxWithTitleNSButton ), 0}); |
202 | IdentifierInfo *buttonWithTitleNSButtonTarget[] = { |
203 | &Ctx.Idents.get("buttonWithTitle"), &Ctx.Idents.get("target"), |
204 | &Ctx.Idents.get("action")}; |
205 | ADD_METHOD(NSButton, buttonWithTitleNSButtonTarget, 3, 0)NSButtonM.insert({Ctx.Selectors.getSelector(3, buttonWithTitleNSButtonTarget ), 0}); |
206 | |
207 | NEW_RECEIVER(NSSavePanel)llvm::DenseMap<Selector, uint8_t> &NSSavePanelM = UIMethods .insert({&Ctx.Idents.get("NSSavePanel"), llvm::DenseMap< Selector, uint8_t>()}) .first->second; |
208 | ADD_UNARY_METHOD(NSSavePanel, setPrompt, 0)NSSavePanelM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setPrompt")), 0}); |
209 | ADD_UNARY_METHOD(NSSavePanel, setTitle, 0)NSSavePanelM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setTitle")), 0}); |
210 | ADD_UNARY_METHOD(NSSavePanel, setNameFieldLabel, 0)NSSavePanelM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setNameFieldLabel")), 0}); |
211 | ADD_UNARY_METHOD(NSSavePanel, setNameFieldStringValue, 0)NSSavePanelM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setNameFieldStringValue")), 0}); |
212 | ADD_UNARY_METHOD(NSSavePanel, setMessage, 0)NSSavePanelM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setMessage")), 0}); |
213 | |
214 | NEW_RECEIVER(UIPrintInfo)llvm::DenseMap<Selector, uint8_t> &UIPrintInfoM = UIMethods .insert({&Ctx.Idents.get("UIPrintInfo"), llvm::DenseMap< Selector, uint8_t>()}) .first->second; |
215 | ADD_UNARY_METHOD(UIPrintInfo, setJobName, 0)UIPrintInfoM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setJobName")), 0}); |
216 | |
217 | NEW_RECEIVER(NSTabViewItem)llvm::DenseMap<Selector, uint8_t> &NSTabViewItemM = UIMethods.insert({&Ctx.Idents.get("NSTabViewItem"), llvm ::DenseMap<Selector, uint8_t>()}) .first->second; |
218 | ADD_UNARY_METHOD(NSTabViewItem, setLabel, 0)NSTabViewItemM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setLabel")), 0}); |
219 | ADD_UNARY_METHOD(NSTabViewItem, setToolTip, 0)NSTabViewItemM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setToolTip")), 0}); |
220 | |
221 | NEW_RECEIVER(NSBrowser)llvm::DenseMap<Selector, uint8_t> &NSBrowserM = UIMethods .insert({&Ctx.Idents.get("NSBrowser"), llvm::DenseMap< Selector, uint8_t>()}) .first->second; |
222 | IdentifierInfo *setTitleNSBrowser[] = {&Ctx.Idents.get("setTitle"), |
223 | &Ctx.Idents.get("ofColumn")}; |
224 | ADD_METHOD(NSBrowser, setTitleNSBrowser, 2, 0)NSBrowserM.insert({Ctx.Selectors.getSelector(2, setTitleNSBrowser ), 0}); |
225 | |
226 | NEW_RECEIVER(UIAccessibilityElement)llvm::DenseMap<Selector, uint8_t> &UIAccessibilityElementM = UIMethods.insert({&Ctx.Idents.get("UIAccessibilityElement" ), llvm::DenseMap<Selector, uint8_t>()}) .first->second ; |
227 | ADD_UNARY_METHOD(UIAccessibilityElement, setAccessibilityLabel, 0)UIAccessibilityElementM.insert( {Ctx.Selectors.getUnarySelector (&Ctx.Idents.get("setAccessibilityLabel")), 0}); |
228 | ADD_UNARY_METHOD(UIAccessibilityElement, setAccessibilityHint, 0)UIAccessibilityElementM.insert( {Ctx.Selectors.getUnarySelector (&Ctx.Idents.get("setAccessibilityHint")), 0}); |
229 | ADD_UNARY_METHOD(UIAccessibilityElement, setAccessibilityValue, 0)UIAccessibilityElementM.insert( {Ctx.Selectors.getUnarySelector (&Ctx.Idents.get("setAccessibilityValue")), 0}); |
230 | |
231 | NEW_RECEIVER(UIAlertAction)llvm::DenseMap<Selector, uint8_t> &UIAlertActionM = UIMethods.insert({&Ctx.Idents.get("UIAlertAction"), llvm ::DenseMap<Selector, uint8_t>()}) .first->second; |
232 | IdentifierInfo *actionWithTitleUIAlertAction[] = { |
233 | &Ctx.Idents.get("actionWithTitle"), &Ctx.Idents.get("style"), |
234 | &Ctx.Idents.get("handler")}; |
235 | ADD_METHOD(UIAlertAction, actionWithTitleUIAlertAction, 3, 0)UIAlertActionM.insert({Ctx.Selectors.getSelector(3, actionWithTitleUIAlertAction ), 0}); |
236 | |
237 | NEW_RECEIVER(NSPopUpButton)llvm::DenseMap<Selector, uint8_t> &NSPopUpButtonM = UIMethods.insert({&Ctx.Idents.get("NSPopUpButton"), llvm ::DenseMap<Selector, uint8_t>()}) .first->second; |
238 | ADD_UNARY_METHOD(NSPopUpButton, addItemWithTitle, 0)NSPopUpButtonM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("addItemWithTitle")), 0}); |
239 | IdentifierInfo *insertItemWithTitleNSPopUpButton[] = { |
240 | &Ctx.Idents.get("insertItemWithTitle"), &Ctx.Idents.get("atIndex")}; |
241 | ADD_METHOD(NSPopUpButton, insertItemWithTitleNSPopUpButton, 2, 0)NSPopUpButtonM.insert({Ctx.Selectors.getSelector(2, insertItemWithTitleNSPopUpButton ), 0}); |
242 | ADD_UNARY_METHOD(NSPopUpButton, removeItemWithTitle, 0)NSPopUpButtonM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("removeItemWithTitle")), 0}); |
243 | ADD_UNARY_METHOD(NSPopUpButton, selectItemWithTitle, 0)NSPopUpButtonM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("selectItemWithTitle")), 0}); |
244 | ADD_UNARY_METHOD(NSPopUpButton, setTitle, 0)NSPopUpButtonM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setTitle")), 0}); |
245 | |
246 | NEW_RECEIVER(NSTableViewRowAction)llvm::DenseMap<Selector, uint8_t> &NSTableViewRowActionM = UIMethods.insert({&Ctx.Idents.get("NSTableViewRowAction" ), llvm::DenseMap<Selector, uint8_t>()}) .first->second ; |
247 | IdentifierInfo *rowActionWithStyleNSTableViewRowAction[] = { |
248 | &Ctx.Idents.get("rowActionWithStyle"), &Ctx.Idents.get("title"), |
249 | &Ctx.Idents.get("handler")}; |
250 | ADD_METHOD(NSTableViewRowAction, rowActionWithStyleNSTableViewRowAction, 3, 1)NSTableViewRowActionM.insert({Ctx.Selectors.getSelector(3, rowActionWithStyleNSTableViewRowAction ), 1}); |
251 | ADD_UNARY_METHOD(NSTableViewRowAction, setTitle, 0)NSTableViewRowActionM.insert( {Ctx.Selectors.getUnarySelector (&Ctx.Idents.get("setTitle")), 0}); |
252 | |
253 | NEW_RECEIVER(NSImage)llvm::DenseMap<Selector, uint8_t> &NSImageM = UIMethods .insert({&Ctx.Idents.get("NSImage"), llvm::DenseMap<Selector , uint8_t>()}) .first->second; |
254 | ADD_UNARY_METHOD(NSImage, setAccessibilityDescription, 0)NSImageM.insert( {Ctx.Selectors.getUnarySelector(&Ctx.Idents .get("setAccessibilityDescription")), 0}); |
255 | |
256 | NEW_RECEIVER(NSUserActivity)llvm::DenseMap<Selector, uint8_t> &NSUserActivityM = UIMethods.insert({&Ctx.Idents.get("NSUserActivity"), llvm ::DenseMap<Selector, uint8_t>()}) .first->second; |
257 | ADD_UNARY_METHOD(NSUserActivity, setTitle, 0)NSUserActivityM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("setTitle")), 0}); |
258 | |
259 | NEW_RECEIVER(NSPathControlItem)llvm::DenseMap<Selector, uint8_t> &NSPathControlItemM = UIMethods.insert({&Ctx.Idents.get("NSPathControlItem") , llvm::DenseMap<Selector, uint8_t>()}) .first->second ; |
260 | ADD_UNARY_METHOD(NSPathControlItem, setTitle, 0)NSPathControlItemM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("setTitle")), 0}); |
261 | |
262 | NEW_RECEIVER(NSCell)llvm::DenseMap<Selector, uint8_t> &NSCellM = UIMethods .insert({&Ctx.Idents.get("NSCell"), llvm::DenseMap<Selector , uint8_t>()}) .first->second; |
263 | ADD_UNARY_METHOD(NSCell, initTextCell, 0)NSCellM.insert( {Ctx.Selectors.getUnarySelector(&Ctx.Idents .get("initTextCell")), 0}); |
264 | ADD_UNARY_METHOD(NSCell, setTitle, 0)NSCellM.insert( {Ctx.Selectors.getUnarySelector(&Ctx.Idents .get("setTitle")), 0}); |
265 | ADD_UNARY_METHOD(NSCell, setStringValue, 0)NSCellM.insert( {Ctx.Selectors.getUnarySelector(&Ctx.Idents .get("setStringValue")), 0}); |
266 | |
267 | NEW_RECEIVER(NSPathControl)llvm::DenseMap<Selector, uint8_t> &NSPathControlM = UIMethods.insert({&Ctx.Idents.get("NSPathControl"), llvm ::DenseMap<Selector, uint8_t>()}) .first->second; |
268 | ADD_UNARY_METHOD(NSPathControl, setPlaceholderString, 0)NSPathControlM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setPlaceholderString")), 0}); |
269 | |
270 | NEW_RECEIVER(UIAccessibility)llvm::DenseMap<Selector, uint8_t> &UIAccessibilityM = UIMethods.insert({&Ctx.Idents.get("UIAccessibility"), llvm ::DenseMap<Selector, uint8_t>()}) .first->second; |
271 | ADD_UNARY_METHOD(UIAccessibility, setAccessibilityLabel, 0)UIAccessibilityM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("setAccessibilityLabel")), 0}); |
272 | ADD_UNARY_METHOD(UIAccessibility, setAccessibilityHint, 0)UIAccessibilityM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("setAccessibilityHint")), 0}); |
273 | ADD_UNARY_METHOD(UIAccessibility, setAccessibilityValue, 0)UIAccessibilityM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("setAccessibilityValue")), 0}); |
274 | |
275 | NEW_RECEIVER(NSTableColumn)llvm::DenseMap<Selector, uint8_t> &NSTableColumnM = UIMethods.insert({&Ctx.Idents.get("NSTableColumn"), llvm ::DenseMap<Selector, uint8_t>()}) .first->second; |
276 | ADD_UNARY_METHOD(NSTableColumn, setTitle, 0)NSTableColumnM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setTitle")), 0}); |
277 | ADD_UNARY_METHOD(NSTableColumn, setHeaderToolTip, 0)NSTableColumnM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setHeaderToolTip")), 0}); |
278 | |
279 | NEW_RECEIVER(NSSegmentedControl)llvm::DenseMap<Selector, uint8_t> &NSSegmentedControlM = UIMethods.insert({&Ctx.Idents.get("NSSegmentedControl" ), llvm::DenseMap<Selector, uint8_t>()}) .first->second ; |
280 | IdentifierInfo *setLabelNSSegmentedControl[] = { |
281 | &Ctx.Idents.get("setLabel"), &Ctx.Idents.get("forSegment")}; |
282 | ADD_METHOD(NSSegmentedControl, setLabelNSSegmentedControl, 2, 0)NSSegmentedControlM.insert({Ctx.Selectors.getSelector(2, setLabelNSSegmentedControl ), 0}); |
283 | IdentifierInfo *setToolTipNSSegmentedControl[] = { |
284 | &Ctx.Idents.get("setToolTip"), &Ctx.Idents.get("forSegment")}; |
285 | ADD_METHOD(NSSegmentedControl, setToolTipNSSegmentedControl, 2, 0)NSSegmentedControlM.insert({Ctx.Selectors.getSelector(2, setToolTipNSSegmentedControl ), 0}); |
286 | |
287 | NEW_RECEIVER(NSButtonCell)llvm::DenseMap<Selector, uint8_t> &NSButtonCellM = UIMethods .insert({&Ctx.Idents.get("NSButtonCell"), llvm::DenseMap< Selector, uint8_t>()}) .first->second; |
288 | ADD_UNARY_METHOD(NSButtonCell, setTitle, 0)NSButtonCellM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setTitle")), 0}); |
289 | ADD_UNARY_METHOD(NSButtonCell, setAlternateTitle, 0)NSButtonCellM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setAlternateTitle")), 0}); |
290 | |
291 | NEW_RECEIVER(NSDatePickerCell)llvm::DenseMap<Selector, uint8_t> &NSDatePickerCellM = UIMethods.insert({&Ctx.Idents.get("NSDatePickerCell"), llvm::DenseMap<Selector, uint8_t>()}) .first->second ; |
292 | ADD_UNARY_METHOD(NSDatePickerCell, initTextCell, 0)NSDatePickerCellM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("initTextCell")), 0}); |
293 | |
294 | NEW_RECEIVER(NSSliderCell)llvm::DenseMap<Selector, uint8_t> &NSSliderCellM = UIMethods .insert({&Ctx.Idents.get("NSSliderCell"), llvm::DenseMap< Selector, uint8_t>()}) .first->second; |
295 | ADD_UNARY_METHOD(NSSliderCell, setTitle, 0)NSSliderCellM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setTitle")), 0}); |
296 | |
297 | NEW_RECEIVER(NSControl)llvm::DenseMap<Selector, uint8_t> &NSControlM = UIMethods .insert({&Ctx.Idents.get("NSControl"), llvm::DenseMap< Selector, uint8_t>()}) .first->second; |
298 | ADD_UNARY_METHOD(NSControl, setStringValue, 0)NSControlM.insert( {Ctx.Selectors.getUnarySelector(&Ctx.Idents .get("setStringValue")), 0}); |
299 | |
300 | NEW_RECEIVER(NSAccessibility)llvm::DenseMap<Selector, uint8_t> &NSAccessibilityM = UIMethods.insert({&Ctx.Idents.get("NSAccessibility"), llvm ::DenseMap<Selector, uint8_t>()}) .first->second; |
301 | ADD_UNARY_METHOD(NSAccessibility, setAccessibilityValueDescription, 0)NSAccessibilityM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("setAccessibilityValueDescription")), 0}); |
302 | ADD_UNARY_METHOD(NSAccessibility, setAccessibilityLabel, 0)NSAccessibilityM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("setAccessibilityLabel")), 0}); |
303 | ADD_UNARY_METHOD(NSAccessibility, setAccessibilityTitle, 0)NSAccessibilityM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("setAccessibilityTitle")), 0}); |
304 | ADD_UNARY_METHOD(NSAccessibility, setAccessibilityPlaceholderValue, 0)NSAccessibilityM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("setAccessibilityPlaceholderValue")), 0}); |
305 | ADD_UNARY_METHOD(NSAccessibility, setAccessibilityHelp, 0)NSAccessibilityM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("setAccessibilityHelp")), 0}); |
306 | |
307 | NEW_RECEIVER(NSMatrix)llvm::DenseMap<Selector, uint8_t> &NSMatrixM = UIMethods .insert({&Ctx.Idents.get("NSMatrix"), llvm::DenseMap<Selector , uint8_t>()}) .first->second; |
308 | IdentifierInfo *setToolTipNSMatrix[] = {&Ctx.Idents.get("setToolTip"), |
309 | &Ctx.Idents.get("forCell")}; |
310 | ADD_METHOD(NSMatrix, setToolTipNSMatrix, 2, 0)NSMatrixM.insert({Ctx.Selectors.getSelector(2, setToolTipNSMatrix ), 0}); |
311 | |
312 | NEW_RECEIVER(NSPrintPanel)llvm::DenseMap<Selector, uint8_t> &NSPrintPanelM = UIMethods .insert({&Ctx.Idents.get("NSPrintPanel"), llvm::DenseMap< Selector, uint8_t>()}) .first->second; |
313 | ADD_UNARY_METHOD(NSPrintPanel, setDefaultButtonTitle, 0)NSPrintPanelM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setDefaultButtonTitle")), 0}); |
314 | |
315 | NEW_RECEIVER(UILocalNotification)llvm::DenseMap<Selector, uint8_t> &UILocalNotificationM = UIMethods.insert({&Ctx.Idents.get("UILocalNotification" ), llvm::DenseMap<Selector, uint8_t>()}) .first->second ; |
316 | ADD_UNARY_METHOD(UILocalNotification, setAlertBody, 0)UILocalNotificationM.insert( {Ctx.Selectors.getUnarySelector( &Ctx.Idents.get("setAlertBody")), 0}); |
317 | ADD_UNARY_METHOD(UILocalNotification, setAlertAction, 0)UILocalNotificationM.insert( {Ctx.Selectors.getUnarySelector( &Ctx.Idents.get("setAlertAction")), 0}); |
318 | ADD_UNARY_METHOD(UILocalNotification, setAlertTitle, 0)UILocalNotificationM.insert( {Ctx.Selectors.getUnarySelector( &Ctx.Idents.get("setAlertTitle")), 0}); |
319 | |
320 | NEW_RECEIVER(NSSlider)llvm::DenseMap<Selector, uint8_t> &NSSliderM = UIMethods .insert({&Ctx.Idents.get("NSSlider"), llvm::DenseMap<Selector , uint8_t>()}) .first->second; |
321 | ADD_UNARY_METHOD(NSSlider, setTitle, 0)NSSliderM.insert( {Ctx.Selectors.getUnarySelector(&Ctx.Idents .get("setTitle")), 0}); |
322 | |
323 | NEW_RECEIVER(UIMenuItem)llvm::DenseMap<Selector, uint8_t> &UIMenuItemM = UIMethods .insert({&Ctx.Idents.get("UIMenuItem"), llvm::DenseMap< Selector, uint8_t>()}) .first->second; |
324 | IdentifierInfo *initWithTitleUIMenuItem[] = {&Ctx.Idents.get("initWithTitle"), |
325 | &Ctx.Idents.get("action")}; |
326 | ADD_METHOD(UIMenuItem, initWithTitleUIMenuItem, 2, 0)UIMenuItemM.insert({Ctx.Selectors.getSelector(2, initWithTitleUIMenuItem ), 0}); |
327 | ADD_UNARY_METHOD(UIMenuItem, setTitle, 0)UIMenuItemM.insert( {Ctx.Selectors.getUnarySelector(&Ctx. Idents.get("setTitle")), 0}); |
328 | |
329 | NEW_RECEIVER(UIAlertController)llvm::DenseMap<Selector, uint8_t> &UIAlertControllerM = UIMethods.insert({&Ctx.Idents.get("UIAlertController") , llvm::DenseMap<Selector, uint8_t>()}) .first->second ; |
330 | IdentifierInfo *alertControllerWithTitleUIAlertController[] = { |
331 | &Ctx.Idents.get("alertControllerWithTitle"), &Ctx.Idents.get("message"), |
332 | &Ctx.Idents.get("preferredStyle")}; |
333 | ADD_METHOD(UIAlertController, alertControllerWithTitleUIAlertController, 3, 1)UIAlertControllerM.insert({Ctx.Selectors.getSelector(3, alertControllerWithTitleUIAlertController ), 1}); |
334 | ADD_UNARY_METHOD(UIAlertController, setTitle, 0)UIAlertControllerM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("setTitle")), 0}); |
335 | ADD_UNARY_METHOD(UIAlertController, setMessage, 0)UIAlertControllerM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("setMessage")), 0}); |
336 | |
337 | NEW_RECEIVER(UIApplicationShortcutItem)llvm::DenseMap<Selector, uint8_t> &UIApplicationShortcutItemM = UIMethods.insert({&Ctx.Idents.get("UIApplicationShortcutItem" ), llvm::DenseMap<Selector, uint8_t>()}) .first->second ; |
338 | IdentifierInfo *initWithTypeUIApplicationShortcutItemIcon[] = { |
339 | &Ctx.Idents.get("initWithType"), &Ctx.Idents.get("localizedTitle"), |
340 | &Ctx.Idents.get("localizedSubtitle"), &Ctx.Idents.get("icon"), |
341 | &Ctx.Idents.get("userInfo")}; |
342 | ADD_METHOD(UIApplicationShortcutItem,UIApplicationShortcutItemM.insert({Ctx.Selectors.getSelector( 5, initWithTypeUIApplicationShortcutItemIcon), 1}); |
343 | initWithTypeUIApplicationShortcutItemIcon, 5, 1)UIApplicationShortcutItemM.insert({Ctx.Selectors.getSelector( 5, initWithTypeUIApplicationShortcutItemIcon), 1}); |
344 | IdentifierInfo *initWithTypeUIApplicationShortcutItem[] = { |
345 | &Ctx.Idents.get("initWithType"), &Ctx.Idents.get("localizedTitle")}; |
346 | ADD_METHOD(UIApplicationShortcutItem, initWithTypeUIApplicationShortcutItem,UIApplicationShortcutItemM.insert({Ctx.Selectors.getSelector( 2, initWithTypeUIApplicationShortcutItem), 1}); |
347 | 2, 1)UIApplicationShortcutItemM.insert({Ctx.Selectors.getSelector( 2, initWithTypeUIApplicationShortcutItem), 1}); |
348 | |
349 | NEW_RECEIVER(UIActionSheet)llvm::DenseMap<Selector, uint8_t> &UIActionSheetM = UIMethods.insert({&Ctx.Idents.get("UIActionSheet"), llvm ::DenseMap<Selector, uint8_t>()}) .first->second; |
350 | IdentifierInfo *initWithTitleUIActionSheet[] = { |
351 | &Ctx.Idents.get("initWithTitle"), &Ctx.Idents.get("delegate"), |
352 | &Ctx.Idents.get("cancelButtonTitle"), |
353 | &Ctx.Idents.get("destructiveButtonTitle"), |
354 | &Ctx.Idents.get("otherButtonTitles")}; |
355 | ADD_METHOD(UIActionSheet, initWithTitleUIActionSheet, 5, 0)UIActionSheetM.insert({Ctx.Selectors.getSelector(5, initWithTitleUIActionSheet ), 0}); |
356 | ADD_UNARY_METHOD(UIActionSheet, addButtonWithTitle, 0)UIActionSheetM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("addButtonWithTitle")), 0}); |
357 | ADD_UNARY_METHOD(UIActionSheet, setTitle, 0)UIActionSheetM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setTitle")), 0}); |
358 | |
359 | NEW_RECEIVER(UIAccessibilityCustomAction)llvm::DenseMap<Selector, uint8_t> &UIAccessibilityCustomActionM = UIMethods.insert({&Ctx.Idents.get("UIAccessibilityCustomAction" ), llvm::DenseMap<Selector, uint8_t>()}) .first->second ; |
360 | IdentifierInfo *initWithNameUIAccessibilityCustomAction[] = { |
361 | &Ctx.Idents.get("initWithName"), &Ctx.Idents.get("target"), |
362 | &Ctx.Idents.get("selector")}; |
363 | ADD_METHOD(UIAccessibilityCustomAction,UIAccessibilityCustomActionM.insert({Ctx.Selectors.getSelector (3, initWithNameUIAccessibilityCustomAction), 0}); |
364 | initWithNameUIAccessibilityCustomAction, 3, 0)UIAccessibilityCustomActionM.insert({Ctx.Selectors.getSelector (3, initWithNameUIAccessibilityCustomAction), 0}); |
365 | ADD_UNARY_METHOD(UIAccessibilityCustomAction, setName, 0)UIAccessibilityCustomActionM.insert( {Ctx.Selectors.getUnarySelector (&Ctx.Idents.get("setName")), 0}); |
366 | |
367 | NEW_RECEIVER(UISearchBar)llvm::DenseMap<Selector, uint8_t> &UISearchBarM = UIMethods .insert({&Ctx.Idents.get("UISearchBar"), llvm::DenseMap< Selector, uint8_t>()}) .first->second; |
368 | ADD_UNARY_METHOD(UISearchBar, setText, 0)UISearchBarM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setText")), 0}); |
369 | ADD_UNARY_METHOD(UISearchBar, setPrompt, 0)UISearchBarM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setPrompt")), 0}); |
370 | ADD_UNARY_METHOD(UISearchBar, setPlaceholder, 0)UISearchBarM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setPlaceholder")), 0}); |
371 | |
372 | NEW_RECEIVER(UIBarItem)llvm::DenseMap<Selector, uint8_t> &UIBarItemM = UIMethods .insert({&Ctx.Idents.get("UIBarItem"), llvm::DenseMap< Selector, uint8_t>()}) .first->second; |
373 | ADD_UNARY_METHOD(UIBarItem, setTitle, 0)UIBarItemM.insert( {Ctx.Selectors.getUnarySelector(&Ctx.Idents .get("setTitle")), 0}); |
374 | |
375 | NEW_RECEIVER(UITextView)llvm::DenseMap<Selector, uint8_t> &UITextViewM = UIMethods .insert({&Ctx.Idents.get("UITextView"), llvm::DenseMap< Selector, uint8_t>()}) .first->second; |
376 | ADD_UNARY_METHOD(UITextView, setText, 0)UITextViewM.insert( {Ctx.Selectors.getUnarySelector(&Ctx. Idents.get("setText")), 0}); |
377 | |
378 | NEW_RECEIVER(NSView)llvm::DenseMap<Selector, uint8_t> &NSViewM = UIMethods .insert({&Ctx.Idents.get("NSView"), llvm::DenseMap<Selector , uint8_t>()}) .first->second; |
379 | ADD_UNARY_METHOD(NSView, setToolTip, 0)NSViewM.insert( {Ctx.Selectors.getUnarySelector(&Ctx.Idents .get("setToolTip")), 0}); |
380 | |
381 | NEW_RECEIVER(NSTextField)llvm::DenseMap<Selector, uint8_t> &NSTextFieldM = UIMethods .insert({&Ctx.Idents.get("NSTextField"), llvm::DenseMap< Selector, uint8_t>()}) .first->second; |
382 | ADD_UNARY_METHOD(NSTextField, setPlaceholderString, 0)NSTextFieldM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setPlaceholderString")), 0}); |
383 | ADD_UNARY_METHOD(NSTextField, textFieldWithString, 0)NSTextFieldM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("textFieldWithString")), 0}); |
384 | ADD_UNARY_METHOD(NSTextField, wrappingLabelWithString, 0)NSTextFieldM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("wrappingLabelWithString")), 0}); |
385 | ADD_UNARY_METHOD(NSTextField, labelWithString, 0)NSTextFieldM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("labelWithString")), 0}); |
386 | |
387 | NEW_RECEIVER(NSAttributedString)llvm::DenseMap<Selector, uint8_t> &NSAttributedStringM = UIMethods.insert({&Ctx.Idents.get("NSAttributedString" ), llvm::DenseMap<Selector, uint8_t>()}) .first->second ; |
388 | ADD_UNARY_METHOD(NSAttributedString, initWithString, 0)NSAttributedStringM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("initWithString")), 0}); |
389 | IdentifierInfo *initWithStringNSAttributedString[] = { |
390 | &Ctx.Idents.get("initWithString"), &Ctx.Idents.get("attributes")}; |
391 | ADD_METHOD(NSAttributedString, initWithStringNSAttributedString, 2, 0)NSAttributedStringM.insert({Ctx.Selectors.getSelector(2, initWithStringNSAttributedString ), 0}); |
392 | |
393 | NEW_RECEIVER(NSText)llvm::DenseMap<Selector, uint8_t> &NSTextM = UIMethods .insert({&Ctx.Idents.get("NSText"), llvm::DenseMap<Selector , uint8_t>()}) .first->second; |
394 | ADD_UNARY_METHOD(NSText, setString, 0)NSTextM.insert( {Ctx.Selectors.getUnarySelector(&Ctx.Idents .get("setString")), 0}); |
395 | |
396 | NEW_RECEIVER(UIKeyCommand)llvm::DenseMap<Selector, uint8_t> &UIKeyCommandM = UIMethods .insert({&Ctx.Idents.get("UIKeyCommand"), llvm::DenseMap< Selector, uint8_t>()}) .first->second; |
397 | IdentifierInfo *keyCommandWithInputUIKeyCommand[] = { |
398 | &Ctx.Idents.get("keyCommandWithInput"), &Ctx.Idents.get("modifierFlags"), |
399 | &Ctx.Idents.get("action"), &Ctx.Idents.get("discoverabilityTitle")}; |
400 | ADD_METHOD(UIKeyCommand, keyCommandWithInputUIKeyCommand, 4, 3)UIKeyCommandM.insert({Ctx.Selectors.getSelector(4, keyCommandWithInputUIKeyCommand ), 3}); |
401 | ADD_UNARY_METHOD(UIKeyCommand, setDiscoverabilityTitle, 0)UIKeyCommandM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setDiscoverabilityTitle")), 0}); |
402 | |
403 | NEW_RECEIVER(UILabel)llvm::DenseMap<Selector, uint8_t> &UILabelM = UIMethods .insert({&Ctx.Idents.get("UILabel"), llvm::DenseMap<Selector , uint8_t>()}) .first->second; |
404 | ADD_UNARY_METHOD(UILabel, setText, 0)UILabelM.insert( {Ctx.Selectors.getUnarySelector(&Ctx.Idents .get("setText")), 0}); |
405 | |
406 | NEW_RECEIVER(NSAlert)llvm::DenseMap<Selector, uint8_t> &NSAlertM = UIMethods .insert({&Ctx.Idents.get("NSAlert"), llvm::DenseMap<Selector , uint8_t>()}) .first->second; |
407 | IdentifierInfo *alertWithMessageTextNSAlert[] = { |
408 | &Ctx.Idents.get("alertWithMessageText"), &Ctx.Idents.get("defaultButton"), |
409 | &Ctx.Idents.get("alternateButton"), &Ctx.Idents.get("otherButton"), |
410 | &Ctx.Idents.get("informativeTextWithFormat")}; |
411 | ADD_METHOD(NSAlert, alertWithMessageTextNSAlert, 5, 0)NSAlertM.insert({Ctx.Selectors.getSelector(5, alertWithMessageTextNSAlert ), 0}); |
412 | ADD_UNARY_METHOD(NSAlert, addButtonWithTitle, 0)NSAlertM.insert( {Ctx.Selectors.getUnarySelector(&Ctx.Idents .get("addButtonWithTitle")), 0}); |
413 | ADD_UNARY_METHOD(NSAlert, setMessageText, 0)NSAlertM.insert( {Ctx.Selectors.getUnarySelector(&Ctx.Idents .get("setMessageText")), 0}); |
414 | ADD_UNARY_METHOD(NSAlert, setInformativeText, 0)NSAlertM.insert( {Ctx.Selectors.getUnarySelector(&Ctx.Idents .get("setInformativeText")), 0}); |
415 | ADD_UNARY_METHOD(NSAlert, setHelpAnchor, 0)NSAlertM.insert( {Ctx.Selectors.getUnarySelector(&Ctx.Idents .get("setHelpAnchor")), 0}); |
416 | |
417 | NEW_RECEIVER(UIMutableApplicationShortcutItem)llvm::DenseMap<Selector, uint8_t> &UIMutableApplicationShortcutItemM = UIMethods.insert({&Ctx.Idents.get("UIMutableApplicationShortcutItem" ), llvm::DenseMap<Selector, uint8_t>()}) .first->second ; |
418 | ADD_UNARY_METHOD(UIMutableApplicationShortcutItem, setLocalizedTitle, 0)UIMutableApplicationShortcutItemM.insert( {Ctx.Selectors.getUnarySelector (&Ctx.Idents.get("setLocalizedTitle")), 0}); |
419 | ADD_UNARY_METHOD(UIMutableApplicationShortcutItem, setLocalizedSubtitle, 0)UIMutableApplicationShortcutItemM.insert( {Ctx.Selectors.getUnarySelector (&Ctx.Idents.get("setLocalizedSubtitle")), 0}); |
420 | |
421 | NEW_RECEIVER(UIButton)llvm::DenseMap<Selector, uint8_t> &UIButtonM = UIMethods .insert({&Ctx.Idents.get("UIButton"), llvm::DenseMap<Selector , uint8_t>()}) .first->second; |
422 | IdentifierInfo *setTitleUIButton[] = {&Ctx.Idents.get("setTitle"), |
423 | &Ctx.Idents.get("forState")}; |
424 | ADD_METHOD(UIButton, setTitleUIButton, 2, 0)UIButtonM.insert({Ctx.Selectors.getSelector(2, setTitleUIButton ), 0}); |
425 | |
426 | NEW_RECEIVER(NSWindow)llvm::DenseMap<Selector, uint8_t> &NSWindowM = UIMethods .insert({&Ctx.Idents.get("NSWindow"), llvm::DenseMap<Selector , uint8_t>()}) .first->second; |
427 | ADD_UNARY_METHOD(NSWindow, setTitle, 0)NSWindowM.insert( {Ctx.Selectors.getUnarySelector(&Ctx.Idents .get("setTitle")), 0}); |
428 | IdentifierInfo *minFrameWidthWithTitleNSWindow[] = { |
429 | &Ctx.Idents.get("minFrameWidthWithTitle"), &Ctx.Idents.get("styleMask")}; |
430 | ADD_METHOD(NSWindow, minFrameWidthWithTitleNSWindow, 2, 0)NSWindowM.insert({Ctx.Selectors.getSelector(2, minFrameWidthWithTitleNSWindow ), 0}); |
431 | ADD_UNARY_METHOD(NSWindow, setMiniwindowTitle, 0)NSWindowM.insert( {Ctx.Selectors.getUnarySelector(&Ctx.Idents .get("setMiniwindowTitle")), 0}); |
432 | |
433 | NEW_RECEIVER(NSPathCell)llvm::DenseMap<Selector, uint8_t> &NSPathCellM = UIMethods .insert({&Ctx.Idents.get("NSPathCell"), llvm::DenseMap< Selector, uint8_t>()}) .first->second; |
434 | ADD_UNARY_METHOD(NSPathCell, setPlaceholderString, 0)NSPathCellM.insert( {Ctx.Selectors.getUnarySelector(&Ctx. Idents.get("setPlaceholderString")), 0}); |
435 | |
436 | NEW_RECEIVER(UIDocumentMenuViewController)llvm::DenseMap<Selector, uint8_t> &UIDocumentMenuViewControllerM = UIMethods.insert({&Ctx.Idents.get("UIDocumentMenuViewController" ), llvm::DenseMap<Selector, uint8_t>()}) .first->second ; |
437 | IdentifierInfo *addOptionWithTitleUIDocumentMenuViewController[] = { |
438 | &Ctx.Idents.get("addOptionWithTitle"), &Ctx.Idents.get("image"), |
439 | &Ctx.Idents.get("order"), &Ctx.Idents.get("handler")}; |
440 | ADD_METHOD(UIDocumentMenuViewController,UIDocumentMenuViewControllerM.insert({Ctx.Selectors.getSelector (4, addOptionWithTitleUIDocumentMenuViewController), 0}); |
441 | addOptionWithTitleUIDocumentMenuViewController, 4, 0)UIDocumentMenuViewControllerM.insert({Ctx.Selectors.getSelector (4, addOptionWithTitleUIDocumentMenuViewController), 0}); |
442 | |
443 | NEW_RECEIVER(UINavigationItem)llvm::DenseMap<Selector, uint8_t> &UINavigationItemM = UIMethods.insert({&Ctx.Idents.get("UINavigationItem"), llvm::DenseMap<Selector, uint8_t>()}) .first->second ; |
444 | ADD_UNARY_METHOD(UINavigationItem, initWithTitle, 0)UINavigationItemM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("initWithTitle")), 0}); |
445 | ADD_UNARY_METHOD(UINavigationItem, setTitle, 0)UINavigationItemM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("setTitle")), 0}); |
446 | ADD_UNARY_METHOD(UINavigationItem, setPrompt, 0)UINavigationItemM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("setPrompt")), 0}); |
447 | |
448 | NEW_RECEIVER(UIAlertView)llvm::DenseMap<Selector, uint8_t> &UIAlertViewM = UIMethods .insert({&Ctx.Idents.get("UIAlertView"), llvm::DenseMap< Selector, uint8_t>()}) .first->second; |
449 | IdentifierInfo *initWithTitleUIAlertView[] = { |
450 | &Ctx.Idents.get("initWithTitle"), &Ctx.Idents.get("message"), |
451 | &Ctx.Idents.get("delegate"), &Ctx.Idents.get("cancelButtonTitle"), |
452 | &Ctx.Idents.get("otherButtonTitles")}; |
453 | ADD_METHOD(UIAlertView, initWithTitleUIAlertView, 5, 0)UIAlertViewM.insert({Ctx.Selectors.getSelector(5, initWithTitleUIAlertView ), 0}); |
454 | ADD_UNARY_METHOD(UIAlertView, addButtonWithTitle, 0)UIAlertViewM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("addButtonWithTitle")), 0}); |
455 | ADD_UNARY_METHOD(UIAlertView, setTitle, 0)UIAlertViewM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setTitle")), 0}); |
456 | ADD_UNARY_METHOD(UIAlertView, setMessage, 0)UIAlertViewM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setMessage")), 0}); |
457 | |
458 | NEW_RECEIVER(NSFormCell)llvm::DenseMap<Selector, uint8_t> &NSFormCellM = UIMethods .insert({&Ctx.Idents.get("NSFormCell"), llvm::DenseMap< Selector, uint8_t>()}) .first->second; |
459 | ADD_UNARY_METHOD(NSFormCell, initTextCell, 0)NSFormCellM.insert( {Ctx.Selectors.getUnarySelector(&Ctx. Idents.get("initTextCell")), 0}); |
460 | ADD_UNARY_METHOD(NSFormCell, setTitle, 0)NSFormCellM.insert( {Ctx.Selectors.getUnarySelector(&Ctx. Idents.get("setTitle")), 0}); |
461 | ADD_UNARY_METHOD(NSFormCell, setPlaceholderString, 0)NSFormCellM.insert( {Ctx.Selectors.getUnarySelector(&Ctx. Idents.get("setPlaceholderString")), 0}); |
462 | |
463 | NEW_RECEIVER(NSUserNotification)llvm::DenseMap<Selector, uint8_t> &NSUserNotificationM = UIMethods.insert({&Ctx.Idents.get("NSUserNotification" ), llvm::DenseMap<Selector, uint8_t>()}) .first->second ; |
464 | ADD_UNARY_METHOD(NSUserNotification, setTitle, 0)NSUserNotificationM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("setTitle")), 0}); |
465 | ADD_UNARY_METHOD(NSUserNotification, setSubtitle, 0)NSUserNotificationM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("setSubtitle")), 0}); |
466 | ADD_UNARY_METHOD(NSUserNotification, setInformativeText, 0)NSUserNotificationM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("setInformativeText")), 0}); |
467 | ADD_UNARY_METHOD(NSUserNotification, setActionButtonTitle, 0)NSUserNotificationM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("setActionButtonTitle")), 0}); |
468 | ADD_UNARY_METHOD(NSUserNotification, setOtherButtonTitle, 0)NSUserNotificationM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("setOtherButtonTitle")), 0}); |
469 | ADD_UNARY_METHOD(NSUserNotification, setResponsePlaceholder, 0)NSUserNotificationM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("setResponsePlaceholder")), 0}); |
470 | |
471 | NEW_RECEIVER(NSToolbarItem)llvm::DenseMap<Selector, uint8_t> &NSToolbarItemM = UIMethods.insert({&Ctx.Idents.get("NSToolbarItem"), llvm ::DenseMap<Selector, uint8_t>()}) .first->second; |
472 | ADD_UNARY_METHOD(NSToolbarItem, setLabel, 0)NSToolbarItemM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setLabel")), 0}); |
473 | ADD_UNARY_METHOD(NSToolbarItem, setPaletteLabel, 0)NSToolbarItemM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setPaletteLabel")), 0}); |
474 | ADD_UNARY_METHOD(NSToolbarItem, setToolTip, 0)NSToolbarItemM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setToolTip")), 0}); |
475 | |
476 | NEW_RECEIVER(NSProgress)llvm::DenseMap<Selector, uint8_t> &NSProgressM = UIMethods .insert({&Ctx.Idents.get("NSProgress"), llvm::DenseMap< Selector, uint8_t>()}) .first->second; |
477 | ADD_UNARY_METHOD(NSProgress, setLocalizedDescription, 0)NSProgressM.insert( {Ctx.Selectors.getUnarySelector(&Ctx. Idents.get("setLocalizedDescription")), 0}); |
478 | ADD_UNARY_METHOD(NSProgress, setLocalizedAdditionalDescription, 0)NSProgressM.insert( {Ctx.Selectors.getUnarySelector(&Ctx. Idents.get("setLocalizedAdditionalDescription")), 0}); |
479 | |
480 | NEW_RECEIVER(NSSegmentedCell)llvm::DenseMap<Selector, uint8_t> &NSSegmentedCellM = UIMethods.insert({&Ctx.Idents.get("NSSegmentedCell"), llvm ::DenseMap<Selector, uint8_t>()}) .first->second; |
481 | IdentifierInfo *setLabelNSSegmentedCell[] = {&Ctx.Idents.get("setLabel"), |
482 | &Ctx.Idents.get("forSegment")}; |
483 | ADD_METHOD(NSSegmentedCell, setLabelNSSegmentedCell, 2, 0)NSSegmentedCellM.insert({Ctx.Selectors.getSelector(2, setLabelNSSegmentedCell ), 0}); |
484 | IdentifierInfo *setToolTipNSSegmentedCell[] = {&Ctx.Idents.get("setToolTip"), |
485 | &Ctx.Idents.get("forSegment")}; |
486 | ADD_METHOD(NSSegmentedCell, setToolTipNSSegmentedCell, 2, 0)NSSegmentedCellM.insert({Ctx.Selectors.getSelector(2, setToolTipNSSegmentedCell ), 0}); |
487 | |
488 | NEW_RECEIVER(NSUndoManager)llvm::DenseMap<Selector, uint8_t> &NSUndoManagerM = UIMethods.insert({&Ctx.Idents.get("NSUndoManager"), llvm ::DenseMap<Selector, uint8_t>()}) .first->second; |
489 | ADD_UNARY_METHOD(NSUndoManager, setActionName, 0)NSUndoManagerM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setActionName")), 0}); |
490 | ADD_UNARY_METHOD(NSUndoManager, undoMenuTitleForUndoActionName, 0)NSUndoManagerM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("undoMenuTitleForUndoActionName")), 0}); |
491 | ADD_UNARY_METHOD(NSUndoManager, redoMenuTitleForUndoActionName, 0)NSUndoManagerM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("redoMenuTitleForUndoActionName")), 0}); |
492 | |
493 | NEW_RECEIVER(NSMenuItem)llvm::DenseMap<Selector, uint8_t> &NSMenuItemM = UIMethods .insert({&Ctx.Idents.get("NSMenuItem"), llvm::DenseMap< Selector, uint8_t>()}) .first->second; |
494 | IdentifierInfo *initWithTitleNSMenuItem[] = { |
495 | &Ctx.Idents.get("initWithTitle"), &Ctx.Idents.get("action"), |
496 | &Ctx.Idents.get("keyEquivalent")}; |
497 | ADD_METHOD(NSMenuItem, initWithTitleNSMenuItem, 3, 0)NSMenuItemM.insert({Ctx.Selectors.getSelector(3, initWithTitleNSMenuItem ), 0}); |
498 | ADD_UNARY_METHOD(NSMenuItem, setTitle, 0)NSMenuItemM.insert( {Ctx.Selectors.getUnarySelector(&Ctx. Idents.get("setTitle")), 0}); |
499 | ADD_UNARY_METHOD(NSMenuItem, setToolTip, 0)NSMenuItemM.insert( {Ctx.Selectors.getUnarySelector(&Ctx. Idents.get("setToolTip")), 0}); |
500 | |
501 | NEW_RECEIVER(NSPopUpButtonCell)llvm::DenseMap<Selector, uint8_t> &NSPopUpButtonCellM = UIMethods.insert({&Ctx.Idents.get("NSPopUpButtonCell") , llvm::DenseMap<Selector, uint8_t>()}) .first->second ; |
502 | IdentifierInfo *initTextCellNSPopUpButtonCell[] = { |
503 | &Ctx.Idents.get("initTextCell"), &Ctx.Idents.get("pullsDown")}; |
504 | ADD_METHOD(NSPopUpButtonCell, initTextCellNSPopUpButtonCell, 2, 0)NSPopUpButtonCellM.insert({Ctx.Selectors.getSelector(2, initTextCellNSPopUpButtonCell ), 0}); |
505 | ADD_UNARY_METHOD(NSPopUpButtonCell, addItemWithTitle, 0)NSPopUpButtonCellM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("addItemWithTitle")), 0}); |
506 | IdentifierInfo *insertItemWithTitleNSPopUpButtonCell[] = { |
507 | &Ctx.Idents.get("insertItemWithTitle"), &Ctx.Idents.get("atIndex")}; |
508 | ADD_METHOD(NSPopUpButtonCell, insertItemWithTitleNSPopUpButtonCell, 2, 0)NSPopUpButtonCellM.insert({Ctx.Selectors.getSelector(2, insertItemWithTitleNSPopUpButtonCell ), 0}); |
509 | ADD_UNARY_METHOD(NSPopUpButtonCell, removeItemWithTitle, 0)NSPopUpButtonCellM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("removeItemWithTitle")), 0}); |
510 | ADD_UNARY_METHOD(NSPopUpButtonCell, selectItemWithTitle, 0)NSPopUpButtonCellM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("selectItemWithTitle")), 0}); |
511 | ADD_UNARY_METHOD(NSPopUpButtonCell, setTitle, 0)NSPopUpButtonCellM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("setTitle")), 0}); |
512 | |
513 | NEW_RECEIVER(NSViewController)llvm::DenseMap<Selector, uint8_t> &NSViewControllerM = UIMethods.insert({&Ctx.Idents.get("NSViewController"), llvm::DenseMap<Selector, uint8_t>()}) .first->second ; |
514 | ADD_UNARY_METHOD(NSViewController, setTitle, 0)NSViewControllerM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("setTitle")), 0}); |
515 | |
516 | NEW_RECEIVER(NSMenu)llvm::DenseMap<Selector, uint8_t> &NSMenuM = UIMethods .insert({&Ctx.Idents.get("NSMenu"), llvm::DenseMap<Selector , uint8_t>()}) .first->second; |
517 | ADD_UNARY_METHOD(NSMenu, initWithTitle, 0)NSMenuM.insert( {Ctx.Selectors.getUnarySelector(&Ctx.Idents .get("initWithTitle")), 0}); |
518 | IdentifierInfo *insertItemWithTitleNSMenu[] = { |
519 | &Ctx.Idents.get("insertItemWithTitle"), &Ctx.Idents.get("action"), |
520 | &Ctx.Idents.get("keyEquivalent"), &Ctx.Idents.get("atIndex")}; |
521 | ADD_METHOD(NSMenu, insertItemWithTitleNSMenu, 4, 0)NSMenuM.insert({Ctx.Selectors.getSelector(4, insertItemWithTitleNSMenu ), 0}); |
522 | IdentifierInfo *addItemWithTitleNSMenu[] = { |
523 | &Ctx.Idents.get("addItemWithTitle"), &Ctx.Idents.get("action"), |
524 | &Ctx.Idents.get("keyEquivalent")}; |
525 | ADD_METHOD(NSMenu, addItemWithTitleNSMenu, 3, 0)NSMenuM.insert({Ctx.Selectors.getSelector(3, addItemWithTitleNSMenu ), 0}); |
526 | ADD_UNARY_METHOD(NSMenu, setTitle, 0)NSMenuM.insert( {Ctx.Selectors.getUnarySelector(&Ctx.Idents .get("setTitle")), 0}); |
527 | |
528 | NEW_RECEIVER(UIMutableUserNotificationAction)llvm::DenseMap<Selector, uint8_t> &UIMutableUserNotificationActionM = UIMethods.insert({&Ctx.Idents.get("UIMutableUserNotificationAction" ), llvm::DenseMap<Selector, uint8_t>()}) .first->second ; |
529 | ADD_UNARY_METHOD(UIMutableUserNotificationAction, setTitle, 0)UIMutableUserNotificationActionM.insert( {Ctx.Selectors.getUnarySelector (&Ctx.Idents.get("setTitle")), 0}); |
530 | |
531 | NEW_RECEIVER(NSForm)llvm::DenseMap<Selector, uint8_t> &NSFormM = UIMethods .insert({&Ctx.Idents.get("NSForm"), llvm::DenseMap<Selector , uint8_t>()}) .first->second; |
532 | ADD_UNARY_METHOD(NSForm, addEntry, 0)NSFormM.insert( {Ctx.Selectors.getUnarySelector(&Ctx.Idents .get("addEntry")), 0}); |
533 | IdentifierInfo *insertEntryNSForm[] = {&Ctx.Idents.get("insertEntry"), |
534 | &Ctx.Idents.get("atIndex")}; |
535 | ADD_METHOD(NSForm, insertEntryNSForm, 2, 0)NSFormM.insert({Ctx.Selectors.getSelector(2, insertEntryNSForm ), 0}); |
536 | |
537 | NEW_RECEIVER(NSTextFieldCell)llvm::DenseMap<Selector, uint8_t> &NSTextFieldCellM = UIMethods.insert({&Ctx.Idents.get("NSTextFieldCell"), llvm ::DenseMap<Selector, uint8_t>()}) .first->second; |
538 | ADD_UNARY_METHOD(NSTextFieldCell, setPlaceholderString, 0)NSTextFieldCellM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("setPlaceholderString")), 0}); |
539 | |
540 | NEW_RECEIVER(NSUserNotificationAction)llvm::DenseMap<Selector, uint8_t> &NSUserNotificationActionM = UIMethods.insert({&Ctx.Idents.get("NSUserNotificationAction" ), llvm::DenseMap<Selector, uint8_t>()}) .first->second ; |
541 | IdentifierInfo *actionWithIdentifierNSUserNotificationAction[] = { |
542 | &Ctx.Idents.get("actionWithIdentifier"), &Ctx.Idents.get("title")}; |
543 | ADD_METHOD(NSUserNotificationAction,NSUserNotificationActionM.insert({Ctx.Selectors.getSelector(2 , actionWithIdentifierNSUserNotificationAction), 1}); |
544 | actionWithIdentifierNSUserNotificationAction, 2, 1)NSUserNotificationActionM.insert({Ctx.Selectors.getSelector(2 , actionWithIdentifierNSUserNotificationAction), 1}); |
545 | |
546 | NEW_RECEIVER(UITextField)llvm::DenseMap<Selector, uint8_t> &UITextFieldM = UIMethods .insert({&Ctx.Idents.get("UITextField"), llvm::DenseMap< Selector, uint8_t>()}) .first->second; |
547 | ADD_UNARY_METHOD(UITextField, setText, 0)UITextFieldM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setText")), 0}); |
548 | ADD_UNARY_METHOD(UITextField, setPlaceholder, 0)UITextFieldM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setPlaceholder")), 0}); |
549 | |
550 | NEW_RECEIVER(UIBarButtonItem)llvm::DenseMap<Selector, uint8_t> &UIBarButtonItemM = UIMethods.insert({&Ctx.Idents.get("UIBarButtonItem"), llvm ::DenseMap<Selector, uint8_t>()}) .first->second; |
551 | IdentifierInfo *initWithTitleUIBarButtonItem[] = { |
552 | &Ctx.Idents.get("initWithTitle"), &Ctx.Idents.get("style"), |
553 | &Ctx.Idents.get("target"), &Ctx.Idents.get("action")}; |
554 | ADD_METHOD(UIBarButtonItem, initWithTitleUIBarButtonItem, 4, 0)UIBarButtonItemM.insert({Ctx.Selectors.getSelector(4, initWithTitleUIBarButtonItem ), 0}); |
555 | |
556 | NEW_RECEIVER(UIViewController)llvm::DenseMap<Selector, uint8_t> &UIViewControllerM = UIMethods.insert({&Ctx.Idents.get("UIViewController"), llvm::DenseMap<Selector, uint8_t>()}) .first->second ; |
557 | ADD_UNARY_METHOD(UIViewController, setTitle, 0)UIViewControllerM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("setTitle")), 0}); |
558 | |
559 | NEW_RECEIVER(UISegmentedControl)llvm::DenseMap<Selector, uint8_t> &UISegmentedControlM = UIMethods.insert({&Ctx.Idents.get("UISegmentedControl" ), llvm::DenseMap<Selector, uint8_t>()}) .first->second ; |
560 | IdentifierInfo *insertSegmentWithTitleUISegmentedControl[] = { |
561 | &Ctx.Idents.get("insertSegmentWithTitle"), &Ctx.Idents.get("atIndex"), |
562 | &Ctx.Idents.get("animated")}; |
563 | ADD_METHOD(UISegmentedControl, insertSegmentWithTitleUISegmentedControl, 3, 0)UISegmentedControlM.insert({Ctx.Selectors.getSelector(3, insertSegmentWithTitleUISegmentedControl ), 0}); |
564 | IdentifierInfo *setTitleUISegmentedControl[] = { |
565 | &Ctx.Idents.get("setTitle"), &Ctx.Idents.get("forSegmentAtIndex")}; |
566 | ADD_METHOD(UISegmentedControl, setTitleUISegmentedControl, 2, 0)UISegmentedControlM.insert({Ctx.Selectors.getSelector(2, setTitleUISegmentedControl ), 0}); |
567 | |
568 | NEW_RECEIVER(NSAccessibilityCustomRotorItemResult)llvm::DenseMap<Selector, uint8_t> &NSAccessibilityCustomRotorItemResultM = UIMethods.insert({&Ctx.Idents.get("NSAccessibilityCustomRotorItemResult" ), llvm::DenseMap<Selector, uint8_t>()}) .first->second ; |
569 | IdentifierInfo |
570 | *initWithItemLoadingTokenNSAccessibilityCustomRotorItemResult[] = { |
571 | &Ctx.Idents.get("initWithItemLoadingToken"), |
572 | &Ctx.Idents.get("customLabel")}; |
573 | ADD_METHOD(NSAccessibilityCustomRotorItemResult,NSAccessibilityCustomRotorItemResultM.insert({Ctx.Selectors.getSelector (2, initWithItemLoadingTokenNSAccessibilityCustomRotorItemResult ), 1}); |
574 | initWithItemLoadingTokenNSAccessibilityCustomRotorItemResult, 2, 1)NSAccessibilityCustomRotorItemResultM.insert({Ctx.Selectors.getSelector (2, initWithItemLoadingTokenNSAccessibilityCustomRotorItemResult ), 1}); |
575 | ADD_UNARY_METHOD(NSAccessibilityCustomRotorItemResult, setCustomLabel, 0)NSAccessibilityCustomRotorItemResultM.insert( {Ctx.Selectors. getUnarySelector(&Ctx.Idents.get("setCustomLabel")), 0}); |
576 | |
577 | NEW_RECEIVER(UIContextualAction)llvm::DenseMap<Selector, uint8_t> &UIContextualActionM = UIMethods.insert({&Ctx.Idents.get("UIContextualAction" ), llvm::DenseMap<Selector, uint8_t>()}) .first->second ; |
578 | IdentifierInfo *contextualActionWithStyleUIContextualAction[] = { |
579 | &Ctx.Idents.get("contextualActionWithStyle"), &Ctx.Idents.get("title"), |
580 | &Ctx.Idents.get("handler")}; |
581 | ADD_METHOD(UIContextualAction, contextualActionWithStyleUIContextualAction, 3,UIContextualActionM.insert({Ctx.Selectors.getSelector(3, contextualActionWithStyleUIContextualAction ), 1}); |
582 | 1)UIContextualActionM.insert({Ctx.Selectors.getSelector(3, contextualActionWithStyleUIContextualAction ), 1}); |
583 | ADD_UNARY_METHOD(UIContextualAction, setTitle, 0)UIContextualActionM.insert( {Ctx.Selectors.getUnarySelector(& Ctx.Idents.get("setTitle")), 0}); |
584 | |
585 | NEW_RECEIVER(NSAccessibilityCustomRotor)llvm::DenseMap<Selector, uint8_t> &NSAccessibilityCustomRotorM = UIMethods.insert({&Ctx.Idents.get("NSAccessibilityCustomRotor" ), llvm::DenseMap<Selector, uint8_t>()}) .first->second ; |
586 | IdentifierInfo *initWithLabelNSAccessibilityCustomRotor[] = { |
587 | &Ctx.Idents.get("initWithLabel"), &Ctx.Idents.get("itemSearchDelegate")}; |
588 | ADD_METHOD(NSAccessibilityCustomRotor,NSAccessibilityCustomRotorM.insert({Ctx.Selectors.getSelector (2, initWithLabelNSAccessibilityCustomRotor), 0}); |
589 | initWithLabelNSAccessibilityCustomRotor, 2, 0)NSAccessibilityCustomRotorM.insert({Ctx.Selectors.getSelector (2, initWithLabelNSAccessibilityCustomRotor), 0}); |
590 | ADD_UNARY_METHOD(NSAccessibilityCustomRotor, setLabel, 0)NSAccessibilityCustomRotorM.insert( {Ctx.Selectors.getUnarySelector (&Ctx.Idents.get("setLabel")), 0}); |
591 | |
592 | NEW_RECEIVER(NSWindowTab)llvm::DenseMap<Selector, uint8_t> &NSWindowTabM = UIMethods .insert({&Ctx.Idents.get("NSWindowTab"), llvm::DenseMap< Selector, uint8_t>()}) .first->second; |
593 | ADD_UNARY_METHOD(NSWindowTab, setTitle, 0)NSWindowTabM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setTitle")), 0}); |
594 | ADD_UNARY_METHOD(NSWindowTab, setToolTip, 0)NSWindowTabM.insert( {Ctx.Selectors.getUnarySelector(&Ctx .Idents.get("setToolTip")), 0}); |
595 | |
596 | NEW_RECEIVER(NSAccessibilityCustomAction)llvm::DenseMap<Selector, uint8_t> &NSAccessibilityCustomActionM = UIMethods.insert({&Ctx.Idents.get("NSAccessibilityCustomAction" ), llvm::DenseMap<Selector, uint8_t>()}) .first->second ; |
597 | IdentifierInfo *initWithNameNSAccessibilityCustomAction[] = { |
598 | &Ctx.Idents.get("initWithName"), &Ctx.Idents.get("handler")}; |
599 | ADD_METHOD(NSAccessibilityCustomAction,NSAccessibilityCustomActionM.insert({Ctx.Selectors.getSelector (2, initWithNameNSAccessibilityCustomAction), 0}); |
600 | initWithNameNSAccessibilityCustomAction, 2, 0)NSAccessibilityCustomActionM.insert({Ctx.Selectors.getSelector (2, initWithNameNSAccessibilityCustomAction), 0}); |
601 | IdentifierInfo *initWithNameTargetNSAccessibilityCustomAction[] = { |
602 | &Ctx.Idents.get("initWithName"), &Ctx.Idents.get("target"), |
603 | &Ctx.Idents.get("selector")}; |
604 | ADD_METHOD(NSAccessibilityCustomAction,NSAccessibilityCustomActionM.insert({Ctx.Selectors.getSelector (3, initWithNameTargetNSAccessibilityCustomAction), 0}); |
605 | initWithNameTargetNSAccessibilityCustomAction, 3, 0)NSAccessibilityCustomActionM.insert({Ctx.Selectors.getSelector (3, initWithNameTargetNSAccessibilityCustomAction), 0}); |
606 | ADD_UNARY_METHOD(NSAccessibilityCustomAction, setName, 0)NSAccessibilityCustomActionM.insert( {Ctx.Selectors.getUnarySelector (&Ctx.Idents.get("setName")), 0}); |
607 | } |
608 | |
609 | #define LSF_INSERT(function_name)LSF.insert(&Ctx.Idents.get(function_name)); LSF.insert(&Ctx.Idents.get(function_name)); |
610 | #define LSM_INSERT_NULLARY(receiver, method_name)LSM.insert({&Ctx.Idents.get(receiver), Ctx.Selectors.getNullarySelector ( &Ctx.Idents.get(method_name))}); \ |
611 | LSM.insert({&Ctx.Idents.get(receiver), Ctx.Selectors.getNullarySelector( \ |
612 | &Ctx.Idents.get(method_name))}); |
613 | #define LSM_INSERT_UNARY(receiver, method_name)LSM.insert({&Ctx.Idents.get(receiver), Ctx.Selectors.getUnarySelector (&Ctx.Idents.get(method_name))}); \ |
614 | LSM.insert({&Ctx.Idents.get(receiver), \ |
615 | Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(method_name))}); |
616 | #define LSM_INSERT_SELECTOR(receiver, method_list, arguments)LSM.insert({&Ctx.Idents.get(receiver), Ctx.Selectors.getSelector (arguments, method_list)}); \ |
617 | LSM.insert({&Ctx.Idents.get(receiver), \ |
618 | Ctx.Selectors.getSelector(arguments, method_list)}); |
619 | |
620 | /// Initializes a list of methods and C functions that return a localized string |
621 | void NonLocalizedStringChecker::initLocStringsMethods(ASTContext &Ctx) const { |
622 | if (!LSM.empty()) |
623 | return; |
624 | |
625 | IdentifierInfo *LocalizedStringMacro[] = { |
626 | &Ctx.Idents.get("localizedStringForKey"), &Ctx.Idents.get("value"), |
627 | &Ctx.Idents.get("table")}; |
628 | LSM_INSERT_SELECTOR("NSBundle", LocalizedStringMacro, 3)LSM.insert({&Ctx.Idents.get("NSBundle"), Ctx.Selectors.getSelector (3, LocalizedStringMacro)}); |
629 | LSM_INSERT_UNARY("NSDateFormatter", "stringFromDate")LSM.insert({&Ctx.Idents.get("NSDateFormatter"), Ctx.Selectors .getUnarySelector(&Ctx.Idents.get("stringFromDate"))}); |
630 | IdentifierInfo *LocalizedStringFromDate[] = { |
631 | &Ctx.Idents.get("localizedStringFromDate"), &Ctx.Idents.get("dateStyle"), |
632 | &Ctx.Idents.get("timeStyle")}; |
633 | LSM_INSERT_SELECTOR("NSDateFormatter", LocalizedStringFromDate, 3)LSM.insert({&Ctx.Idents.get("NSDateFormatter"), Ctx.Selectors .getSelector(3, LocalizedStringFromDate)}); |
634 | LSM_INSERT_UNARY("NSNumberFormatter", "stringFromNumber")LSM.insert({&Ctx.Idents.get("NSNumberFormatter"), Ctx.Selectors .getUnarySelector(&Ctx.Idents.get("stringFromNumber"))}); |
635 | LSM_INSERT_NULLARY("UITextField", "text")LSM.insert({&Ctx.Idents.get("UITextField"), Ctx.Selectors .getNullarySelector( &Ctx.Idents.get("text"))}); |
636 | LSM_INSERT_NULLARY("UITextView", "text")LSM.insert({&Ctx.Idents.get("UITextView"), Ctx.Selectors. getNullarySelector( &Ctx.Idents.get("text"))}); |
637 | LSM_INSERT_NULLARY("UILabel", "text")LSM.insert({&Ctx.Idents.get("UILabel"), Ctx.Selectors.getNullarySelector ( &Ctx.Idents.get("text"))}); |
638 | |
639 | LSF_INSERT("CFDateFormatterCreateStringWithDate")LSF.insert(&Ctx.Idents.get("CFDateFormatterCreateStringWithDate" ));; |
640 | LSF_INSERT("CFDateFormatterCreateStringWithAbsoluteTime")LSF.insert(&Ctx.Idents.get("CFDateFormatterCreateStringWithAbsoluteTime" ));; |
641 | LSF_INSERT("CFNumberFormatterCreateStringWithNumber")LSF.insert(&Ctx.Idents.get("CFNumberFormatterCreateStringWithNumber" ));; |
642 | } |
643 | |
644 | /// Checks to see if the method / function declaration includes |
645 | /// __attribute__((annotate("returns_localized_nsstring"))) |
646 | bool NonLocalizedStringChecker::isAnnotatedAsReturningLocalized( |
647 | const Decl *D) const { |
648 | if (!D) |
649 | return false; |
650 | return std::any_of( |
651 | D->specific_attr_begin<AnnotateAttr>(), |
652 | D->specific_attr_end<AnnotateAttr>(), [](const AnnotateAttr *Ann) { |
653 | return Ann->getAnnotation() == "returns_localized_nsstring"; |
654 | }); |
655 | } |
656 | |
657 | /// Checks to see if the method / function declaration includes |
658 | /// __attribute__((annotate("takes_localized_nsstring"))) |
659 | bool NonLocalizedStringChecker::isAnnotatedAsTakingLocalized( |
660 | const Decl *D) const { |
661 | if (!D) |
662 | return false; |
663 | return std::any_of( |
664 | D->specific_attr_begin<AnnotateAttr>(), |
665 | D->specific_attr_end<AnnotateAttr>(), [](const AnnotateAttr *Ann) { |
666 | return Ann->getAnnotation() == "takes_localized_nsstring"; |
667 | }); |
668 | } |
669 | |
670 | /// Returns true if the given SVal is marked as Localized in the program state |
671 | bool NonLocalizedStringChecker::hasLocalizedState(SVal S, |
672 | CheckerContext &C) const { |
673 | const MemRegion *mt = S.getAsRegion(); |
674 | if (mt) { |
675 | const LocalizedState *LS = C.getState()->get<LocalizedMemMap>(mt); |
676 | if (LS && LS->isLocalized()) |
677 | return true; |
678 | } |
679 | return false; |
680 | } |
681 | |
682 | /// Returns true if the given SVal is marked as NonLocalized in the program |
683 | /// state |
684 | bool NonLocalizedStringChecker::hasNonLocalizedState(SVal S, |
685 | CheckerContext &C) const { |
686 | const MemRegion *mt = S.getAsRegion(); |
687 | if (mt) { |
688 | const LocalizedState *LS = C.getState()->get<LocalizedMemMap>(mt); |
689 | if (LS && LS->isNonLocalized()) |
690 | return true; |
691 | } |
692 | return false; |
693 | } |
694 | |
695 | /// Marks the given SVal as Localized in the program state |
696 | void NonLocalizedStringChecker::setLocalizedState(const SVal S, |
697 | CheckerContext &C) const { |
698 | const MemRegion *mt = S.getAsRegion(); |
699 | if (mt) { |
700 | ProgramStateRef State = |
701 | C.getState()->set<LocalizedMemMap>(mt, LocalizedState::getLocalized()); |
702 | C.addTransition(State); |
703 | } |
704 | } |
705 | |
706 | /// Marks the given SVal as NonLocalized in the program state |
707 | void NonLocalizedStringChecker::setNonLocalizedState(const SVal S, |
708 | CheckerContext &C) const { |
709 | const MemRegion *mt = S.getAsRegion(); |
710 | if (mt) { |
711 | ProgramStateRef State = C.getState()->set<LocalizedMemMap>( |
712 | mt, LocalizedState::getNonLocalized()); |
713 | C.addTransition(State); |
714 | } |
715 | } |
716 | |
717 | |
718 | static bool isDebuggingName(std::string name) { |
719 | return StringRef(name).lower().find("debug") != StringRef::npos; |
720 | } |
721 | |
722 | /// Returns true when, heuristically, the analyzer may be analyzing debugging |
723 | /// code. We use this to suppress localization diagnostics in un-localized user |
724 | /// interfaces that are only used for debugging and are therefore not user |
725 | /// facing. |
726 | static bool isDebuggingContext(CheckerContext &C) { |
727 | const Decl *D = C.getCurrentAnalysisDeclContext()->getDecl(); |
728 | if (!D) |
729 | return false; |
730 | |
731 | if (auto *ND = dyn_cast<NamedDecl>(D)) { |
732 | if (isDebuggingName(ND->getNameAsString())) |
733 | return true; |
734 | } |
735 | |
736 | const DeclContext *DC = D->getDeclContext(); |
737 | |
738 | if (auto *CD = dyn_cast<ObjCContainerDecl>(DC)) { |
739 | if (isDebuggingName(CD->getNameAsString())) |
740 | return true; |
741 | } |
742 | |
743 | return false; |
744 | } |
745 | |
746 | |
747 | /// Reports a localization error for the passed in method call and SVal |
748 | void NonLocalizedStringChecker::reportLocalizationError( |
749 | SVal S, const CallEvent &M, CheckerContext &C, int argumentNumber) const { |
750 | |
751 | // Don't warn about localization errors in classes and methods that |
752 | // may be debug code. |
753 | if (isDebuggingContext(C)) |
754 | return; |
755 | |
756 | ExplodedNode *ErrNode = C.getPredecessor(); |
Value stored to 'ErrNode' during its initialization is never read | |
757 | static CheckerProgramPointTag Tag("NonLocalizedStringChecker", |
758 | "UnlocalizedString"); |
759 | ErrNode = C.addTransition(C.getState(), C.getPredecessor(), &Tag); |
760 | |
761 | if (!ErrNode) |
762 | return; |
763 | |
764 | // Generate the bug report. |
765 | std::unique_ptr<BugReport> R(new BugReport( |
766 | *BT, "User-facing text should use localized string macro", ErrNode)); |
767 | if (argumentNumber) { |
768 | R->addRange(M.getArgExpr(argumentNumber - 1)->getSourceRange()); |
769 | } else { |
770 | R->addRange(M.getSourceRange()); |
771 | } |
772 | R->markInteresting(S); |
773 | |
774 | const MemRegion *StringRegion = S.getAsRegion(); |
775 | if (StringRegion) |
776 | R->addVisitor(llvm::make_unique<NonLocalizedStringBRVisitor>(StringRegion)); |
777 | |
778 | C.emitReport(std::move(R)); |
779 | } |
780 | |
781 | /// Returns the argument number requiring localized string if it exists |
782 | /// otherwise, returns -1 |
783 | int NonLocalizedStringChecker::getLocalizedArgumentForSelector( |
784 | const IdentifierInfo *Receiver, Selector S) const { |
785 | auto method = UIMethods.find(Receiver); |
786 | |
787 | if (method == UIMethods.end()) |
788 | return -1; |
789 | |
790 | auto argumentIterator = method->getSecond().find(S); |
791 | |
792 | if (argumentIterator == method->getSecond().end()) |
793 | return -1; |
794 | |
795 | int argumentNumber = argumentIterator->getSecond(); |
796 | return argumentNumber; |
797 | } |
798 | |
799 | /// Check if the string being passed in has NonLocalized state |
800 | void NonLocalizedStringChecker::checkPreObjCMessage(const ObjCMethodCall &msg, |
801 | CheckerContext &C) const { |
802 | initUIMethods(C.getASTContext()); |
803 | |
804 | const ObjCInterfaceDecl *OD = msg.getReceiverInterface(); |
805 | if (!OD) |
806 | return; |
807 | const IdentifierInfo *odInfo = OD->getIdentifier(); |
808 | |
809 | Selector S = msg.getSelector(); |
810 | |
811 | std::string SelectorString = S.getAsString(); |
812 | StringRef SelectorName = SelectorString; |
813 | assert(!SelectorName.empty())((!SelectorName.empty()) ? static_cast<void> (0) : __assert_fail ("!SelectorName.empty()", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp" , 813, __PRETTY_FUNCTION__)); |
814 | |
815 | if (odInfo->isStr("NSString")) { |
816 | // Handle the case where the receiver is an NSString |
817 | // These special NSString methods draw to the screen |
818 | |
819 | if (!(SelectorName.startswith("drawAtPoint") || |
820 | SelectorName.startswith("drawInRect") || |
821 | SelectorName.startswith("drawWithRect"))) |
822 | return; |
823 | |
824 | SVal svTitle = msg.getReceiverSVal(); |
825 | |
826 | bool isNonLocalized = hasNonLocalizedState(svTitle, C); |
827 | |
828 | if (isNonLocalized) { |
829 | reportLocalizationError(svTitle, msg, C); |
830 | } |
831 | } |
832 | |
833 | int argumentNumber = getLocalizedArgumentForSelector(odInfo, S); |
834 | // Go up each hierarchy of superclasses and their protocols |
835 | while (argumentNumber < 0 && OD->getSuperClass() != nullptr) { |
836 | for (const auto *P : OD->all_referenced_protocols()) { |
837 | argumentNumber = getLocalizedArgumentForSelector(P->getIdentifier(), S); |
838 | if (argumentNumber >= 0) |
839 | break; |
840 | } |
841 | if (argumentNumber < 0) { |
842 | OD = OD->getSuperClass(); |
843 | argumentNumber = getLocalizedArgumentForSelector(OD->getIdentifier(), S); |
844 | } |
845 | } |
846 | |
847 | if (argumentNumber < 0) { // There was no match in UIMethods |
848 | if (const Decl *D = msg.getDecl()) { |
849 | if (const ObjCMethodDecl *OMD = dyn_cast_or_null<ObjCMethodDecl>(D)) { |
850 | auto formals = OMD->parameters(); |
851 | for (unsigned i = 0, ei = formals.size(); i != ei; ++i) { |
852 | if (isAnnotatedAsTakingLocalized(formals[i])) { |
853 | argumentNumber = i; |
854 | break; |
855 | } |
856 | } |
857 | } |
858 | } |
859 | } |
860 | |
861 | if (argumentNumber < 0) // Still no match |
862 | return; |
863 | |
864 | SVal svTitle = msg.getArgSVal(argumentNumber); |
865 | |
866 | if (const ObjCStringRegion *SR = |
867 | dyn_cast_or_null<ObjCStringRegion>(svTitle.getAsRegion())) { |
868 | StringRef stringValue = |
869 | SR->getObjCStringLiteral()->getString()->getString(); |
870 | if ((stringValue.trim().size() == 0 && stringValue.size() > 0) || |
871 | stringValue.empty()) |
872 | return; |
873 | if (!IsAggressive && llvm::sys::unicode::columnWidthUTF8(stringValue) < 2) |
874 | return; |
875 | } |
876 | |
877 | bool isNonLocalized = hasNonLocalizedState(svTitle, C); |
878 | |
879 | if (isNonLocalized) { |
880 | reportLocalizationError(svTitle, msg, C, argumentNumber + 1); |
881 | } |
882 | } |
883 | |
884 | void NonLocalizedStringChecker::checkPreCall(const CallEvent &Call, |
885 | CheckerContext &C) const { |
886 | const Decl *D = Call.getDecl(); |
887 | if (D && isa<FunctionDecl>(D)) { |
888 | const FunctionDecl *FD = dyn_cast<FunctionDecl>(D); |
889 | auto formals = FD->parameters(); |
890 | for (unsigned i = 0, |
891 | ei = std::min(unsigned(formals.size()), Call.getNumArgs()); |
892 | i != ei; ++i) { |
893 | if (isAnnotatedAsTakingLocalized(formals[i])) { |
894 | auto actual = Call.getArgSVal(i); |
895 | if (hasNonLocalizedState(actual, C)) { |
896 | reportLocalizationError(actual, Call, C, i + 1); |
897 | } |
898 | } |
899 | } |
900 | } |
901 | } |
902 | |
903 | static inline bool isNSStringType(QualType T, ASTContext &Ctx) { |
904 | |
905 | const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>(); |
906 | if (!PT) |
907 | return false; |
908 | |
909 | ObjCInterfaceDecl *Cls = PT->getObjectType()->getInterface(); |
910 | if (!Cls) |
911 | return false; |
912 | |
913 | IdentifierInfo *ClsName = Cls->getIdentifier(); |
914 | |
915 | // FIXME: Should we walk the chain of classes? |
916 | return ClsName == &Ctx.Idents.get("NSString") || |
917 | ClsName == &Ctx.Idents.get("NSMutableString"); |
918 | } |
919 | |
920 | /// Marks a string being returned by any call as localized |
921 | /// if it is in LocStringFunctions (LSF) or the function is annotated. |
922 | /// Otherwise, we mark it as NonLocalized (Aggressive) or |
923 | /// NonLocalized only if it is not backed by a SymRegion (Non-Aggressive), |
924 | /// basically leaving only string literals as NonLocalized. |
925 | void NonLocalizedStringChecker::checkPostCall(const CallEvent &Call, |
926 | CheckerContext &C) const { |
927 | initLocStringsMethods(C.getASTContext()); |
928 | |
929 | if (!Call.getOriginExpr()) |
930 | return; |
931 | |
932 | // Anything that takes in a localized NSString as an argument |
933 | // and returns an NSString will be assumed to be returning a |
934 | // localized NSString. (Counter: Incorrectly combining two LocalizedStrings) |
935 | const QualType RT = Call.getResultType(); |
936 | if (isNSStringType(RT, C.getASTContext())) { |
937 | for (unsigned i = 0; i < Call.getNumArgs(); ++i) { |
938 | SVal argValue = Call.getArgSVal(i); |
939 | if (hasLocalizedState(argValue, C)) { |
940 | SVal sv = Call.getReturnValue(); |
941 | setLocalizedState(sv, C); |
942 | return; |
943 | } |
944 | } |
945 | } |
946 | |
947 | const Decl *D = Call.getDecl(); |
948 | if (!D) |
949 | return; |
950 | |
951 | const IdentifierInfo *Identifier = Call.getCalleeIdentifier(); |
952 | |
953 | SVal sv = Call.getReturnValue(); |
954 | if (isAnnotatedAsReturningLocalized(D) || LSF.count(Identifier) != 0) { |
955 | setLocalizedState(sv, C); |
956 | } else if (isNSStringType(RT, C.getASTContext()) && |
957 | !hasLocalizedState(sv, C)) { |
958 | if (IsAggressive) { |
959 | setNonLocalizedState(sv, C); |
960 | } else { |
961 | const SymbolicRegion *SymReg = |
962 | dyn_cast_or_null<SymbolicRegion>(sv.getAsRegion()); |
963 | if (!SymReg) |
964 | setNonLocalizedState(sv, C); |
965 | } |
966 | } |
967 | } |
968 | |
969 | /// Marks a string being returned by an ObjC method as localized |
970 | /// if it is in LocStringMethods or the method is annotated |
971 | void NonLocalizedStringChecker::checkPostObjCMessage(const ObjCMethodCall &msg, |
972 | CheckerContext &C) const { |
973 | initLocStringsMethods(C.getASTContext()); |
974 | |
975 | if (!msg.isInstanceMessage()) |
976 | return; |
977 | |
978 | const ObjCInterfaceDecl *OD = msg.getReceiverInterface(); |
979 | if (!OD) |
980 | return; |
981 | const IdentifierInfo *odInfo = OD->getIdentifier(); |
982 | |
983 | Selector S = msg.getSelector(); |
984 | std::string SelectorName = S.getAsString(); |
985 | |
986 | std::pair<const IdentifierInfo *, Selector> MethodDescription = {odInfo, S}; |
987 | |
988 | if (LSM.count(MethodDescription) || |
989 | isAnnotatedAsReturningLocalized(msg.getDecl())) { |
990 | SVal sv = msg.getReturnValue(); |
991 | setLocalizedState(sv, C); |
992 | } |
993 | } |
994 | |
995 | /// Marks all empty string literals as localized |
996 | void NonLocalizedStringChecker::checkPostStmt(const ObjCStringLiteral *SL, |
997 | CheckerContext &C) const { |
998 | SVal sv = C.getSVal(SL); |
999 | setNonLocalizedState(sv, C); |
1000 | } |
1001 | |
1002 | std::shared_ptr<PathDiagnosticPiece> |
1003 | NonLocalizedStringBRVisitor::VisitNode(const ExplodedNode *Succ, |
1004 | BugReporterContext &BRC, BugReport &BR) { |
1005 | if (Satisfied) |
1006 | return nullptr; |
1007 | |
1008 | Optional<StmtPoint> Point = Succ->getLocation().getAs<StmtPoint>(); |
1009 | if (!Point.hasValue()) |
1010 | return nullptr; |
1011 | |
1012 | auto *LiteralExpr = dyn_cast<ObjCStringLiteral>(Point->getStmt()); |
1013 | if (!LiteralExpr) |
1014 | return nullptr; |
1015 | |
1016 | SVal LiteralSVal = Succ->getSVal(LiteralExpr); |
1017 | if (LiteralSVal.getAsRegion() != NonLocalizedString) |
1018 | return nullptr; |
1019 | |
1020 | Satisfied = true; |
1021 | |
1022 | PathDiagnosticLocation L = |
1023 | PathDiagnosticLocation::create(*Point, BRC.getSourceManager()); |
1024 | |
1025 | if (!L.isValid() || !L.asLocation().isValid()) |
1026 | return nullptr; |
1027 | |
1028 | auto Piece = std::make_shared<PathDiagnosticEventPiece>( |
1029 | L, "Non-localized string literal here"); |
1030 | Piece->addRange(LiteralExpr->getSourceRange()); |
1031 | |
1032 | return std::move(Piece); |
1033 | } |
1034 | |
1035 | namespace { |
1036 | class EmptyLocalizationContextChecker |
1037 | : public Checker<check::ASTDecl<ObjCImplementationDecl>> { |
1038 | |
1039 | // A helper class, which walks the AST |
1040 | class MethodCrawler : public ConstStmtVisitor<MethodCrawler> { |
1041 | const ObjCMethodDecl *MD; |
1042 | BugReporter &BR; |
1043 | AnalysisManager &Mgr; |
1044 | const CheckerBase *Checker; |
1045 | LocationOrAnalysisDeclContext DCtx; |
1046 | |
1047 | public: |
1048 | MethodCrawler(const ObjCMethodDecl *InMD, BugReporter &InBR, |
1049 | const CheckerBase *Checker, AnalysisManager &InMgr, |
1050 | AnalysisDeclContext *InDCtx) |
1051 | : MD(InMD), BR(InBR), Mgr(InMgr), Checker(Checker), DCtx(InDCtx) {} |
1052 | |
1053 | void VisitStmt(const Stmt *S) { VisitChildren(S); } |
1054 | |
1055 | void VisitObjCMessageExpr(const ObjCMessageExpr *ME); |
1056 | |
1057 | void reportEmptyContextError(const ObjCMessageExpr *M) const; |
1058 | |
1059 | void VisitChildren(const Stmt *S) { |
1060 | for (const Stmt *Child : S->children()) { |
1061 | if (Child) |
1062 | this->Visit(Child); |
1063 | } |
1064 | } |
1065 | }; |
1066 | |
1067 | public: |
1068 | void checkASTDecl(const ObjCImplementationDecl *D, AnalysisManager &Mgr, |
1069 | BugReporter &BR) const; |
1070 | }; |
1071 | } // end anonymous namespace |
1072 | |
1073 | void EmptyLocalizationContextChecker::checkASTDecl( |
1074 | const ObjCImplementationDecl *D, AnalysisManager &Mgr, |
1075 | BugReporter &BR) const { |
1076 | |
1077 | for (const ObjCMethodDecl *M : D->methods()) { |
1078 | AnalysisDeclContext *DCtx = Mgr.getAnalysisDeclContext(M); |
1079 | |
1080 | const Stmt *Body = M->getBody(); |
1081 | assert(Body)((Body) ? static_cast<void> (0) : __assert_fail ("Body" , "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp" , 1081, __PRETTY_FUNCTION__)); |
1082 | |
1083 | MethodCrawler MC(M->getCanonicalDecl(), BR, this, Mgr, DCtx); |
1084 | MC.VisitStmt(Body); |
1085 | } |
1086 | } |
1087 | |
1088 | /// This check attempts to match these macros, assuming they are defined as |
1089 | /// follows: |
1090 | /// |
1091 | /// #define NSLocalizedString(key, comment) \ |
1092 | /// [[NSBundle mainBundle] localizedStringForKey:(key) value:@"" table:nil] |
1093 | /// #define NSLocalizedStringFromTable(key, tbl, comment) \ |
1094 | /// [[NSBundle mainBundle] localizedStringForKey:(key) value:@"" table:(tbl)] |
1095 | /// #define NSLocalizedStringFromTableInBundle(key, tbl, bundle, comment) \ |
1096 | /// [bundle localizedStringForKey:(key) value:@"" table:(tbl)] |
1097 | /// #define NSLocalizedStringWithDefaultValue(key, tbl, bundle, val, comment) |
1098 | /// |
1099 | /// We cannot use the path sensitive check because the macro argument we are |
1100 | /// checking for (comment) is not used and thus not present in the AST, |
1101 | /// so we use Lexer on the original macro call and retrieve the value of |
1102 | /// the comment. If it's empty or nil, we raise a warning. |
1103 | void EmptyLocalizationContextChecker::MethodCrawler::VisitObjCMessageExpr( |
1104 | const ObjCMessageExpr *ME) { |
1105 | |
1106 | // FIXME: We may be able to use PPCallbacks to check for empty context |
1107 | // comments as part of preprocessing and avoid this re-lexing hack. |
1108 | const ObjCInterfaceDecl *OD = ME->getReceiverInterface(); |
1109 | if (!OD) |
1110 | return; |
1111 | |
1112 | const IdentifierInfo *odInfo = OD->getIdentifier(); |
1113 | |
1114 | if (!(odInfo->isStr("NSBundle") && |
1115 | ME->getSelector().getAsString() == |
1116 | "localizedStringForKey:value:table:")) { |
1117 | return; |
1118 | } |
1119 | |
1120 | SourceRange R = ME->getSourceRange(); |
1121 | if (!R.getBegin().isMacroID()) |
1122 | return; |
1123 | |
1124 | // getImmediateMacroCallerLoc gets the location of the immediate macro |
1125 | // caller, one level up the stack toward the initial macro typed into the |
1126 | // source, so SL should point to the NSLocalizedString macro. |
1127 | SourceLocation SL = |
1128 | Mgr.getSourceManager().getImmediateMacroCallerLoc(R.getBegin()); |
1129 | std::pair<FileID, unsigned> SLInfo = |
1130 | Mgr.getSourceManager().getDecomposedLoc(SL); |
1131 | |
1132 | SrcMgr::SLocEntry SE = Mgr.getSourceManager().getSLocEntry(SLInfo.first); |
1133 | |
1134 | // If NSLocalizedString macro is wrapped in another macro, we need to |
1135 | // unwrap the expansion until we get to the NSLocalizedStringMacro. |
1136 | while (SE.isExpansion()) { |
1137 | SL = SE.getExpansion().getSpellingLoc(); |
1138 | SLInfo = Mgr.getSourceManager().getDecomposedLoc(SL); |
1139 | SE = Mgr.getSourceManager().getSLocEntry(SLInfo.first); |
1140 | } |
1141 | |
1142 | bool Invalid = false; |
1143 | const llvm::MemoryBuffer *BF = |
1144 | Mgr.getSourceManager().getBuffer(SLInfo.first, SL, &Invalid); |
1145 | if (Invalid) |
1146 | return; |
1147 | |
1148 | Lexer TheLexer(SL, LangOptions(), BF->getBufferStart(), |
1149 | BF->getBufferStart() + SLInfo.second, BF->getBufferEnd()); |
1150 | |
1151 | Token I; |
1152 | Token Result; // This will hold the token just before the last ')' |
1153 | int p_count = 0; // This is for parenthesis matching |
1154 | while (!TheLexer.LexFromRawLexer(I)) { |
1155 | if (I.getKind() == tok::l_paren) |
1156 | ++p_count; |
1157 | if (I.getKind() == tok::r_paren) { |
1158 | if (p_count == 1) |
1159 | break; |
1160 | --p_count; |
1161 | } |
1162 | Result = I; |
1163 | } |
1164 | |
1165 | if (isAnyIdentifier(Result.getKind())) { |
1166 | if (Result.getRawIdentifier().equals("nil")) { |
1167 | reportEmptyContextError(ME); |
1168 | return; |
1169 | } |
1170 | } |
1171 | |
1172 | if (!isStringLiteral(Result.getKind())) |
1173 | return; |
1174 | |
1175 | StringRef Comment = |
1176 | StringRef(Result.getLiteralData(), Result.getLength()).trim('"'); |
1177 | |
1178 | if ((Comment.trim().size() == 0 && Comment.size() > 0) || // Is Whitespace |
1179 | Comment.empty()) { |
1180 | reportEmptyContextError(ME); |
1181 | } |
1182 | } |
1183 | |
1184 | void EmptyLocalizationContextChecker::MethodCrawler::reportEmptyContextError( |
1185 | const ObjCMessageExpr *ME) const { |
1186 | // Generate the bug report. |
1187 | BR.EmitBasicReport(MD, Checker, "Context Missing", |
1188 | "Localizability Issue (Apple)", |
1189 | "Localized string macro should include a non-empty " |
1190 | "comment for translators", |
1191 | PathDiagnosticLocation(ME, BR.getSourceManager(), DCtx)); |
1192 | } |
1193 | |
1194 | namespace { |
1195 | class PluralMisuseChecker : public Checker<check::ASTCodeBody> { |
1196 | |
1197 | // A helper class, which walks the AST |
1198 | class MethodCrawler : public RecursiveASTVisitor<MethodCrawler> { |
1199 | BugReporter &BR; |
1200 | const CheckerBase *Checker; |
1201 | AnalysisDeclContext *AC; |
1202 | |
1203 | // This functions like a stack. We push on any IfStmt or |
1204 | // ConditionalOperator that matches the condition |
1205 | // and pop it off when we leave that statement |
1206 | llvm::SmallVector<const clang::Stmt *, 8> MatchingStatements; |
1207 | // This is true when we are the direct-child of a |
1208 | // matching statement |
1209 | bool InMatchingStatement = false; |
1210 | |
1211 | public: |
1212 | explicit MethodCrawler(BugReporter &InBR, const CheckerBase *Checker, |
1213 | AnalysisDeclContext *InAC) |
1214 | : BR(InBR), Checker(Checker), AC(InAC) {} |
1215 | |
1216 | bool VisitIfStmt(const IfStmt *I); |
1217 | bool EndVisitIfStmt(IfStmt *I); |
1218 | bool TraverseIfStmt(IfStmt *x); |
1219 | bool VisitConditionalOperator(const ConditionalOperator *C); |
1220 | bool TraverseConditionalOperator(ConditionalOperator *C); |
1221 | bool VisitCallExpr(const CallExpr *CE); |
1222 | bool VisitObjCMessageExpr(const ObjCMessageExpr *ME); |
1223 | |
1224 | private: |
1225 | void reportPluralMisuseError(const Stmt *S) const; |
1226 | bool isCheckingPlurality(const Expr *E) const; |
1227 | }; |
1228 | |
1229 | public: |
1230 | void checkASTCodeBody(const Decl *D, AnalysisManager &Mgr, |
1231 | BugReporter &BR) const { |
1232 | MethodCrawler Visitor(BR, this, Mgr.getAnalysisDeclContext(D)); |
1233 | Visitor.TraverseDecl(const_cast<Decl *>(D)); |
1234 | } |
1235 | }; |
1236 | } // end anonymous namespace |
1237 | |
1238 | // Checks the condition of the IfStmt and returns true if one |
1239 | // of the following heuristics are met: |
1240 | // 1) The conidtion is a variable with "singular" or "plural" in the name |
1241 | // 2) The condition is a binary operator with 1 or 2 on the right-hand side |
1242 | bool PluralMisuseChecker::MethodCrawler::isCheckingPlurality( |
1243 | const Expr *Condition) const { |
1244 | const BinaryOperator *BO = nullptr; |
1245 | // Accounts for when a VarDecl represents a BinaryOperator |
1246 | if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Condition)) { |
1247 | if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) { |
1248 | const Expr *InitExpr = VD->getInit(); |
1249 | if (InitExpr) { |
1250 | if (const BinaryOperator *B = |
1251 | dyn_cast<BinaryOperator>(InitExpr->IgnoreParenImpCasts())) { |
1252 | BO = B; |
1253 | } |
1254 | } |
1255 | if (VD->getName().lower().find("plural") != StringRef::npos || |
1256 | VD->getName().lower().find("singular") != StringRef::npos) { |
1257 | return true; |
1258 | } |
1259 | } |
1260 | } else if (const BinaryOperator *B = dyn_cast<BinaryOperator>(Condition)) { |
1261 | BO = B; |
1262 | } |
1263 | |
1264 | if (BO == nullptr) |
1265 | return false; |
1266 | |
1267 | if (IntegerLiteral *IL = dyn_cast_or_null<IntegerLiteral>( |
1268 | BO->getRHS()->IgnoreParenImpCasts())) { |
1269 | llvm::APInt Value = IL->getValue(); |
1270 | if (Value == 1 || Value == 2) { |
1271 | return true; |
1272 | } |
1273 | } |
1274 | return false; |
1275 | } |
1276 | |
1277 | // A CallExpr with "LOC" in its identifier that takes in a string literal |
1278 | // has been shown to almost always be a function that returns a localized |
1279 | // string. Raise a diagnostic when this is in a statement that matches |
1280 | // the condition. |
1281 | bool PluralMisuseChecker::MethodCrawler::VisitCallExpr(const CallExpr *CE) { |
1282 | if (InMatchingStatement) { |
1283 | if (const FunctionDecl *FD = CE->getDirectCallee()) { |
1284 | std::string NormalizedName = |
1285 | StringRef(FD->getNameInfo().getAsString()).lower(); |
1286 | if (NormalizedName.find("loc") != std::string::npos) { |
1287 | for (const Expr *Arg : CE->arguments()) { |
1288 | if (isa<ObjCStringLiteral>(Arg)) |
1289 | reportPluralMisuseError(CE); |
1290 | } |
1291 | } |
1292 | } |
1293 | } |
1294 | return true; |
1295 | } |
1296 | |
1297 | // The other case is for NSLocalizedString which also returns |
1298 | // a localized string. It's a macro for the ObjCMessageExpr |
1299 | // [NSBundle localizedStringForKey:value:table:] Raise a |
1300 | // diagnostic when this is in a statement that matches |
1301 | // the condition. |
1302 | bool PluralMisuseChecker::MethodCrawler::VisitObjCMessageExpr( |
1303 | const ObjCMessageExpr *ME) { |
1304 | const ObjCInterfaceDecl *OD = ME->getReceiverInterface(); |
1305 | if (!OD) |
1306 | return true; |
1307 | |
1308 | const IdentifierInfo *odInfo = OD->getIdentifier(); |
1309 | |
1310 | if (odInfo->isStr("NSBundle") && |
1311 | ME->getSelector().getAsString() == "localizedStringForKey:value:table:") { |
1312 | if (InMatchingStatement) { |
1313 | reportPluralMisuseError(ME); |
1314 | } |
1315 | } |
1316 | return true; |
1317 | } |
1318 | |
1319 | /// Override TraverseIfStmt so we know when we are done traversing an IfStmt |
1320 | bool PluralMisuseChecker::MethodCrawler::TraverseIfStmt(IfStmt *I) { |
1321 | RecursiveASTVisitor<MethodCrawler>::TraverseIfStmt(I); |
1322 | return EndVisitIfStmt(I); |
1323 | } |
1324 | |
1325 | // EndVisit callbacks are not provided by the RecursiveASTVisitor |
1326 | // so we override TraverseIfStmt and make a call to EndVisitIfStmt |
1327 | // after traversing the IfStmt |
1328 | bool PluralMisuseChecker::MethodCrawler::EndVisitIfStmt(IfStmt *I) { |
1329 | MatchingStatements.pop_back(); |
1330 | if (!MatchingStatements.empty()) { |
1331 | if (MatchingStatements.back() != nullptr) { |
1332 | InMatchingStatement = true; |
1333 | return true; |
1334 | } |
1335 | } |
1336 | InMatchingStatement = false; |
1337 | return true; |
1338 | } |
1339 | |
1340 | bool PluralMisuseChecker::MethodCrawler::VisitIfStmt(const IfStmt *I) { |
1341 | const Expr *Condition = I->getCond()->IgnoreParenImpCasts(); |
1342 | if (isCheckingPlurality(Condition)) { |
1343 | MatchingStatements.push_back(I); |
1344 | InMatchingStatement = true; |
1345 | } else { |
1346 | MatchingStatements.push_back(nullptr); |
1347 | InMatchingStatement = false; |
1348 | } |
1349 | |
1350 | return true; |
1351 | } |
1352 | |
1353 | // Preliminary support for conditional operators. |
1354 | bool PluralMisuseChecker::MethodCrawler::TraverseConditionalOperator( |
1355 | ConditionalOperator *C) { |
1356 | RecursiveASTVisitor<MethodCrawler>::TraverseConditionalOperator(C); |
1357 | MatchingStatements.pop_back(); |
1358 | if (!MatchingStatements.empty()) { |
1359 | if (MatchingStatements.back() != nullptr) |
1360 | InMatchingStatement = true; |
1361 | else |
1362 | InMatchingStatement = false; |
1363 | } else { |
1364 | InMatchingStatement = false; |
1365 | } |
1366 | return true; |
1367 | } |
1368 | |
1369 | bool PluralMisuseChecker::MethodCrawler::VisitConditionalOperator( |
1370 | const ConditionalOperator *C) { |
1371 | const Expr *Condition = C->getCond()->IgnoreParenImpCasts(); |
1372 | if (isCheckingPlurality(Condition)) { |
1373 | MatchingStatements.push_back(C); |
1374 | InMatchingStatement = true; |
1375 | } else { |
1376 | MatchingStatements.push_back(nullptr); |
1377 | InMatchingStatement = false; |
1378 | } |
1379 | return true; |
1380 | } |
1381 | |
1382 | void PluralMisuseChecker::MethodCrawler::reportPluralMisuseError( |
1383 | const Stmt *S) const { |
1384 | // Generate the bug report. |
1385 | BR.EmitBasicReport(AC->getDecl(), Checker, "Plural Misuse", |
1386 | "Localizability Issue (Apple)", |
1387 | "Plural cases are not supported across all languages. " |
1388 | "Use a .stringsdict file instead", |
1389 | PathDiagnosticLocation(S, BR.getSourceManager(), AC)); |
1390 | } |
1391 | |
1392 | //===----------------------------------------------------------------------===// |
1393 | // Checker registration. |
1394 | //===----------------------------------------------------------------------===// |
1395 | |
1396 | void ento::registerNonLocalizedStringChecker(CheckerManager &mgr) { |
1397 | NonLocalizedStringChecker *checker = |
1398 | mgr.registerChecker<NonLocalizedStringChecker>(); |
1399 | checker->IsAggressive = |
1400 | mgr.getAnalyzerOptions().getCheckerBooleanOption( |
1401 | checker, "AggressiveReport"); |
1402 | } |
1403 | |
1404 | bool ento::shouldRegisterNonLocalizedStringChecker(const LangOptions &LO) { |
1405 | return true; |
1406 | } |
1407 | |
1408 | void ento::registerEmptyLocalizationContextChecker(CheckerManager &mgr) { |
1409 | mgr.registerChecker<EmptyLocalizationContextChecker>(); |
1410 | } |
1411 | |
1412 | bool ento::shouldRegisterEmptyLocalizationContextChecker( |
1413 | const LangOptions &LO) { |
1414 | return true; |
1415 | } |
1416 | |
1417 | void ento::registerPluralMisuseChecker(CheckerManager &mgr) { |
1418 | mgr.registerChecker<PluralMisuseChecker>(); |
1419 | } |
1420 | |
1421 | bool ento::shouldRegisterPluralMisuseChecker(const LangOptions &LO) { |
1422 | return true; |
1423 | } |