annotate clang/lib/AST/PrintfFormatString.cpp @ 207:2e18cbf3894f

LLVM12
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Tue, 08 Jun 2021 06:07:14 +0900
parents 0572611fdcc8
children c4bab56944e8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 //== PrintfFormatString.cpp - Analysis of printf format strings --*- C++ -*-==//
anatofuz
parents:
diff changeset
2 //
anatofuz
parents:
diff changeset
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
anatofuz
parents:
diff changeset
4 // See https://llvm.org/LICENSE.txt for license information.
anatofuz
parents:
diff changeset
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
anatofuz
parents:
diff changeset
6 //
anatofuz
parents:
diff changeset
7 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
8 //
anatofuz
parents:
diff changeset
9 // Handling of format string in printf and friends. The structure of format
anatofuz
parents:
diff changeset
10 // strings for fprintf() are described in C99 7.19.6.1.
anatofuz
parents:
diff changeset
11 //
anatofuz
parents:
diff changeset
12 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
13
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
14 #include "FormatStringParsing.h"
150
anatofuz
parents:
diff changeset
15 #include "clang/AST/FormatString.h"
anatofuz
parents:
diff changeset
16 #include "clang/AST/OSLog.h"
anatofuz
parents:
diff changeset
17 #include "clang/Basic/TargetInfo.h"
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
18 #include "llvm/Support/Regex.h"
150
anatofuz
parents:
diff changeset
19
anatofuz
parents:
diff changeset
20 using clang::analyze_format_string::ArgType;
anatofuz
parents:
diff changeset
21 using clang::analyze_format_string::FormatStringHandler;
anatofuz
parents:
diff changeset
22 using clang::analyze_format_string::LengthModifier;
anatofuz
parents:
diff changeset
23 using clang::analyze_format_string::OptionalAmount;
anatofuz
parents:
diff changeset
24 using clang::analyze_format_string::ConversionSpecifier;
anatofuz
parents:
diff changeset
25 using clang::analyze_printf::PrintfSpecifier;
anatofuz
parents:
diff changeset
26
anatofuz
parents:
diff changeset
27 using namespace clang;
anatofuz
parents:
diff changeset
28
anatofuz
parents:
diff changeset
29 typedef clang::analyze_format_string::SpecifierResult<PrintfSpecifier>
anatofuz
parents:
diff changeset
30 PrintfSpecifierResult;
anatofuz
parents:
diff changeset
31
anatofuz
parents:
diff changeset
32 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
33 // Methods for parsing format strings.
anatofuz
parents:
diff changeset
34 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
35
anatofuz
parents:
diff changeset
36 using analyze_format_string::ParseNonPositionAmount;
anatofuz
parents:
diff changeset
37
anatofuz
parents:
diff changeset
38 static bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS,
anatofuz
parents:
diff changeset
39 const char *Start, const char *&Beg, const char *E,
anatofuz
parents:
diff changeset
40 unsigned *argIndex) {
anatofuz
parents:
diff changeset
41 if (argIndex) {
anatofuz
parents:
diff changeset
42 FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex));
anatofuz
parents:
diff changeset
43 } else {
anatofuz
parents:
diff changeset
44 const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E,
anatofuz
parents:
diff changeset
45 analyze_format_string::PrecisionPos);
anatofuz
parents:
diff changeset
46 if (Amt.isInvalid())
anatofuz
parents:
diff changeset
47 return true;
anatofuz
parents:
diff changeset
48 FS.setPrecision(Amt);
anatofuz
parents:
diff changeset
49 }
anatofuz
parents:
diff changeset
50 return false;
anatofuz
parents:
diff changeset
51 }
anatofuz
parents:
diff changeset
52
anatofuz
parents:
diff changeset
53 static bool ParseObjCFlags(FormatStringHandler &H, PrintfSpecifier &FS,
anatofuz
parents:
diff changeset
54 const char *FlagBeg, const char *E, bool Warn) {
anatofuz
parents:
diff changeset
55 StringRef Flag(FlagBeg, E - FlagBeg);
anatofuz
parents:
diff changeset
56 // Currently there is only one flag.
anatofuz
parents:
diff changeset
57 if (Flag == "tt") {
anatofuz
parents:
diff changeset
58 FS.setHasObjCTechnicalTerm(FlagBeg);
anatofuz
parents:
diff changeset
59 return false;
anatofuz
parents:
diff changeset
60 }
anatofuz
parents:
diff changeset
61 // Handle either the case of no flag or an invalid flag.
anatofuz
parents:
diff changeset
62 if (Warn) {
anatofuz
parents:
diff changeset
63 if (Flag == "")
anatofuz
parents:
diff changeset
64 H.HandleEmptyObjCModifierFlag(FlagBeg, E - FlagBeg);
anatofuz
parents:
diff changeset
65 else
anatofuz
parents:
diff changeset
66 H.HandleInvalidObjCModifierFlag(FlagBeg, E - FlagBeg);
anatofuz
parents:
diff changeset
67 }
anatofuz
parents:
diff changeset
68 return true;
anatofuz
parents:
diff changeset
69 }
anatofuz
parents:
diff changeset
70
anatofuz
parents:
diff changeset
71 static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
anatofuz
parents:
diff changeset
72 const char *&Beg,
anatofuz
parents:
diff changeset
73 const char *E,
anatofuz
parents:
diff changeset
74 unsigned &argIndex,
anatofuz
parents:
diff changeset
75 const LangOptions &LO,
anatofuz
parents:
diff changeset
76 const TargetInfo &Target,
anatofuz
parents:
diff changeset
77 bool Warn,
anatofuz
parents:
diff changeset
78 bool isFreeBSDKPrintf) {
anatofuz
parents:
diff changeset
79
anatofuz
parents:
diff changeset
80 using namespace clang::analyze_format_string;
anatofuz
parents:
diff changeset
81 using namespace clang::analyze_printf;
anatofuz
parents:
diff changeset
82
anatofuz
parents:
diff changeset
83 const char *I = Beg;
anatofuz
parents:
diff changeset
84 const char *Start = nullptr;
anatofuz
parents:
diff changeset
85 UpdateOnReturn <const char*> UpdateBeg(Beg, I);
anatofuz
parents:
diff changeset
86
anatofuz
parents:
diff changeset
87 // Look for a '%' character that indicates the start of a format specifier.
anatofuz
parents:
diff changeset
88 for ( ; I != E ; ++I) {
anatofuz
parents:
diff changeset
89 char c = *I;
anatofuz
parents:
diff changeset
90 if (c == '\0') {
anatofuz
parents:
diff changeset
91 // Detect spurious null characters, which are likely errors.
anatofuz
parents:
diff changeset
92 H.HandleNullChar(I);
anatofuz
parents:
diff changeset
93 return true;
anatofuz
parents:
diff changeset
94 }
anatofuz
parents:
diff changeset
95 if (c == '%') {
anatofuz
parents:
diff changeset
96 Start = I++; // Record the start of the format specifier.
anatofuz
parents:
diff changeset
97 break;
anatofuz
parents:
diff changeset
98 }
anatofuz
parents:
diff changeset
99 }
anatofuz
parents:
diff changeset
100
anatofuz
parents:
diff changeset
101 // No format specifier found?
anatofuz
parents:
diff changeset
102 if (!Start)
anatofuz
parents:
diff changeset
103 return false;
anatofuz
parents:
diff changeset
104
anatofuz
parents:
diff changeset
105 if (I == E) {
anatofuz
parents:
diff changeset
106 // No more characters left?
anatofuz
parents:
diff changeset
107 if (Warn)
anatofuz
parents:
diff changeset
108 H.HandleIncompleteSpecifier(Start, E - Start);
anatofuz
parents:
diff changeset
109 return true;
anatofuz
parents:
diff changeset
110 }
anatofuz
parents:
diff changeset
111
anatofuz
parents:
diff changeset
112 PrintfSpecifier FS;
anatofuz
parents:
diff changeset
113 if (ParseArgPosition(H, FS, Start, I, E))
anatofuz
parents:
diff changeset
114 return true;
anatofuz
parents:
diff changeset
115
anatofuz
parents:
diff changeset
116 if (I == E) {
anatofuz
parents:
diff changeset
117 // No more characters left?
anatofuz
parents:
diff changeset
118 if (Warn)
anatofuz
parents:
diff changeset
119 H.HandleIncompleteSpecifier(Start, E - Start);
anatofuz
parents:
diff changeset
120 return true;
anatofuz
parents:
diff changeset
121 }
anatofuz
parents:
diff changeset
122
anatofuz
parents:
diff changeset
123 if (*I == '{') {
anatofuz
parents:
diff changeset
124 ++I;
anatofuz
parents:
diff changeset
125 unsigned char PrivacyFlags = 0;
anatofuz
parents:
diff changeset
126 StringRef MatchedStr;
anatofuz
parents:
diff changeset
127
anatofuz
parents:
diff changeset
128 do {
anatofuz
parents:
diff changeset
129 StringRef Str(I, E - I);
anatofuz
parents:
diff changeset
130 std::string Match = "^[[:space:]]*"
anatofuz
parents:
diff changeset
131 "(private|public|sensitive|mask\\.[^[:space:],}]*)"
anatofuz
parents:
diff changeset
132 "[[:space:]]*(,|})";
anatofuz
parents:
diff changeset
133 llvm::Regex R(Match);
anatofuz
parents:
diff changeset
134 SmallVector<StringRef, 2> Matches;
anatofuz
parents:
diff changeset
135
anatofuz
parents:
diff changeset
136 if (R.match(Str, &Matches)) {
anatofuz
parents:
diff changeset
137 MatchedStr = Matches[1];
anatofuz
parents:
diff changeset
138 I += Matches[0].size();
anatofuz
parents:
diff changeset
139
anatofuz
parents:
diff changeset
140 // Set the privacy flag if the privacy annotation in the
anatofuz
parents:
diff changeset
141 // comma-delimited segment is at least as strict as the privacy
anatofuz
parents:
diff changeset
142 // annotations in previous comma-delimited segments.
anatofuz
parents:
diff changeset
143 if (MatchedStr.startswith("mask")) {
anatofuz
parents:
diff changeset
144 StringRef MaskType = MatchedStr.substr(sizeof("mask.") - 1);
anatofuz
parents:
diff changeset
145 unsigned Size = MaskType.size();
anatofuz
parents:
diff changeset
146 if (Warn && (Size == 0 || Size > 8))
anatofuz
parents:
diff changeset
147 H.handleInvalidMaskType(MaskType);
anatofuz
parents:
diff changeset
148 FS.setMaskType(MaskType);
anatofuz
parents:
diff changeset
149 } else if (MatchedStr.equals("sensitive"))
anatofuz
parents:
diff changeset
150 PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsSensitive;
anatofuz
parents:
diff changeset
151 else if (PrivacyFlags !=
anatofuz
parents:
diff changeset
152 clang::analyze_os_log::OSLogBufferItem::IsSensitive &&
anatofuz
parents:
diff changeset
153 MatchedStr.equals("private"))
anatofuz
parents:
diff changeset
154 PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPrivate;
anatofuz
parents:
diff changeset
155 else if (PrivacyFlags == 0 && MatchedStr.equals("public"))
anatofuz
parents:
diff changeset
156 PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPublic;
anatofuz
parents:
diff changeset
157 } else {
anatofuz
parents:
diff changeset
158 size_t CommaOrBracePos =
anatofuz
parents:
diff changeset
159 Str.find_if([](char c) { return c == ',' || c == '}'; });
anatofuz
parents:
diff changeset
160
anatofuz
parents:
diff changeset
161 if (CommaOrBracePos == StringRef::npos) {
anatofuz
parents:
diff changeset
162 // Neither a comma nor the closing brace was found.
anatofuz
parents:
diff changeset
163 if (Warn)
anatofuz
parents:
diff changeset
164 H.HandleIncompleteSpecifier(Start, E - Start);
anatofuz
parents:
diff changeset
165 return true;
anatofuz
parents:
diff changeset
166 }
anatofuz
parents:
diff changeset
167
anatofuz
parents:
diff changeset
168 I += CommaOrBracePos + 1;
anatofuz
parents:
diff changeset
169 }
anatofuz
parents:
diff changeset
170 // Continue until the closing brace is found.
anatofuz
parents:
diff changeset
171 } while (*(I - 1) == ',');
anatofuz
parents:
diff changeset
172
anatofuz
parents:
diff changeset
173 // Set the privacy flag.
anatofuz
parents:
diff changeset
174 switch (PrivacyFlags) {
anatofuz
parents:
diff changeset
175 case 0:
anatofuz
parents:
diff changeset
176 break;
anatofuz
parents:
diff changeset
177 case clang::analyze_os_log::OSLogBufferItem::IsPrivate:
anatofuz
parents:
diff changeset
178 FS.setIsPrivate(MatchedStr.data());
anatofuz
parents:
diff changeset
179 break;
anatofuz
parents:
diff changeset
180 case clang::analyze_os_log::OSLogBufferItem::IsPublic:
anatofuz
parents:
diff changeset
181 FS.setIsPublic(MatchedStr.data());
anatofuz
parents:
diff changeset
182 break;
anatofuz
parents:
diff changeset
183 case clang::analyze_os_log::OSLogBufferItem::IsSensitive:
anatofuz
parents:
diff changeset
184 FS.setIsSensitive(MatchedStr.data());
anatofuz
parents:
diff changeset
185 break;
anatofuz
parents:
diff changeset
186 default:
anatofuz
parents:
diff changeset
187 llvm_unreachable("Unexpected privacy flag value");
anatofuz
parents:
diff changeset
188 }
anatofuz
parents:
diff changeset
189 }
anatofuz
parents:
diff changeset
190
anatofuz
parents:
diff changeset
191 // Look for flags (if any).
anatofuz
parents:
diff changeset
192 bool hasMore = true;
anatofuz
parents:
diff changeset
193 for ( ; I != E; ++I) {
anatofuz
parents:
diff changeset
194 switch (*I) {
anatofuz
parents:
diff changeset
195 default: hasMore = false; break;
anatofuz
parents:
diff changeset
196 case '\'':
anatofuz
parents:
diff changeset
197 // FIXME: POSIX specific. Always accept?
anatofuz
parents:
diff changeset
198 FS.setHasThousandsGrouping(I);
anatofuz
parents:
diff changeset
199 break;
anatofuz
parents:
diff changeset
200 case '-': FS.setIsLeftJustified(I); break;
anatofuz
parents:
diff changeset
201 case '+': FS.setHasPlusPrefix(I); break;
anatofuz
parents:
diff changeset
202 case ' ': FS.setHasSpacePrefix(I); break;
anatofuz
parents:
diff changeset
203 case '#': FS.setHasAlternativeForm(I); break;
anatofuz
parents:
diff changeset
204 case '0': FS.setHasLeadingZeros(I); break;
anatofuz
parents:
diff changeset
205 }
anatofuz
parents:
diff changeset
206 if (!hasMore)
anatofuz
parents:
diff changeset
207 break;
anatofuz
parents:
diff changeset
208 }
anatofuz
parents:
diff changeset
209
anatofuz
parents:
diff changeset
210 if (I == E) {
anatofuz
parents:
diff changeset
211 // No more characters left?
anatofuz
parents:
diff changeset
212 if (Warn)
anatofuz
parents:
diff changeset
213 H.HandleIncompleteSpecifier(Start, E - Start);
anatofuz
parents:
diff changeset
214 return true;
anatofuz
parents:
diff changeset
215 }
anatofuz
parents:
diff changeset
216
anatofuz
parents:
diff changeset
217 // Look for the field width (if any).
anatofuz
parents:
diff changeset
218 if (ParseFieldWidth(H, FS, Start, I, E,
anatofuz
parents:
diff changeset
219 FS.usesPositionalArg() ? nullptr : &argIndex))
anatofuz
parents:
diff changeset
220 return true;
anatofuz
parents:
diff changeset
221
anatofuz
parents:
diff changeset
222 if (I == E) {
anatofuz
parents:
diff changeset
223 // No more characters left?
anatofuz
parents:
diff changeset
224 if (Warn)
anatofuz
parents:
diff changeset
225 H.HandleIncompleteSpecifier(Start, E - Start);
anatofuz
parents:
diff changeset
226 return true;
anatofuz
parents:
diff changeset
227 }
anatofuz
parents:
diff changeset
228
anatofuz
parents:
diff changeset
229 // Look for the precision (if any).
anatofuz
parents:
diff changeset
230 if (*I == '.') {
anatofuz
parents:
diff changeset
231 ++I;
anatofuz
parents:
diff changeset
232 if (I == E) {
anatofuz
parents:
diff changeset
233 if (Warn)
anatofuz
parents:
diff changeset
234 H.HandleIncompleteSpecifier(Start, E - Start);
anatofuz
parents:
diff changeset
235 return true;
anatofuz
parents:
diff changeset
236 }
anatofuz
parents:
diff changeset
237
anatofuz
parents:
diff changeset
238 if (ParsePrecision(H, FS, Start, I, E,
anatofuz
parents:
diff changeset
239 FS.usesPositionalArg() ? nullptr : &argIndex))
anatofuz
parents:
diff changeset
240 return true;
anatofuz
parents:
diff changeset
241
anatofuz
parents:
diff changeset
242 if (I == E) {
anatofuz
parents:
diff changeset
243 // No more characters left?
anatofuz
parents:
diff changeset
244 if (Warn)
anatofuz
parents:
diff changeset
245 H.HandleIncompleteSpecifier(Start, E - Start);
anatofuz
parents:
diff changeset
246 return true;
anatofuz
parents:
diff changeset
247 }
anatofuz
parents:
diff changeset
248 }
anatofuz
parents:
diff changeset
249
anatofuz
parents:
diff changeset
250 if (ParseVectorModifier(H, FS, I, E, LO))
anatofuz
parents:
diff changeset
251 return true;
anatofuz
parents:
diff changeset
252
anatofuz
parents:
diff changeset
253 // Look for the length modifier.
anatofuz
parents:
diff changeset
254 if (ParseLengthModifier(FS, I, E, LO) && I == E) {
anatofuz
parents:
diff changeset
255 // No more characters left?
anatofuz
parents:
diff changeset
256 if (Warn)
anatofuz
parents:
diff changeset
257 H.HandleIncompleteSpecifier(Start, E - Start);
anatofuz
parents:
diff changeset
258 return true;
anatofuz
parents:
diff changeset
259 }
anatofuz
parents:
diff changeset
260
anatofuz
parents:
diff changeset
261 // Look for the Objective-C modifier flags, if any.
anatofuz
parents:
diff changeset
262 // We parse these here, even if they don't apply to
anatofuz
parents:
diff changeset
263 // the conversion specifier, and then emit an error
anatofuz
parents:
diff changeset
264 // later if the conversion specifier isn't '@'. This
anatofuz
parents:
diff changeset
265 // enables better recovery, and we don't know if
anatofuz
parents:
diff changeset
266 // these flags are applicable until later.
anatofuz
parents:
diff changeset
267 const char *ObjCModifierFlagsStart = nullptr,
anatofuz
parents:
diff changeset
268 *ObjCModifierFlagsEnd = nullptr;
anatofuz
parents:
diff changeset
269 if (*I == '[') {
anatofuz
parents:
diff changeset
270 ObjCModifierFlagsStart = I;
anatofuz
parents:
diff changeset
271 ++I;
anatofuz
parents:
diff changeset
272 auto flagStart = I;
anatofuz
parents:
diff changeset
273 for (;; ++I) {
anatofuz
parents:
diff changeset
274 ObjCModifierFlagsEnd = I;
anatofuz
parents:
diff changeset
275 if (I == E) {
anatofuz
parents:
diff changeset
276 if (Warn)
anatofuz
parents:
diff changeset
277 H.HandleIncompleteSpecifier(Start, E - Start);
anatofuz
parents:
diff changeset
278 return true;
anatofuz
parents:
diff changeset
279 }
anatofuz
parents:
diff changeset
280 // Did we find the closing ']'?
anatofuz
parents:
diff changeset
281 if (*I == ']') {
anatofuz
parents:
diff changeset
282 if (ParseObjCFlags(H, FS, flagStart, I, Warn))
anatofuz
parents:
diff changeset
283 return true;
anatofuz
parents:
diff changeset
284 ++I;
anatofuz
parents:
diff changeset
285 break;
anatofuz
parents:
diff changeset
286 }
anatofuz
parents:
diff changeset
287 // There are no separators defined yet for multiple
anatofuz
parents:
diff changeset
288 // Objective-C modifier flags. When those are
anatofuz
parents:
diff changeset
289 // defined, this is the place to check.
anatofuz
parents:
diff changeset
290 }
anatofuz
parents:
diff changeset
291 }
anatofuz
parents:
diff changeset
292
anatofuz
parents:
diff changeset
293 if (*I == '\0') {
anatofuz
parents:
diff changeset
294 // Detect spurious null characters, which are likely errors.
anatofuz
parents:
diff changeset
295 H.HandleNullChar(I);
anatofuz
parents:
diff changeset
296 return true;
anatofuz
parents:
diff changeset
297 }
anatofuz
parents:
diff changeset
298
anatofuz
parents:
diff changeset
299 // Finally, look for the conversion specifier.
anatofuz
parents:
diff changeset
300 const char *conversionPosition = I++;
anatofuz
parents:
diff changeset
301 ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier;
anatofuz
parents:
diff changeset
302 switch (*conversionPosition) {
anatofuz
parents:
diff changeset
303 default:
anatofuz
parents:
diff changeset
304 break;
anatofuz
parents:
diff changeset
305 // C99: 7.19.6.1 (section 8).
anatofuz
parents:
diff changeset
306 case '%': k = ConversionSpecifier::PercentArg; break;
anatofuz
parents:
diff changeset
307 case 'A': k = ConversionSpecifier::AArg; break;
anatofuz
parents:
diff changeset
308 case 'E': k = ConversionSpecifier::EArg; break;
anatofuz
parents:
diff changeset
309 case 'F': k = ConversionSpecifier::FArg; break;
anatofuz
parents:
diff changeset
310 case 'G': k = ConversionSpecifier::GArg; break;
anatofuz
parents:
diff changeset
311 case 'X': k = ConversionSpecifier::XArg; break;
anatofuz
parents:
diff changeset
312 case 'a': k = ConversionSpecifier::aArg; break;
anatofuz
parents:
diff changeset
313 case 'c': k = ConversionSpecifier::cArg; break;
anatofuz
parents:
diff changeset
314 case 'd': k = ConversionSpecifier::dArg; break;
anatofuz
parents:
diff changeset
315 case 'e': k = ConversionSpecifier::eArg; break;
anatofuz
parents:
diff changeset
316 case 'f': k = ConversionSpecifier::fArg; break;
anatofuz
parents:
diff changeset
317 case 'g': k = ConversionSpecifier::gArg; break;
anatofuz
parents:
diff changeset
318 case 'i': k = ConversionSpecifier::iArg; break;
anatofuz
parents:
diff changeset
319 case 'n':
anatofuz
parents:
diff changeset
320 // Not handled, but reserved in OpenCL.
anatofuz
parents:
diff changeset
321 if (!LO.OpenCL)
anatofuz
parents:
diff changeset
322 k = ConversionSpecifier::nArg;
anatofuz
parents:
diff changeset
323 break;
anatofuz
parents:
diff changeset
324 case 'o': k = ConversionSpecifier::oArg; break;
anatofuz
parents:
diff changeset
325 case 'p': k = ConversionSpecifier::pArg; break;
anatofuz
parents:
diff changeset
326 case 's': k = ConversionSpecifier::sArg; break;
anatofuz
parents:
diff changeset
327 case 'u': k = ConversionSpecifier::uArg; break;
anatofuz
parents:
diff changeset
328 case 'x': k = ConversionSpecifier::xArg; break;
anatofuz
parents:
diff changeset
329 // POSIX specific.
anatofuz
parents:
diff changeset
330 case 'C': k = ConversionSpecifier::CArg; break;
anatofuz
parents:
diff changeset
331 case 'S': k = ConversionSpecifier::SArg; break;
anatofuz
parents:
diff changeset
332 // Apple extension for os_log
anatofuz
parents:
diff changeset
333 case 'P':
anatofuz
parents:
diff changeset
334 k = ConversionSpecifier::PArg;
anatofuz
parents:
diff changeset
335 break;
anatofuz
parents:
diff changeset
336 // Objective-C.
anatofuz
parents:
diff changeset
337 case '@': k = ConversionSpecifier::ObjCObjArg; break;
anatofuz
parents:
diff changeset
338 // Glibc specific.
anatofuz
parents:
diff changeset
339 case 'm': k = ConversionSpecifier::PrintErrno; break;
anatofuz
parents:
diff changeset
340 // FreeBSD kernel specific.
anatofuz
parents:
diff changeset
341 case 'b':
anatofuz
parents:
diff changeset
342 if (isFreeBSDKPrintf)
anatofuz
parents:
diff changeset
343 k = ConversionSpecifier::FreeBSDbArg; // int followed by char *
anatofuz
parents:
diff changeset
344 break;
anatofuz
parents:
diff changeset
345 case 'r':
anatofuz
parents:
diff changeset
346 if (isFreeBSDKPrintf)
anatofuz
parents:
diff changeset
347 k = ConversionSpecifier::FreeBSDrArg; // int
anatofuz
parents:
diff changeset
348 break;
anatofuz
parents:
diff changeset
349 case 'y':
anatofuz
parents:
diff changeset
350 if (isFreeBSDKPrintf)
anatofuz
parents:
diff changeset
351 k = ConversionSpecifier::FreeBSDyArg; // int
anatofuz
parents:
diff changeset
352 break;
anatofuz
parents:
diff changeset
353 // Apple-specific.
anatofuz
parents:
diff changeset
354 case 'D':
anatofuz
parents:
diff changeset
355 if (isFreeBSDKPrintf)
anatofuz
parents:
diff changeset
356 k = ConversionSpecifier::FreeBSDDArg; // void * followed by char *
anatofuz
parents:
diff changeset
357 else if (Target.getTriple().isOSDarwin())
anatofuz
parents:
diff changeset
358 k = ConversionSpecifier::DArg;
anatofuz
parents:
diff changeset
359 break;
anatofuz
parents:
diff changeset
360 case 'O':
anatofuz
parents:
diff changeset
361 if (Target.getTriple().isOSDarwin())
anatofuz
parents:
diff changeset
362 k = ConversionSpecifier::OArg;
anatofuz
parents:
diff changeset
363 break;
anatofuz
parents:
diff changeset
364 case 'U':
anatofuz
parents:
diff changeset
365 if (Target.getTriple().isOSDarwin())
anatofuz
parents:
diff changeset
366 k = ConversionSpecifier::UArg;
anatofuz
parents:
diff changeset
367 break;
anatofuz
parents:
diff changeset
368 // MS specific.
anatofuz
parents:
diff changeset
369 case 'Z':
anatofuz
parents:
diff changeset
370 if (Target.getTriple().isOSMSVCRT())
anatofuz
parents:
diff changeset
371 k = ConversionSpecifier::ZArg;
anatofuz
parents:
diff changeset
372 break;
anatofuz
parents:
diff changeset
373 }
anatofuz
parents:
diff changeset
374
anatofuz
parents:
diff changeset
375 // Check to see if we used the Objective-C modifier flags with
anatofuz
parents:
diff changeset
376 // a conversion specifier other than '@'.
anatofuz
parents:
diff changeset
377 if (k != ConversionSpecifier::ObjCObjArg &&
anatofuz
parents:
diff changeset
378 k != ConversionSpecifier::InvalidSpecifier &&
anatofuz
parents:
diff changeset
379 ObjCModifierFlagsStart) {
anatofuz
parents:
diff changeset
380 H.HandleObjCFlagsWithNonObjCConversion(ObjCModifierFlagsStart,
anatofuz
parents:
diff changeset
381 ObjCModifierFlagsEnd + 1,
anatofuz
parents:
diff changeset
382 conversionPosition);
anatofuz
parents:
diff changeset
383 return true;
anatofuz
parents:
diff changeset
384 }
anatofuz
parents:
diff changeset
385
anatofuz
parents:
diff changeset
386 PrintfConversionSpecifier CS(conversionPosition, k);
anatofuz
parents:
diff changeset
387 FS.setConversionSpecifier(CS);
anatofuz
parents:
diff changeset
388 if (CS.consumesDataArgument() && !FS.usesPositionalArg())
anatofuz
parents:
diff changeset
389 FS.setArgIndex(argIndex++);
anatofuz
parents:
diff changeset
390 // FreeBSD kernel specific.
anatofuz
parents:
diff changeset
391 if (k == ConversionSpecifier::FreeBSDbArg ||
anatofuz
parents:
diff changeset
392 k == ConversionSpecifier::FreeBSDDArg)
anatofuz
parents:
diff changeset
393 argIndex++;
anatofuz
parents:
diff changeset
394
anatofuz
parents:
diff changeset
395 if (k == ConversionSpecifier::InvalidSpecifier) {
anatofuz
parents:
diff changeset
396 unsigned Len = I - Start;
anatofuz
parents:
diff changeset
397 if (ParseUTF8InvalidSpecifier(Start, E, Len)) {
anatofuz
parents:
diff changeset
398 CS.setEndScanList(Start + Len);
anatofuz
parents:
diff changeset
399 FS.setConversionSpecifier(CS);
anatofuz
parents:
diff changeset
400 }
anatofuz
parents:
diff changeset
401 // Assume the conversion takes one argument.
anatofuz
parents:
diff changeset
402 return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, Len);
anatofuz
parents:
diff changeset
403 }
anatofuz
parents:
diff changeset
404 return PrintfSpecifierResult(Start, FS);
anatofuz
parents:
diff changeset
405 }
anatofuz
parents:
diff changeset
406
anatofuz
parents:
diff changeset
407 bool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H,
anatofuz
parents:
diff changeset
408 const char *I,
anatofuz
parents:
diff changeset
409 const char *E,
anatofuz
parents:
diff changeset
410 const LangOptions &LO,
anatofuz
parents:
diff changeset
411 const TargetInfo &Target,
anatofuz
parents:
diff changeset
412 bool isFreeBSDKPrintf) {
anatofuz
parents:
diff changeset
413
anatofuz
parents:
diff changeset
414 unsigned argIndex = 0;
anatofuz
parents:
diff changeset
415
anatofuz
parents:
diff changeset
416 // Keep looking for a format specifier until we have exhausted the string.
anatofuz
parents:
diff changeset
417 while (I != E) {
anatofuz
parents:
diff changeset
418 const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
anatofuz
parents:
diff changeset
419 LO, Target, true,
anatofuz
parents:
diff changeset
420 isFreeBSDKPrintf);
anatofuz
parents:
diff changeset
421 // Did a fail-stop error of any kind occur when parsing the specifier?
anatofuz
parents:
diff changeset
422 // If so, don't do any more processing.
anatofuz
parents:
diff changeset
423 if (FSR.shouldStop())
anatofuz
parents:
diff changeset
424 return true;
anatofuz
parents:
diff changeset
425 // Did we exhaust the string or encounter an error that
anatofuz
parents:
diff changeset
426 // we can recover from?
anatofuz
parents:
diff changeset
427 if (!FSR.hasValue())
anatofuz
parents:
diff changeset
428 continue;
anatofuz
parents:
diff changeset
429 // We have a format specifier. Pass it to the callback.
anatofuz
parents:
diff changeset
430 if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),
anatofuz
parents:
diff changeset
431 I - FSR.getStart()))
anatofuz
parents:
diff changeset
432 return true;
anatofuz
parents:
diff changeset
433 }
anatofuz
parents:
diff changeset
434 assert(I == E && "Format string not exhausted");
anatofuz
parents:
diff changeset
435 return false;
anatofuz
parents:
diff changeset
436 }
anatofuz
parents:
diff changeset
437
anatofuz
parents:
diff changeset
438 bool clang::analyze_format_string::ParseFormatStringHasSArg(const char *I,
anatofuz
parents:
diff changeset
439 const char *E,
anatofuz
parents:
diff changeset
440 const LangOptions &LO,
anatofuz
parents:
diff changeset
441 const TargetInfo &Target) {
anatofuz
parents:
diff changeset
442
anatofuz
parents:
diff changeset
443 unsigned argIndex = 0;
anatofuz
parents:
diff changeset
444
anatofuz
parents:
diff changeset
445 // Keep looking for a %s format specifier until we have exhausted the string.
anatofuz
parents:
diff changeset
446 FormatStringHandler H;
anatofuz
parents:
diff changeset
447 while (I != E) {
anatofuz
parents:
diff changeset
448 const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
anatofuz
parents:
diff changeset
449 LO, Target, false,
anatofuz
parents:
diff changeset
450 false);
anatofuz
parents:
diff changeset
451 // Did a fail-stop error of any kind occur when parsing the specifier?
anatofuz
parents:
diff changeset
452 // If so, don't do any more processing.
anatofuz
parents:
diff changeset
453 if (FSR.shouldStop())
anatofuz
parents:
diff changeset
454 return false;
anatofuz
parents:
diff changeset
455 // Did we exhaust the string or encounter an error that
anatofuz
parents:
diff changeset
456 // we can recover from?
anatofuz
parents:
diff changeset
457 if (!FSR.hasValue())
anatofuz
parents:
diff changeset
458 continue;
anatofuz
parents:
diff changeset
459 const analyze_printf::PrintfSpecifier &FS = FSR.getValue();
anatofuz
parents:
diff changeset
460 // Return true if this a %s format specifier.
anatofuz
parents:
diff changeset
461 if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::Kind::sArg)
anatofuz
parents:
diff changeset
462 return true;
anatofuz
parents:
diff changeset
463 }
anatofuz
parents:
diff changeset
464 return false;
anatofuz
parents:
diff changeset
465 }
anatofuz
parents:
diff changeset
466
anatofuz
parents:
diff changeset
467 bool clang::analyze_format_string::parseFormatStringHasFormattingSpecifiers(
anatofuz
parents:
diff changeset
468 const char *Begin, const char *End, const LangOptions &LO,
anatofuz
parents:
diff changeset
469 const TargetInfo &Target) {
anatofuz
parents:
diff changeset
470 unsigned ArgIndex = 0;
anatofuz
parents:
diff changeset
471 // Keep looking for a formatting specifier until we have exhausted the string.
anatofuz
parents:
diff changeset
472 FormatStringHandler H;
anatofuz
parents:
diff changeset
473 while (Begin != End) {
anatofuz
parents:
diff changeset
474 const PrintfSpecifierResult &FSR =
anatofuz
parents:
diff changeset
475 ParsePrintfSpecifier(H, Begin, End, ArgIndex, LO, Target, false, false);
anatofuz
parents:
diff changeset
476 if (FSR.shouldStop())
anatofuz
parents:
diff changeset
477 break;
anatofuz
parents:
diff changeset
478 if (FSR.hasValue())
anatofuz
parents:
diff changeset
479 return true;
anatofuz
parents:
diff changeset
480 }
anatofuz
parents:
diff changeset
481 return false;
anatofuz
parents:
diff changeset
482 }
anatofuz
parents:
diff changeset
483
anatofuz
parents:
diff changeset
484 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
485 // Methods on PrintfSpecifier.
anatofuz
parents:
diff changeset
486 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
487
anatofuz
parents:
diff changeset
488 ArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx,
anatofuz
parents:
diff changeset
489 bool IsObjCLiteral) const {
anatofuz
parents:
diff changeset
490 if (CS.getKind() == ConversionSpecifier::cArg)
anatofuz
parents:
diff changeset
491 switch (LM.getKind()) {
anatofuz
parents:
diff changeset
492 case LengthModifier::None:
anatofuz
parents:
diff changeset
493 return Ctx.IntTy;
anatofuz
parents:
diff changeset
494 case LengthModifier::AsLong:
anatofuz
parents:
diff changeset
495 case LengthModifier::AsWide:
anatofuz
parents:
diff changeset
496 return ArgType(ArgType::WIntTy, "wint_t");
anatofuz
parents:
diff changeset
497 case LengthModifier::AsShort:
anatofuz
parents:
diff changeset
498 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
anatofuz
parents:
diff changeset
499 return Ctx.IntTy;
anatofuz
parents:
diff changeset
500 LLVM_FALLTHROUGH;
anatofuz
parents:
diff changeset
501 default:
anatofuz
parents:
diff changeset
502 return ArgType::Invalid();
anatofuz
parents:
diff changeset
503 }
anatofuz
parents:
diff changeset
504
anatofuz
parents:
diff changeset
505 if (CS.isIntArg())
anatofuz
parents:
diff changeset
506 switch (LM.getKind()) {
anatofuz
parents:
diff changeset
507 case LengthModifier::AsLongDouble:
anatofuz
parents:
diff changeset
508 // GNU extension.
anatofuz
parents:
diff changeset
509 return Ctx.LongLongTy;
anatofuz
parents:
diff changeset
510 case LengthModifier::None:
anatofuz
parents:
diff changeset
511 case LengthModifier::AsShortLong:
anatofuz
parents:
diff changeset
512 return Ctx.IntTy;
anatofuz
parents:
diff changeset
513 case LengthModifier::AsInt32:
anatofuz
parents:
diff changeset
514 return ArgType(Ctx.IntTy, "__int32");
anatofuz
parents:
diff changeset
515 case LengthModifier::AsChar:
anatofuz
parents:
diff changeset
516 return ArgType::AnyCharTy;
anatofuz
parents:
diff changeset
517 case LengthModifier::AsShort: return Ctx.ShortTy;
anatofuz
parents:
diff changeset
518 case LengthModifier::AsLong: return Ctx.LongTy;
anatofuz
parents:
diff changeset
519 case LengthModifier::AsLongLong:
anatofuz
parents:
diff changeset
520 case LengthModifier::AsQuad:
anatofuz
parents:
diff changeset
521 return Ctx.LongLongTy;
anatofuz
parents:
diff changeset
522 case LengthModifier::AsInt64:
anatofuz
parents:
diff changeset
523 return ArgType(Ctx.LongLongTy, "__int64");
anatofuz
parents:
diff changeset
524 case LengthModifier::AsIntMax:
anatofuz
parents:
diff changeset
525 return ArgType(Ctx.getIntMaxType(), "intmax_t");
anatofuz
parents:
diff changeset
526 case LengthModifier::AsSizeT:
anatofuz
parents:
diff changeset
527 return ArgType::makeSizeT(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
anatofuz
parents:
diff changeset
528 case LengthModifier::AsInt3264:
anatofuz
parents:
diff changeset
529 return Ctx.getTargetInfo().getTriple().isArch64Bit()
anatofuz
parents:
diff changeset
530 ? ArgType(Ctx.LongLongTy, "__int64")
anatofuz
parents:
diff changeset
531 : ArgType(Ctx.IntTy, "__int32");
anatofuz
parents:
diff changeset
532 case LengthModifier::AsPtrDiff:
anatofuz
parents:
diff changeset
533 return ArgType::makePtrdiffT(
anatofuz
parents:
diff changeset
534 ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
anatofuz
parents:
diff changeset
535 case LengthModifier::AsAllocate:
anatofuz
parents:
diff changeset
536 case LengthModifier::AsMAllocate:
anatofuz
parents:
diff changeset
537 case LengthModifier::AsWide:
anatofuz
parents:
diff changeset
538 return ArgType::Invalid();
anatofuz
parents:
diff changeset
539 }
anatofuz
parents:
diff changeset
540
anatofuz
parents:
diff changeset
541 if (CS.isUIntArg())
anatofuz
parents:
diff changeset
542 switch (LM.getKind()) {
anatofuz
parents:
diff changeset
543 case LengthModifier::AsLongDouble:
anatofuz
parents:
diff changeset
544 // GNU extension.
anatofuz
parents:
diff changeset
545 return Ctx.UnsignedLongLongTy;
anatofuz
parents:
diff changeset
546 case LengthModifier::None:
anatofuz
parents:
diff changeset
547 case LengthModifier::AsShortLong:
anatofuz
parents:
diff changeset
548 return Ctx.UnsignedIntTy;
anatofuz
parents:
diff changeset
549 case LengthModifier::AsInt32:
anatofuz
parents:
diff changeset
550 return ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
anatofuz
parents:
diff changeset
551 case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
anatofuz
parents:
diff changeset
552 case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
anatofuz
parents:
diff changeset
553 case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
anatofuz
parents:
diff changeset
554 case LengthModifier::AsLongLong:
anatofuz
parents:
diff changeset
555 case LengthModifier::AsQuad:
anatofuz
parents:
diff changeset
556 return Ctx.UnsignedLongLongTy;
anatofuz
parents:
diff changeset
557 case LengthModifier::AsInt64:
anatofuz
parents:
diff changeset
558 return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64");
anatofuz
parents:
diff changeset
559 case LengthModifier::AsIntMax:
anatofuz
parents:
diff changeset
560 return ArgType(Ctx.getUIntMaxType(), "uintmax_t");
anatofuz
parents:
diff changeset
561 case LengthModifier::AsSizeT:
anatofuz
parents:
diff changeset
562 return ArgType::makeSizeT(ArgType(Ctx.getSizeType(), "size_t"));
anatofuz
parents:
diff changeset
563 case LengthModifier::AsInt3264:
anatofuz
parents:
diff changeset
564 return Ctx.getTargetInfo().getTriple().isArch64Bit()
anatofuz
parents:
diff changeset
565 ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")
anatofuz
parents:
diff changeset
566 : ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
anatofuz
parents:
diff changeset
567 case LengthModifier::AsPtrDiff:
anatofuz
parents:
diff changeset
568 return ArgType::makePtrdiffT(
anatofuz
parents:
diff changeset
569 ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"));
anatofuz
parents:
diff changeset
570 case LengthModifier::AsAllocate:
anatofuz
parents:
diff changeset
571 case LengthModifier::AsMAllocate:
anatofuz
parents:
diff changeset
572 case LengthModifier::AsWide:
anatofuz
parents:
diff changeset
573 return ArgType::Invalid();
anatofuz
parents:
diff changeset
574 }
anatofuz
parents:
diff changeset
575
anatofuz
parents:
diff changeset
576 if (CS.isDoubleArg()) {
anatofuz
parents:
diff changeset
577 if (!VectorNumElts.isInvalid()) {
anatofuz
parents:
diff changeset
578 switch (LM.getKind()) {
anatofuz
parents:
diff changeset
579 case LengthModifier::AsShort:
anatofuz
parents:
diff changeset
580 return Ctx.HalfTy;
anatofuz
parents:
diff changeset
581 case LengthModifier::AsShortLong:
anatofuz
parents:
diff changeset
582 return Ctx.FloatTy;
anatofuz
parents:
diff changeset
583 case LengthModifier::AsLong:
anatofuz
parents:
diff changeset
584 default:
anatofuz
parents:
diff changeset
585 return Ctx.DoubleTy;
anatofuz
parents:
diff changeset
586 }
anatofuz
parents:
diff changeset
587 }
anatofuz
parents:
diff changeset
588
anatofuz
parents:
diff changeset
589 if (LM.getKind() == LengthModifier::AsLongDouble)
anatofuz
parents:
diff changeset
590 return Ctx.LongDoubleTy;
anatofuz
parents:
diff changeset
591 return Ctx.DoubleTy;
anatofuz
parents:
diff changeset
592 }
anatofuz
parents:
diff changeset
593
anatofuz
parents:
diff changeset
594 if (CS.getKind() == ConversionSpecifier::nArg) {
anatofuz
parents:
diff changeset
595 switch (LM.getKind()) {
anatofuz
parents:
diff changeset
596 case LengthModifier::None:
anatofuz
parents:
diff changeset
597 return ArgType::PtrTo(Ctx.IntTy);
anatofuz
parents:
diff changeset
598 case LengthModifier::AsChar:
anatofuz
parents:
diff changeset
599 return ArgType::PtrTo(Ctx.SignedCharTy);
anatofuz
parents:
diff changeset
600 case LengthModifier::AsShort:
anatofuz
parents:
diff changeset
601 return ArgType::PtrTo(Ctx.ShortTy);
anatofuz
parents:
diff changeset
602 case LengthModifier::AsLong:
anatofuz
parents:
diff changeset
603 return ArgType::PtrTo(Ctx.LongTy);
anatofuz
parents:
diff changeset
604 case LengthModifier::AsLongLong:
anatofuz
parents:
diff changeset
605 case LengthModifier::AsQuad:
anatofuz
parents:
diff changeset
606 return ArgType::PtrTo(Ctx.LongLongTy);
anatofuz
parents:
diff changeset
607 case LengthModifier::AsIntMax:
anatofuz
parents:
diff changeset
608 return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
anatofuz
parents:
diff changeset
609 case LengthModifier::AsSizeT:
anatofuz
parents:
diff changeset
610 return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
anatofuz
parents:
diff changeset
611 case LengthModifier::AsPtrDiff:
anatofuz
parents:
diff changeset
612 return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
anatofuz
parents:
diff changeset
613 case LengthModifier::AsLongDouble:
anatofuz
parents:
diff changeset
614 return ArgType(); // FIXME: Is this a known extension?
anatofuz
parents:
diff changeset
615 case LengthModifier::AsAllocate:
anatofuz
parents:
diff changeset
616 case LengthModifier::AsMAllocate:
anatofuz
parents:
diff changeset
617 case LengthModifier::AsInt32:
anatofuz
parents:
diff changeset
618 case LengthModifier::AsInt3264:
anatofuz
parents:
diff changeset
619 case LengthModifier::AsInt64:
anatofuz
parents:
diff changeset
620 case LengthModifier::AsWide:
anatofuz
parents:
diff changeset
621 return ArgType::Invalid();
anatofuz
parents:
diff changeset
622 case LengthModifier::AsShortLong:
anatofuz
parents:
diff changeset
623 llvm_unreachable("only used for OpenCL which doesn not handle nArg");
anatofuz
parents:
diff changeset
624 }
anatofuz
parents:
diff changeset
625 }
anatofuz
parents:
diff changeset
626
anatofuz
parents:
diff changeset
627 switch (CS.getKind()) {
anatofuz
parents:
diff changeset
628 case ConversionSpecifier::sArg:
anatofuz
parents:
diff changeset
629 if (LM.getKind() == LengthModifier::AsWideChar) {
anatofuz
parents:
diff changeset
630 if (IsObjCLiteral)
anatofuz
parents:
diff changeset
631 return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
anatofuz
parents:
diff changeset
632 "const unichar *");
anatofuz
parents:
diff changeset
633 return ArgType(ArgType::WCStrTy, "wchar_t *");
anatofuz
parents:
diff changeset
634 }
anatofuz
parents:
diff changeset
635 if (LM.getKind() == LengthModifier::AsWide)
anatofuz
parents:
diff changeset
636 return ArgType(ArgType::WCStrTy, "wchar_t *");
anatofuz
parents:
diff changeset
637 return ArgType::CStrTy;
anatofuz
parents:
diff changeset
638 case ConversionSpecifier::SArg:
anatofuz
parents:
diff changeset
639 if (IsObjCLiteral)
anatofuz
parents:
diff changeset
640 return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
anatofuz
parents:
diff changeset
641 "const unichar *");
anatofuz
parents:
diff changeset
642 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
anatofuz
parents:
diff changeset
643 LM.getKind() == LengthModifier::AsShort)
anatofuz
parents:
diff changeset
644 return ArgType::CStrTy;
anatofuz
parents:
diff changeset
645 return ArgType(ArgType::WCStrTy, "wchar_t *");
anatofuz
parents:
diff changeset
646 case ConversionSpecifier::CArg:
anatofuz
parents:
diff changeset
647 if (IsObjCLiteral)
anatofuz
parents:
diff changeset
648 return ArgType(Ctx.UnsignedShortTy, "unichar");
anatofuz
parents:
diff changeset
649 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
anatofuz
parents:
diff changeset
650 LM.getKind() == LengthModifier::AsShort)
anatofuz
parents:
diff changeset
651 return Ctx.IntTy;
anatofuz
parents:
diff changeset
652 return ArgType(Ctx.WideCharTy, "wchar_t");
anatofuz
parents:
diff changeset
653 case ConversionSpecifier::pArg:
anatofuz
parents:
diff changeset
654 case ConversionSpecifier::PArg:
anatofuz
parents:
diff changeset
655 return ArgType::CPointerTy;
anatofuz
parents:
diff changeset
656 case ConversionSpecifier::ObjCObjArg:
anatofuz
parents:
diff changeset
657 return ArgType::ObjCPointerTy;
anatofuz
parents:
diff changeset
658 default:
anatofuz
parents:
diff changeset
659 break;
anatofuz
parents:
diff changeset
660 }
anatofuz
parents:
diff changeset
661
anatofuz
parents:
diff changeset
662 // FIXME: Handle other cases.
anatofuz
parents:
diff changeset
663 return ArgType();
anatofuz
parents:
diff changeset
664 }
anatofuz
parents:
diff changeset
665
anatofuz
parents:
diff changeset
666
anatofuz
parents:
diff changeset
667 ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
anatofuz
parents:
diff changeset
668 bool IsObjCLiteral) const {
anatofuz
parents:
diff changeset
669 const PrintfConversionSpecifier &CS = getConversionSpecifier();
anatofuz
parents:
diff changeset
670
anatofuz
parents:
diff changeset
671 if (!CS.consumesDataArgument())
anatofuz
parents:
diff changeset
672 return ArgType::Invalid();
anatofuz
parents:
diff changeset
673
anatofuz
parents:
diff changeset
674 ArgType ScalarTy = getScalarArgType(Ctx, IsObjCLiteral);
anatofuz
parents:
diff changeset
675 if (!ScalarTy.isValid() || VectorNumElts.isInvalid())
anatofuz
parents:
diff changeset
676 return ScalarTy;
anatofuz
parents:
diff changeset
677
anatofuz
parents:
diff changeset
678 return ScalarTy.makeVectorType(Ctx, VectorNumElts.getConstantAmount());
anatofuz
parents:
diff changeset
679 }
anatofuz
parents:
diff changeset
680
anatofuz
parents:
diff changeset
681 bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
anatofuz
parents:
diff changeset
682 ASTContext &Ctx, bool IsObjCLiteral) {
anatofuz
parents:
diff changeset
683 // %n is different from other conversion specifiers; don't try to fix it.
anatofuz
parents:
diff changeset
684 if (CS.getKind() == ConversionSpecifier::nArg)
anatofuz
parents:
diff changeset
685 return false;
anatofuz
parents:
diff changeset
686
anatofuz
parents:
diff changeset
687 // Handle Objective-C objects first. Note that while the '%@' specifier will
anatofuz
parents:
diff changeset
688 // not warn for structure pointer or void pointer arguments (because that's
anatofuz
parents:
diff changeset
689 // how CoreFoundation objects are implemented), we only show a fixit for '%@'
anatofuz
parents:
diff changeset
690 // if we know it's an object (block, id, class, or __attribute__((NSObject))).
anatofuz
parents:
diff changeset
691 if (QT->isObjCRetainableType()) {
anatofuz
parents:
diff changeset
692 if (!IsObjCLiteral)
anatofuz
parents:
diff changeset
693 return false;
anatofuz
parents:
diff changeset
694
anatofuz
parents:
diff changeset
695 CS.setKind(ConversionSpecifier::ObjCObjArg);
anatofuz
parents:
diff changeset
696
anatofuz
parents:
diff changeset
697 // Disable irrelevant flags
anatofuz
parents:
diff changeset
698 HasThousandsGrouping = false;
anatofuz
parents:
diff changeset
699 HasPlusPrefix = false;
anatofuz
parents:
diff changeset
700 HasSpacePrefix = false;
anatofuz
parents:
diff changeset
701 HasAlternativeForm = false;
anatofuz
parents:
diff changeset
702 HasLeadingZeroes = false;
anatofuz
parents:
diff changeset
703 Precision.setHowSpecified(OptionalAmount::NotSpecified);
anatofuz
parents:
diff changeset
704 LM.setKind(LengthModifier::None);
anatofuz
parents:
diff changeset
705
anatofuz
parents:
diff changeset
706 return true;
anatofuz
parents:
diff changeset
707 }
anatofuz
parents:
diff changeset
708
anatofuz
parents:
diff changeset
709 // Handle strings next (char *, wchar_t *)
anatofuz
parents:
diff changeset
710 if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
anatofuz
parents:
diff changeset
711 CS.setKind(ConversionSpecifier::sArg);
anatofuz
parents:
diff changeset
712
anatofuz
parents:
diff changeset
713 // Disable irrelevant flags
anatofuz
parents:
diff changeset
714 HasAlternativeForm = 0;
anatofuz
parents:
diff changeset
715 HasLeadingZeroes = 0;
anatofuz
parents:
diff changeset
716
anatofuz
parents:
diff changeset
717 // Set the long length modifier for wide characters
anatofuz
parents:
diff changeset
718 if (QT->getPointeeType()->isWideCharType())
anatofuz
parents:
diff changeset
719 LM.setKind(LengthModifier::AsWideChar);
anatofuz
parents:
diff changeset
720 else
anatofuz
parents:
diff changeset
721 LM.setKind(LengthModifier::None);
anatofuz
parents:
diff changeset
722
anatofuz
parents:
diff changeset
723 return true;
anatofuz
parents:
diff changeset
724 }
anatofuz
parents:
diff changeset
725
anatofuz
parents:
diff changeset
726 // If it's an enum, get its underlying type.
anatofuz
parents:
diff changeset
727 if (const EnumType *ETy = QT->getAs<EnumType>())
anatofuz
parents:
diff changeset
728 QT = ETy->getDecl()->getIntegerType();
anatofuz
parents:
diff changeset
729
anatofuz
parents:
diff changeset
730 const BuiltinType *BT = QT->getAs<BuiltinType>();
anatofuz
parents:
diff changeset
731 if (!BT) {
anatofuz
parents:
diff changeset
732 const VectorType *VT = QT->getAs<VectorType>();
anatofuz
parents:
diff changeset
733 if (VT) {
anatofuz
parents:
diff changeset
734 QT = VT->getElementType();
anatofuz
parents:
diff changeset
735 BT = QT->getAs<BuiltinType>();
anatofuz
parents:
diff changeset
736 VectorNumElts = OptionalAmount(VT->getNumElements());
anatofuz
parents:
diff changeset
737 }
anatofuz
parents:
diff changeset
738 }
anatofuz
parents:
diff changeset
739
anatofuz
parents:
diff changeset
740 // We can only work with builtin types.
anatofuz
parents:
diff changeset
741 if (!BT)
anatofuz
parents:
diff changeset
742 return false;
anatofuz
parents:
diff changeset
743
anatofuz
parents:
diff changeset
744 // Set length modifier
anatofuz
parents:
diff changeset
745 switch (BT->getKind()) {
anatofuz
parents:
diff changeset
746 case BuiltinType::Bool:
anatofuz
parents:
diff changeset
747 case BuiltinType::WChar_U:
anatofuz
parents:
diff changeset
748 case BuiltinType::WChar_S:
anatofuz
parents:
diff changeset
749 case BuiltinType::Char8: // FIXME: Treat like 'char'?
anatofuz
parents:
diff changeset
750 case BuiltinType::Char16:
anatofuz
parents:
diff changeset
751 case BuiltinType::Char32:
anatofuz
parents:
diff changeset
752 case BuiltinType::UInt128:
anatofuz
parents:
diff changeset
753 case BuiltinType::Int128:
anatofuz
parents:
diff changeset
754 case BuiltinType::Half:
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
755 case BuiltinType::BFloat16:
150
anatofuz
parents:
diff changeset
756 case BuiltinType::Float16:
anatofuz
parents:
diff changeset
757 case BuiltinType::Float128:
anatofuz
parents:
diff changeset
758 case BuiltinType::ShortAccum:
anatofuz
parents:
diff changeset
759 case BuiltinType::Accum:
anatofuz
parents:
diff changeset
760 case BuiltinType::LongAccum:
anatofuz
parents:
diff changeset
761 case BuiltinType::UShortAccum:
anatofuz
parents:
diff changeset
762 case BuiltinType::UAccum:
anatofuz
parents:
diff changeset
763 case BuiltinType::ULongAccum:
anatofuz
parents:
diff changeset
764 case BuiltinType::ShortFract:
anatofuz
parents:
diff changeset
765 case BuiltinType::Fract:
anatofuz
parents:
diff changeset
766 case BuiltinType::LongFract:
anatofuz
parents:
diff changeset
767 case BuiltinType::UShortFract:
anatofuz
parents:
diff changeset
768 case BuiltinType::UFract:
anatofuz
parents:
diff changeset
769 case BuiltinType::ULongFract:
anatofuz
parents:
diff changeset
770 case BuiltinType::SatShortAccum:
anatofuz
parents:
diff changeset
771 case BuiltinType::SatAccum:
anatofuz
parents:
diff changeset
772 case BuiltinType::SatLongAccum:
anatofuz
parents:
diff changeset
773 case BuiltinType::SatUShortAccum:
anatofuz
parents:
diff changeset
774 case BuiltinType::SatUAccum:
anatofuz
parents:
diff changeset
775 case BuiltinType::SatULongAccum:
anatofuz
parents:
diff changeset
776 case BuiltinType::SatShortFract:
anatofuz
parents:
diff changeset
777 case BuiltinType::SatFract:
anatofuz
parents:
diff changeset
778 case BuiltinType::SatLongFract:
anatofuz
parents:
diff changeset
779 case BuiltinType::SatUShortFract:
anatofuz
parents:
diff changeset
780 case BuiltinType::SatUFract:
anatofuz
parents:
diff changeset
781 case BuiltinType::SatULongFract:
anatofuz
parents:
diff changeset
782 // Various types which are non-trivial to correct.
anatofuz
parents:
diff changeset
783 return false;
anatofuz
parents:
diff changeset
784
anatofuz
parents:
diff changeset
785 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
anatofuz
parents:
diff changeset
786 case BuiltinType::Id:
anatofuz
parents:
diff changeset
787 #include "clang/Basic/OpenCLImageTypes.def"
anatofuz
parents:
diff changeset
788 #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
anatofuz
parents:
diff changeset
789 case BuiltinType::Id:
anatofuz
parents:
diff changeset
790 #include "clang/Basic/OpenCLExtensionTypes.def"
anatofuz
parents:
diff changeset
791 #define SVE_TYPE(Name, Id, SingletonId) \
anatofuz
parents:
diff changeset
792 case BuiltinType::Id:
anatofuz
parents:
diff changeset
793 #include "clang/Basic/AArch64SVEACLETypes.def"
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
794 #define PPC_VECTOR_TYPE(Name, Id, Size) \
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
795 case BuiltinType::Id:
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
796 #include "clang/Basic/PPCTypes.def"
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
797 #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
798 #include "clang/Basic/RISCVVTypes.def"
150
anatofuz
parents:
diff changeset
799 #define SIGNED_TYPE(Id, SingletonId)
anatofuz
parents:
diff changeset
800 #define UNSIGNED_TYPE(Id, SingletonId)
anatofuz
parents:
diff changeset
801 #define FLOATING_TYPE(Id, SingletonId)
anatofuz
parents:
diff changeset
802 #define BUILTIN_TYPE(Id, SingletonId) \
anatofuz
parents:
diff changeset
803 case BuiltinType::Id:
anatofuz
parents:
diff changeset
804 #include "clang/AST/BuiltinTypes.def"
anatofuz
parents:
diff changeset
805 // Misc other stuff which doesn't make sense here.
anatofuz
parents:
diff changeset
806 return false;
anatofuz
parents:
diff changeset
807
anatofuz
parents:
diff changeset
808 case BuiltinType::UInt:
anatofuz
parents:
diff changeset
809 case BuiltinType::Int:
anatofuz
parents:
diff changeset
810 case BuiltinType::Float:
anatofuz
parents:
diff changeset
811 LM.setKind(VectorNumElts.isInvalid() ?
anatofuz
parents:
diff changeset
812 LengthModifier::None : LengthModifier::AsShortLong);
anatofuz
parents:
diff changeset
813 break;
anatofuz
parents:
diff changeset
814 case BuiltinType::Double:
anatofuz
parents:
diff changeset
815 LM.setKind(VectorNumElts.isInvalid() ?
anatofuz
parents:
diff changeset
816 LengthModifier::None : LengthModifier::AsLong);
anatofuz
parents:
diff changeset
817 break;
anatofuz
parents:
diff changeset
818 case BuiltinType::Char_U:
anatofuz
parents:
diff changeset
819 case BuiltinType::UChar:
anatofuz
parents:
diff changeset
820 case BuiltinType::Char_S:
anatofuz
parents:
diff changeset
821 case BuiltinType::SChar:
anatofuz
parents:
diff changeset
822 LM.setKind(LengthModifier::AsChar);
anatofuz
parents:
diff changeset
823 break;
anatofuz
parents:
diff changeset
824
anatofuz
parents:
diff changeset
825 case BuiltinType::Short:
anatofuz
parents:
diff changeset
826 case BuiltinType::UShort:
anatofuz
parents:
diff changeset
827 LM.setKind(LengthModifier::AsShort);
anatofuz
parents:
diff changeset
828 break;
anatofuz
parents:
diff changeset
829
anatofuz
parents:
diff changeset
830 case BuiltinType::Long:
anatofuz
parents:
diff changeset
831 case BuiltinType::ULong:
anatofuz
parents:
diff changeset
832 LM.setKind(LengthModifier::AsLong);
anatofuz
parents:
diff changeset
833 break;
anatofuz
parents:
diff changeset
834
anatofuz
parents:
diff changeset
835 case BuiltinType::LongLong:
anatofuz
parents:
diff changeset
836 case BuiltinType::ULongLong:
anatofuz
parents:
diff changeset
837 LM.setKind(LengthModifier::AsLongLong);
anatofuz
parents:
diff changeset
838 break;
anatofuz
parents:
diff changeset
839
anatofuz
parents:
diff changeset
840 case BuiltinType::LongDouble:
anatofuz
parents:
diff changeset
841 LM.setKind(LengthModifier::AsLongDouble);
anatofuz
parents:
diff changeset
842 break;
anatofuz
parents:
diff changeset
843 }
anatofuz
parents:
diff changeset
844
anatofuz
parents:
diff changeset
845 // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
anatofuz
parents:
diff changeset
846 if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11))
anatofuz
parents:
diff changeset
847 namedTypeToLengthModifier(QT, LM);
anatofuz
parents:
diff changeset
848
anatofuz
parents:
diff changeset
849 // If fixing the length modifier was enough, we might be done.
anatofuz
parents:
diff changeset
850 if (hasValidLengthModifier(Ctx.getTargetInfo(), LangOpt)) {
anatofuz
parents:
diff changeset
851 // If we're going to offer a fix anyway, make sure the sign matches.
anatofuz
parents:
diff changeset
852 switch (CS.getKind()) {
anatofuz
parents:
diff changeset
853 case ConversionSpecifier::uArg:
anatofuz
parents:
diff changeset
854 case ConversionSpecifier::UArg:
anatofuz
parents:
diff changeset
855 if (QT->isSignedIntegerType())
anatofuz
parents:
diff changeset
856 CS.setKind(clang::analyze_format_string::ConversionSpecifier::dArg);
anatofuz
parents:
diff changeset
857 break;
anatofuz
parents:
diff changeset
858 case ConversionSpecifier::dArg:
anatofuz
parents:
diff changeset
859 case ConversionSpecifier::DArg:
anatofuz
parents:
diff changeset
860 case ConversionSpecifier::iArg:
anatofuz
parents:
diff changeset
861 if (QT->isUnsignedIntegerType() && !HasPlusPrefix)
anatofuz
parents:
diff changeset
862 CS.setKind(clang::analyze_format_string::ConversionSpecifier::uArg);
anatofuz
parents:
diff changeset
863 break;
anatofuz
parents:
diff changeset
864 default:
anatofuz
parents:
diff changeset
865 // Other specifiers do not have signed/unsigned variants.
anatofuz
parents:
diff changeset
866 break;
anatofuz
parents:
diff changeset
867 }
anatofuz
parents:
diff changeset
868
anatofuz
parents:
diff changeset
869 const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral);
anatofuz
parents:
diff changeset
870 if (ATR.isValid() && ATR.matchesType(Ctx, QT))
anatofuz
parents:
diff changeset
871 return true;
anatofuz
parents:
diff changeset
872 }
anatofuz
parents:
diff changeset
873
anatofuz
parents:
diff changeset
874 // Set conversion specifier and disable any flags which do not apply to it.
anatofuz
parents:
diff changeset
875 // Let typedefs to char fall through to int, as %c is silly for uint8_t.
anatofuz
parents:
diff changeset
876 if (!isa<TypedefType>(QT) && QT->isCharType()) {
anatofuz
parents:
diff changeset
877 CS.setKind(ConversionSpecifier::cArg);
anatofuz
parents:
diff changeset
878 LM.setKind(LengthModifier::None);
anatofuz
parents:
diff changeset
879 Precision.setHowSpecified(OptionalAmount::NotSpecified);
anatofuz
parents:
diff changeset
880 HasAlternativeForm = 0;
anatofuz
parents:
diff changeset
881 HasLeadingZeroes = 0;
anatofuz
parents:
diff changeset
882 HasPlusPrefix = 0;
anatofuz
parents:
diff changeset
883 }
anatofuz
parents:
diff changeset
884 // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
anatofuz
parents:
diff changeset
885 else if (QT->isRealFloatingType()) {
anatofuz
parents:
diff changeset
886 CS.setKind(ConversionSpecifier::fArg);
anatofuz
parents:
diff changeset
887 }
anatofuz
parents:
diff changeset
888 else if (QT->isSignedIntegerType()) {
anatofuz
parents:
diff changeset
889 CS.setKind(ConversionSpecifier::dArg);
anatofuz
parents:
diff changeset
890 HasAlternativeForm = 0;
anatofuz
parents:
diff changeset
891 }
anatofuz
parents:
diff changeset
892 else if (QT->isUnsignedIntegerType()) {
anatofuz
parents:
diff changeset
893 CS.setKind(ConversionSpecifier::uArg);
anatofuz
parents:
diff changeset
894 HasAlternativeForm = 0;
anatofuz
parents:
diff changeset
895 HasPlusPrefix = 0;
anatofuz
parents:
diff changeset
896 } else {
anatofuz
parents:
diff changeset
897 llvm_unreachable("Unexpected type");
anatofuz
parents:
diff changeset
898 }
anatofuz
parents:
diff changeset
899
anatofuz
parents:
diff changeset
900 return true;
anatofuz
parents:
diff changeset
901 }
anatofuz
parents:
diff changeset
902
anatofuz
parents:
diff changeset
903 void PrintfSpecifier::toString(raw_ostream &os) const {
anatofuz
parents:
diff changeset
904 // Whilst some features have no defined order, we are using the order
anatofuz
parents:
diff changeset
905 // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
anatofuz
parents:
diff changeset
906 os << "%";
anatofuz
parents:
diff changeset
907
anatofuz
parents:
diff changeset
908 // Positional args
anatofuz
parents:
diff changeset
909 if (usesPositionalArg()) {
anatofuz
parents:
diff changeset
910 os << getPositionalArgIndex() << "$";
anatofuz
parents:
diff changeset
911 }
anatofuz
parents:
diff changeset
912
anatofuz
parents:
diff changeset
913 // Conversion flags
anatofuz
parents:
diff changeset
914 if (IsLeftJustified) os << "-";
anatofuz
parents:
diff changeset
915 if (HasPlusPrefix) os << "+";
anatofuz
parents:
diff changeset
916 if (HasSpacePrefix) os << " ";
anatofuz
parents:
diff changeset
917 if (HasAlternativeForm) os << "#";
anatofuz
parents:
diff changeset
918 if (HasLeadingZeroes) os << "0";
anatofuz
parents:
diff changeset
919
anatofuz
parents:
diff changeset
920 // Minimum field width
anatofuz
parents:
diff changeset
921 FieldWidth.toString(os);
anatofuz
parents:
diff changeset
922 // Precision
anatofuz
parents:
diff changeset
923 Precision.toString(os);
anatofuz
parents:
diff changeset
924
anatofuz
parents:
diff changeset
925 // Vector modifier
anatofuz
parents:
diff changeset
926 if (!VectorNumElts.isInvalid())
anatofuz
parents:
diff changeset
927 os << 'v' << VectorNumElts.getConstantAmount();
anatofuz
parents:
diff changeset
928
anatofuz
parents:
diff changeset
929 // Length modifier
anatofuz
parents:
diff changeset
930 os << LM.toString();
anatofuz
parents:
diff changeset
931 // Conversion specifier
anatofuz
parents:
diff changeset
932 os << CS.toString();
anatofuz
parents:
diff changeset
933 }
anatofuz
parents:
diff changeset
934
anatofuz
parents:
diff changeset
935 bool PrintfSpecifier::hasValidPlusPrefix() const {
anatofuz
parents:
diff changeset
936 if (!HasPlusPrefix)
anatofuz
parents:
diff changeset
937 return true;
anatofuz
parents:
diff changeset
938
anatofuz
parents:
diff changeset
939 // The plus prefix only makes sense for signed conversions
anatofuz
parents:
diff changeset
940 switch (CS.getKind()) {
anatofuz
parents:
diff changeset
941 case ConversionSpecifier::dArg:
anatofuz
parents:
diff changeset
942 case ConversionSpecifier::DArg:
anatofuz
parents:
diff changeset
943 case ConversionSpecifier::iArg:
anatofuz
parents:
diff changeset
944 case ConversionSpecifier::fArg:
anatofuz
parents:
diff changeset
945 case ConversionSpecifier::FArg:
anatofuz
parents:
diff changeset
946 case ConversionSpecifier::eArg:
anatofuz
parents:
diff changeset
947 case ConversionSpecifier::EArg:
anatofuz
parents:
diff changeset
948 case ConversionSpecifier::gArg:
anatofuz
parents:
diff changeset
949 case ConversionSpecifier::GArg:
anatofuz
parents:
diff changeset
950 case ConversionSpecifier::aArg:
anatofuz
parents:
diff changeset
951 case ConversionSpecifier::AArg:
anatofuz
parents:
diff changeset
952 case ConversionSpecifier::FreeBSDrArg:
anatofuz
parents:
diff changeset
953 case ConversionSpecifier::FreeBSDyArg:
anatofuz
parents:
diff changeset
954 return true;
anatofuz
parents:
diff changeset
955
anatofuz
parents:
diff changeset
956 default:
anatofuz
parents:
diff changeset
957 return false;
anatofuz
parents:
diff changeset
958 }
anatofuz
parents:
diff changeset
959 }
anatofuz
parents:
diff changeset
960
anatofuz
parents:
diff changeset
961 bool PrintfSpecifier::hasValidAlternativeForm() const {
anatofuz
parents:
diff changeset
962 if (!HasAlternativeForm)
anatofuz
parents:
diff changeset
963 return true;
anatofuz
parents:
diff changeset
964
anatofuz
parents:
diff changeset
965 // Alternate form flag only valid with the oxXaAeEfFgG conversions
anatofuz
parents:
diff changeset
966 switch (CS.getKind()) {
anatofuz
parents:
diff changeset
967 case ConversionSpecifier::oArg:
anatofuz
parents:
diff changeset
968 case ConversionSpecifier::OArg:
anatofuz
parents:
diff changeset
969 case ConversionSpecifier::xArg:
anatofuz
parents:
diff changeset
970 case ConversionSpecifier::XArg:
anatofuz
parents:
diff changeset
971 case ConversionSpecifier::aArg:
anatofuz
parents:
diff changeset
972 case ConversionSpecifier::AArg:
anatofuz
parents:
diff changeset
973 case ConversionSpecifier::eArg:
anatofuz
parents:
diff changeset
974 case ConversionSpecifier::EArg:
anatofuz
parents:
diff changeset
975 case ConversionSpecifier::fArg:
anatofuz
parents:
diff changeset
976 case ConversionSpecifier::FArg:
anatofuz
parents:
diff changeset
977 case ConversionSpecifier::gArg:
anatofuz
parents:
diff changeset
978 case ConversionSpecifier::GArg:
anatofuz
parents:
diff changeset
979 case ConversionSpecifier::FreeBSDrArg:
anatofuz
parents:
diff changeset
980 case ConversionSpecifier::FreeBSDyArg:
anatofuz
parents:
diff changeset
981 return true;
anatofuz
parents:
diff changeset
982
anatofuz
parents:
diff changeset
983 default:
anatofuz
parents:
diff changeset
984 return false;
anatofuz
parents:
diff changeset
985 }
anatofuz
parents:
diff changeset
986 }
anatofuz
parents:
diff changeset
987
anatofuz
parents:
diff changeset
988 bool PrintfSpecifier::hasValidLeadingZeros() const {
anatofuz
parents:
diff changeset
989 if (!HasLeadingZeroes)
anatofuz
parents:
diff changeset
990 return true;
anatofuz
parents:
diff changeset
991
anatofuz
parents:
diff changeset
992 // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
anatofuz
parents:
diff changeset
993 switch (CS.getKind()) {
anatofuz
parents:
diff changeset
994 case ConversionSpecifier::dArg:
anatofuz
parents:
diff changeset
995 case ConversionSpecifier::DArg:
anatofuz
parents:
diff changeset
996 case ConversionSpecifier::iArg:
anatofuz
parents:
diff changeset
997 case ConversionSpecifier::oArg:
anatofuz
parents:
diff changeset
998 case ConversionSpecifier::OArg:
anatofuz
parents:
diff changeset
999 case ConversionSpecifier::uArg:
anatofuz
parents:
diff changeset
1000 case ConversionSpecifier::UArg:
anatofuz
parents:
diff changeset
1001 case ConversionSpecifier::xArg:
anatofuz
parents:
diff changeset
1002 case ConversionSpecifier::XArg:
anatofuz
parents:
diff changeset
1003 case ConversionSpecifier::aArg:
anatofuz
parents:
diff changeset
1004 case ConversionSpecifier::AArg:
anatofuz
parents:
diff changeset
1005 case ConversionSpecifier::eArg:
anatofuz
parents:
diff changeset
1006 case ConversionSpecifier::EArg:
anatofuz
parents:
diff changeset
1007 case ConversionSpecifier::fArg:
anatofuz
parents:
diff changeset
1008 case ConversionSpecifier::FArg:
anatofuz
parents:
diff changeset
1009 case ConversionSpecifier::gArg:
anatofuz
parents:
diff changeset
1010 case ConversionSpecifier::GArg:
anatofuz
parents:
diff changeset
1011 case ConversionSpecifier::FreeBSDrArg:
anatofuz
parents:
diff changeset
1012 case ConversionSpecifier::FreeBSDyArg:
anatofuz
parents:
diff changeset
1013 return true;
anatofuz
parents:
diff changeset
1014
anatofuz
parents:
diff changeset
1015 default:
anatofuz
parents:
diff changeset
1016 return false;
anatofuz
parents:
diff changeset
1017 }
anatofuz
parents:
diff changeset
1018 }
anatofuz
parents:
diff changeset
1019
anatofuz
parents:
diff changeset
1020 bool PrintfSpecifier::hasValidSpacePrefix() const {
anatofuz
parents:
diff changeset
1021 if (!HasSpacePrefix)
anatofuz
parents:
diff changeset
1022 return true;
anatofuz
parents:
diff changeset
1023
anatofuz
parents:
diff changeset
1024 // The space prefix only makes sense for signed conversions
anatofuz
parents:
diff changeset
1025 switch (CS.getKind()) {
anatofuz
parents:
diff changeset
1026 case ConversionSpecifier::dArg:
anatofuz
parents:
diff changeset
1027 case ConversionSpecifier::DArg:
anatofuz
parents:
diff changeset
1028 case ConversionSpecifier::iArg:
anatofuz
parents:
diff changeset
1029 case ConversionSpecifier::fArg:
anatofuz
parents:
diff changeset
1030 case ConversionSpecifier::FArg:
anatofuz
parents:
diff changeset
1031 case ConversionSpecifier::eArg:
anatofuz
parents:
diff changeset
1032 case ConversionSpecifier::EArg:
anatofuz
parents:
diff changeset
1033 case ConversionSpecifier::gArg:
anatofuz
parents:
diff changeset
1034 case ConversionSpecifier::GArg:
anatofuz
parents:
diff changeset
1035 case ConversionSpecifier::aArg:
anatofuz
parents:
diff changeset
1036 case ConversionSpecifier::AArg:
anatofuz
parents:
diff changeset
1037 case ConversionSpecifier::FreeBSDrArg:
anatofuz
parents:
diff changeset
1038 case ConversionSpecifier::FreeBSDyArg:
anatofuz
parents:
diff changeset
1039 return true;
anatofuz
parents:
diff changeset
1040
anatofuz
parents:
diff changeset
1041 default:
anatofuz
parents:
diff changeset
1042 return false;
anatofuz
parents:
diff changeset
1043 }
anatofuz
parents:
diff changeset
1044 }
anatofuz
parents:
diff changeset
1045
anatofuz
parents:
diff changeset
1046 bool PrintfSpecifier::hasValidLeftJustified() const {
anatofuz
parents:
diff changeset
1047 if (!IsLeftJustified)
anatofuz
parents:
diff changeset
1048 return true;
anatofuz
parents:
diff changeset
1049
anatofuz
parents:
diff changeset
1050 // The left justified flag is valid for all conversions except n
anatofuz
parents:
diff changeset
1051 switch (CS.getKind()) {
anatofuz
parents:
diff changeset
1052 case ConversionSpecifier::nArg:
anatofuz
parents:
diff changeset
1053 return false;
anatofuz
parents:
diff changeset
1054
anatofuz
parents:
diff changeset
1055 default:
anatofuz
parents:
diff changeset
1056 return true;
anatofuz
parents:
diff changeset
1057 }
anatofuz
parents:
diff changeset
1058 }
anatofuz
parents:
diff changeset
1059
anatofuz
parents:
diff changeset
1060 bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
anatofuz
parents:
diff changeset
1061 if (!HasThousandsGrouping)
anatofuz
parents:
diff changeset
1062 return true;
anatofuz
parents:
diff changeset
1063
anatofuz
parents:
diff changeset
1064 switch (CS.getKind()) {
anatofuz
parents:
diff changeset
1065 case ConversionSpecifier::dArg:
anatofuz
parents:
diff changeset
1066 case ConversionSpecifier::DArg:
anatofuz
parents:
diff changeset
1067 case ConversionSpecifier::iArg:
anatofuz
parents:
diff changeset
1068 case ConversionSpecifier::uArg:
anatofuz
parents:
diff changeset
1069 case ConversionSpecifier::UArg:
anatofuz
parents:
diff changeset
1070 case ConversionSpecifier::fArg:
anatofuz
parents:
diff changeset
1071 case ConversionSpecifier::FArg:
anatofuz
parents:
diff changeset
1072 case ConversionSpecifier::gArg:
anatofuz
parents:
diff changeset
1073 case ConversionSpecifier::GArg:
anatofuz
parents:
diff changeset
1074 return true;
anatofuz
parents:
diff changeset
1075 default:
anatofuz
parents:
diff changeset
1076 return false;
anatofuz
parents:
diff changeset
1077 }
anatofuz
parents:
diff changeset
1078 }
anatofuz
parents:
diff changeset
1079
anatofuz
parents:
diff changeset
1080 bool PrintfSpecifier::hasValidPrecision() const {
anatofuz
parents:
diff changeset
1081 if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
anatofuz
parents:
diff changeset
1082 return true;
anatofuz
parents:
diff changeset
1083
anatofuz
parents:
diff changeset
1084 // Precision is only valid with the diouxXaAeEfFgGsP conversions
anatofuz
parents:
diff changeset
1085 switch (CS.getKind()) {
anatofuz
parents:
diff changeset
1086 case ConversionSpecifier::dArg:
anatofuz
parents:
diff changeset
1087 case ConversionSpecifier::DArg:
anatofuz
parents:
diff changeset
1088 case ConversionSpecifier::iArg:
anatofuz
parents:
diff changeset
1089 case ConversionSpecifier::oArg:
anatofuz
parents:
diff changeset
1090 case ConversionSpecifier::OArg:
anatofuz
parents:
diff changeset
1091 case ConversionSpecifier::uArg:
anatofuz
parents:
diff changeset
1092 case ConversionSpecifier::UArg:
anatofuz
parents:
diff changeset
1093 case ConversionSpecifier::xArg:
anatofuz
parents:
diff changeset
1094 case ConversionSpecifier::XArg:
anatofuz
parents:
diff changeset
1095 case ConversionSpecifier::aArg:
anatofuz
parents:
diff changeset
1096 case ConversionSpecifier::AArg:
anatofuz
parents:
diff changeset
1097 case ConversionSpecifier::eArg:
anatofuz
parents:
diff changeset
1098 case ConversionSpecifier::EArg:
anatofuz
parents:
diff changeset
1099 case ConversionSpecifier::fArg:
anatofuz
parents:
diff changeset
1100 case ConversionSpecifier::FArg:
anatofuz
parents:
diff changeset
1101 case ConversionSpecifier::gArg:
anatofuz
parents:
diff changeset
1102 case ConversionSpecifier::GArg:
anatofuz
parents:
diff changeset
1103 case ConversionSpecifier::sArg:
anatofuz
parents:
diff changeset
1104 case ConversionSpecifier::FreeBSDrArg:
anatofuz
parents:
diff changeset
1105 case ConversionSpecifier::FreeBSDyArg:
anatofuz
parents:
diff changeset
1106 case ConversionSpecifier::PArg:
anatofuz
parents:
diff changeset
1107 return true;
anatofuz
parents:
diff changeset
1108
anatofuz
parents:
diff changeset
1109 default:
anatofuz
parents:
diff changeset
1110 return false;
anatofuz
parents:
diff changeset
1111 }
anatofuz
parents:
diff changeset
1112 }
anatofuz
parents:
diff changeset
1113 bool PrintfSpecifier::hasValidFieldWidth() const {
anatofuz
parents:
diff changeset
1114 if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
anatofuz
parents:
diff changeset
1115 return true;
anatofuz
parents:
diff changeset
1116
anatofuz
parents:
diff changeset
1117 // The field width is valid for all conversions except n
anatofuz
parents:
diff changeset
1118 switch (CS.getKind()) {
anatofuz
parents:
diff changeset
1119 case ConversionSpecifier::nArg:
anatofuz
parents:
diff changeset
1120 return false;
anatofuz
parents:
diff changeset
1121
anatofuz
parents:
diff changeset
1122 default:
anatofuz
parents:
diff changeset
1123 return true;
anatofuz
parents:
diff changeset
1124 }
anatofuz
parents:
diff changeset
1125 }