/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/AST/FormatString.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | // FormatString.cpp - Common stuff for handling printf/scanf formats -*- 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 | | // Shared details for processing format strings of printf and scanf |
10 | | // (and friends). |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "FormatStringParsing.h" |
15 | | #include "clang/Basic/LangOptions.h" |
16 | | #include "clang/Basic/TargetInfo.h" |
17 | | #include "llvm/Support/ConvertUTF.h" |
18 | | |
19 | | using clang::analyze_format_string::ArgType; |
20 | | using clang::analyze_format_string::FormatStringHandler; |
21 | | using clang::analyze_format_string::FormatSpecifier; |
22 | | using clang::analyze_format_string::LengthModifier; |
23 | | using clang::analyze_format_string::OptionalAmount; |
24 | | using clang::analyze_format_string::ConversionSpecifier; |
25 | | using namespace clang; |
26 | | |
27 | | // Key function to FormatStringHandler. |
28 | 23.7k | FormatStringHandler::~FormatStringHandler() {} |
29 | | |
30 | | //===----------------------------------------------------------------------===// |
31 | | // Functions for parsing format strings components in both printf and |
32 | | // scanf format strings. |
33 | | //===----------------------------------------------------------------------===// |
34 | | |
35 | | OptionalAmount |
36 | 68.1k | clang::analyze_format_string::ParseAmount(const char *&Beg, const char *E) { |
37 | 68.1k | const char *I = Beg; |
38 | 68.1k | UpdateOnReturn <const char*> UpdateBeg(Beg, I); |
39 | | |
40 | 68.1k | unsigned accumulator = 0; |
41 | 68.1k | bool hasDigits = false; |
42 | | |
43 | 70.6k | for ( ; I != E; ++I2.48k ) { |
44 | 70.6k | char c = *I; |
45 | 70.6k | if (c >= '0' && c <= '9'69.3k ) { |
46 | 2.48k | hasDigits = true; |
47 | 2.48k | accumulator = (accumulator * 10) + (c - '0'); |
48 | 2.48k | continue; |
49 | 2.48k | } |
50 | | |
51 | 68.1k | if (hasDigits) |
52 | 2.20k | return OptionalAmount(OptionalAmount::Constant, accumulator, Beg, I - Beg, |
53 | 2.20k | false); |
54 | | |
55 | 65.9k | break; |
56 | 68.1k | } |
57 | | |
58 | 65.9k | return OptionalAmount(); |
59 | 68.1k | } |
60 | | |
61 | | OptionalAmount |
62 | | clang::analyze_format_string::ParseNonPositionAmount(const char *&Beg, |
63 | | const char *E, |
64 | 32.1k | unsigned &argIndex) { |
65 | 32.1k | if (*Beg == '*') { |
66 | 138 | ++Beg; |
67 | 138 | return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg, 0, false); |
68 | 138 | } |
69 | | |
70 | 31.9k | return ParseAmount(Beg, E); |
71 | 32.1k | } |
72 | | |
73 | | OptionalAmount |
74 | | clang::analyze_format_string::ParsePositionAmount(FormatStringHandler &H, |
75 | | const char *Start, |
76 | | const char *&Beg, |
77 | | const char *E, |
78 | 105 | PositionContext p) { |
79 | 105 | if (*Beg == '*') { |
80 | 16 | const char *I = Beg + 1; |
81 | 16 | const OptionalAmount &Amt = ParseAmount(I, E); |
82 | | |
83 | 16 | if (Amt.getHowSpecified() == OptionalAmount::NotSpecified) { |
84 | 0 | H.HandleInvalidPosition(Beg, I - Beg, p); |
85 | 0 | return OptionalAmount(false); |
86 | 0 | } |
87 | | |
88 | 16 | if (I == E) { |
89 | | // No more characters left? |
90 | 0 | H.HandleIncompleteSpecifier(Start, E - Start); |
91 | 0 | return OptionalAmount(false); |
92 | 0 | } |
93 | | |
94 | 16 | assert(Amt.getHowSpecified() == OptionalAmount::Constant); |
95 | | |
96 | 16 | if (*I == '$') { |
97 | | // Handle positional arguments |
98 | | |
99 | | // Special case: '*0$', since this is an easy mistake. |
100 | 16 | if (Amt.getConstantAmount() == 0) { |
101 | 4 | H.HandleZeroPosition(Beg, I - Beg + 1); |
102 | 4 | return OptionalAmount(false); |
103 | 4 | } |
104 | | |
105 | 12 | const char *Tmp = Beg; |
106 | 12 | Beg = ++I; |
107 | | |
108 | 12 | return OptionalAmount(OptionalAmount::Arg, Amt.getConstantAmount() - 1, |
109 | 12 | Tmp, 0, true); |
110 | 16 | } |
111 | | |
112 | 0 | H.HandleInvalidPosition(Beg, I - Beg, p); |
113 | 0 | return OptionalAmount(false); |
114 | 16 | } |
115 | | |
116 | 89 | return ParseAmount(Beg, E); |
117 | 105 | } |
118 | | |
119 | | |
120 | | bool |
121 | | clang::analyze_format_string::ParseFieldWidth(FormatStringHandler &H, |
122 | | FormatSpecifier &CS, |
123 | | const char *Start, |
124 | | const char *&Beg, const char *E, |
125 | 31.9k | unsigned *argIndex) { |
126 | | // FIXME: Support negative field widths. |
127 | 31.9k | if (argIndex) { |
128 | 31.8k | CS.setFieldWidth(ParseNonPositionAmount(Beg, E, *argIndex)); |
129 | 31.8k | } |
130 | 93 | else { |
131 | 93 | const OptionalAmount Amt = |
132 | 93 | ParsePositionAmount(H, Start, Beg, E, |
133 | 93 | analyze_format_string::FieldWidthPos); |
134 | | |
135 | 93 | if (Amt.isInvalid()) |
136 | 4 | return true; |
137 | 89 | CS.setFieldWidth(Amt); |
138 | 89 | } |
139 | 31.9k | return false; |
140 | 31.9k | } |
141 | | |
142 | | bool |
143 | | clang::analyze_format_string::ParseArgPosition(FormatStringHandler &H, |
144 | | FormatSpecifier &FS, |
145 | | const char *Start, |
146 | | const char *&Beg, |
147 | 33.9k | const char *E) { |
148 | 33.9k | const char *I = Beg; |
149 | | |
150 | 33.9k | const OptionalAmount &Amt = ParseAmount(I, E); |
151 | | |
152 | 33.9k | if (I == E) { |
153 | | // No more characters left? |
154 | 0 | H.HandleIncompleteSpecifier(Start, E - Start); |
155 | 0 | return true; |
156 | 0 | } |
157 | | |
158 | 33.9k | if (Amt.getHowSpecified() == OptionalAmount::Constant && *(I++) == '$'983 ) { |
159 | | // Warn that positional arguments are non-standard. |
160 | 121 | H.HandlePosition(Start, I - Start); |
161 | | |
162 | | // Special case: '%0$', since this is an easy mistake. |
163 | 121 | if (Amt.getConstantAmount() == 0) { |
164 | 12 | H.HandleZeroPosition(Start, I - Start); |
165 | 12 | return true; |
166 | 12 | } |
167 | | |
168 | 109 | FS.setArgIndex(Amt.getConstantAmount() - 1); |
169 | 109 | FS.setUsesPositionalArg(); |
170 | | // Update the caller's pointer if we decided to consume |
171 | | // these characters. |
172 | 109 | Beg = I; |
173 | 109 | return false; |
174 | 121 | } |
175 | | |
176 | 33.8k | return false; |
177 | 33.9k | } |
178 | | |
179 | | bool |
180 | | clang::analyze_format_string::ParseVectorModifier(FormatStringHandler &H, |
181 | | FormatSpecifier &FS, |
182 | | const char *&I, |
183 | | const char *E, |
184 | 31.9k | const LangOptions &LO) { |
185 | 31.9k | if (!LO.OpenCL) |
186 | 31.7k | return false; |
187 | | |
188 | 187 | const char *Start = I; |
189 | 187 | if (*I == 'v') { |
190 | 178 | ++I; |
191 | | |
192 | 178 | if (I == E) { |
193 | 2 | H.HandleIncompleteSpecifier(Start, E - Start); |
194 | 2 | return true; |
195 | 2 | } |
196 | | |
197 | 176 | OptionalAmount NumElts = ParseAmount(I, E); |
198 | 176 | if (NumElts.getHowSpecified() != OptionalAmount::Constant) { |
199 | 10 | H.HandleIncompleteSpecifier(Start, E - Start); |
200 | 10 | return true; |
201 | 10 | } |
202 | | |
203 | 166 | FS.setVectorNumElts(NumElts); |
204 | 166 | } |
205 | | |
206 | 175 | return false; |
207 | 187 | } |
208 | | |
209 | | bool |
210 | | clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS, |
211 | | const char *&I, |
212 | | const char *E, |
213 | | const LangOptions &LO, |
214 | 33.8k | bool IsScanf) { |
215 | 33.8k | LengthModifier::Kind lmKind = LengthModifier::None; |
216 | 33.8k | const char *lmPosition = I; |
217 | 33.8k | switch (*I) { |
218 | 26.8k | default: |
219 | 26.8k | return false; |
220 | 1.73k | case 'h': |
221 | 1.73k | ++I; |
222 | 1.73k | if (I != E && *I == 'h') { |
223 | 178 | ++I; |
224 | 178 | lmKind = LengthModifier::AsChar; |
225 | 1.55k | } else if (I != E && *I == 'l' && LO.OpenCL51 ) { |
226 | 43 | ++I; |
227 | 43 | lmKind = LengthModifier::AsShortLong; |
228 | 1.51k | } else { |
229 | 1.51k | lmKind = LengthModifier::AsShort; |
230 | 1.51k | } |
231 | 1.73k | break; |
232 | 4.49k | case 'l': |
233 | 4.49k | ++I; |
234 | 4.49k | if (I != E && *I == 'l'4.48k ) { |
235 | 1.61k | ++I; |
236 | 1.61k | lmKind = LengthModifier::AsLongLong; |
237 | 2.88k | } else { |
238 | 2.88k | lmKind = LengthModifier::AsLong; |
239 | 2.88k | } |
240 | 4.49k | break; |
241 | 25 | case 'j': lmKind = LengthModifier::AsIntMax; ++I; break; |
242 | 267 | case 'z': lmKind = LengthModifier::AsSizeT; ++I; break; |
243 | 82 | case 't': lmKind = LengthModifier::AsPtrDiff; ++I; break; |
244 | 237 | case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break; |
245 | 45 | case 'q': lmKind = LengthModifier::AsQuad; ++I; break; |
246 | 58 | case 'a': |
247 | 58 | if (IsScanf && !LO.C9944 && !LO.CPlusPlus1130 ) { |
248 | | // For scanf in C90, look at the next character to see if this should |
249 | | // be parsed as the GNU extension 'a' length modifier. If not, this |
250 | | // will be parsed as a conversion specifier. |
251 | 18 | ++I; |
252 | 18 | if (I != E && (16 *I == 's'16 || *I == 'S'10 || *I == '['8 )) { |
253 | 12 | lmKind = LengthModifier::AsAllocate; |
254 | 12 | break; |
255 | 12 | } |
256 | 6 | --I; |
257 | 6 | } |
258 | 46 | return false; |
259 | 61 | case 'm': |
260 | 61 | if (IsScanf) { |
261 | 46 | lmKind = LengthModifier::AsMAllocate; |
262 | 46 | ++I; |
263 | 46 | break; |
264 | 46 | } |
265 | 15 | return false; |
266 | | // printf: AsInt64, AsInt32, AsInt3264 |
267 | | // scanf: AsInt64 |
268 | 11 | case 'I': |
269 | 11 | if (I + 1 != E && I + 2 != E) { |
270 | 10 | if (I[1] == '6' && I[2] == '4'3 ) { |
271 | 3 | I += 3; |
272 | 3 | lmKind = LengthModifier::AsInt64; |
273 | 3 | break; |
274 | 3 | } |
275 | 7 | if (IsScanf) |
276 | 0 | return false; |
277 | | |
278 | 7 | if (I[1] == '3' && I[2] == '2'3 ) { |
279 | 3 | I += 3; |
280 | 3 | lmKind = LengthModifier::AsInt32; |
281 | 3 | break; |
282 | 3 | } |
283 | 7 | } |
284 | 5 | ++I; |
285 | 5 | lmKind = LengthModifier::AsInt3264; |
286 | 5 | break; |
287 | 26 | case 'w': |
288 | 26 | lmKind = LengthModifier::AsWide; ++I; break; |
289 | 33.8k | } |
290 | 6.97k | LengthModifier lm(lmPosition, lmKind); |
291 | 6.97k | FS.setLengthModifier(lm); |
292 | 6.97k | return true; |
293 | 33.8k | } |
294 | | |
295 | | bool clang::analyze_format_string::ParseUTF8InvalidSpecifier( |
296 | 137 | const char *SpecifierBegin, const char *FmtStrEnd, unsigned &Len) { |
297 | 137 | if (SpecifierBegin + 1 >= FmtStrEnd) |
298 | 0 | return false; |
299 | | |
300 | 137 | const llvm::UTF8 *SB = |
301 | 137 | reinterpret_cast<const llvm::UTF8 *>(SpecifierBegin + 1); |
302 | 137 | const llvm::UTF8 *SE = reinterpret_cast<const llvm::UTF8 *>(FmtStrEnd); |
303 | 137 | const char FirstByte = *SB; |
304 | | |
305 | | // If the invalid specifier is a multibyte UTF-8 string, return the |
306 | | // total length accordingly so that the conversion specifier can be |
307 | | // properly updated to reflect a complete UTF-8 specifier. |
308 | 137 | unsigned NumBytes = llvm::getNumBytesForUTF8(FirstByte); |
309 | 137 | if (NumBytes == 1) |
310 | 112 | return false; |
311 | 25 | if (SB + NumBytes > SE) |
312 | 5 | return false; |
313 | | |
314 | 20 | Len = NumBytes + 1; |
315 | 20 | return true; |
316 | 25 | } |
317 | | |
318 | | //===----------------------------------------------------------------------===// |
319 | | // Methods on ArgType. |
320 | | //===----------------------------------------------------------------------===// |
321 | | |
322 | | clang::analyze_format_string::ArgType::MatchKind |
323 | 29.8k | ArgType::matchesType(ASTContext &C, QualType argTy) const { |
324 | | // When using the format attribute in C++, you can receive a function or an |
325 | | // array that will necessarily decay to a pointer when passed to the final |
326 | | // format consumer. Apply decay before type comparison. |
327 | 29.8k | if (argTy->canDecayToPointerType()) |
328 | 0 | argTy = C.getDecayedType(argTy); |
329 | | |
330 | 29.8k | if (Ptr) { |
331 | | // It has to be a pointer. |
332 | 1.10k | const PointerType *PT = argTy->getAs<PointerType>(); |
333 | 1.10k | if (!PT) |
334 | 13 | return NoMatch; |
335 | | |
336 | | // We cannot write through a const qualified pointer. |
337 | 1.09k | if (PT->getPointeeType().isConstQualified()) |
338 | 28 | return NoMatch; |
339 | | |
340 | 1.06k | argTy = PT->getPointeeType(); |
341 | 1.06k | } |
342 | | |
343 | 29.8k | switch (K) { |
344 | 0 | case InvalidTy: |
345 | 0 | llvm_unreachable("ArgType must be valid"); |
346 | |
|
347 | 8 | case UnknownTy: |
348 | 8 | return Match; |
349 | | |
350 | 567 | case AnyCharTy: { |
351 | 567 | if (const EnumType *ETy = argTy->getAs<EnumType>()) { |
352 | | // If the enum is incomplete we know nothing about the underlying type. |
353 | | // Assume that it's 'int'. |
354 | 20 | if (!ETy->getDecl()->isComplete()) |
355 | 2 | return NoMatch; |
356 | 18 | argTy = ETy->getDecl()->getIntegerType(); |
357 | 18 | } |
358 | | |
359 | 565 | if (const BuiltinType *BT = argTy->getAs<BuiltinType>()) |
360 | 565 | switch (BT->getKind()) { |
361 | 100 | default: |
362 | 100 | break; |
363 | 441 | case BuiltinType::Char_S: |
364 | 451 | case BuiltinType::SChar: |
365 | 458 | case BuiltinType::UChar: |
366 | 459 | case BuiltinType::Char_U: |
367 | 465 | case BuiltinType::Bool: |
368 | 465 | return Match; |
369 | 565 | } |
370 | 100 | return NoMatch; |
371 | 565 | } |
372 | | |
373 | 19.4k | case SpecificTy: { |
374 | 19.4k | if (const EnumType *ETy = argTy->getAs<EnumType>()) { |
375 | | // If the enum is incomplete we know nothing about the underlying type. |
376 | | // Assume that it's 'int'. |
377 | 54 | if (!ETy->getDecl()->isComplete()) |
378 | 4 | argTy = C.IntTy; |
379 | 50 | else |
380 | 50 | argTy = ETy->getDecl()->getIntegerType(); |
381 | 54 | } |
382 | 19.4k | argTy = C.getCanonicalType(argTy).getUnqualifiedType(); |
383 | | |
384 | 19.4k | if (T == argTy) |
385 | 16.5k | return Match; |
386 | | // Check for "compatible types". |
387 | 2.92k | if (const BuiltinType *BT = argTy->getAs<BuiltinType>()) |
388 | 2.73k | switch (BT->getKind()) { |
389 | 182 | default: |
390 | 182 | break; |
391 | 182 | case BuiltinType::Char_S: |
392 | 47 | case BuiltinType::SChar: |
393 | 51 | case BuiltinType::Char_U: |
394 | 77 | case BuiltinType::UChar: |
395 | 110 | case BuiltinType::Bool: |
396 | 110 | if (T == C.UnsignedShortTy || T == C.ShortTy92 ) |
397 | 32 | return NoMatchTypeConfusion; |
398 | 78 | return T == C.UnsignedCharTy || T == C.SignedCharTy61 ? Match29 |
399 | 78 | : NoMatch49 ; |
400 | 41 | case BuiltinType::Short: |
401 | 41 | return T == C.UnsignedShortTy ? Match8 : NoMatch33 ; |
402 | 14 | case BuiltinType::UShort: |
403 | 14 | return T == C.ShortTy ? Match6 : NoMatch8 ; |
404 | 1.86k | case BuiltinType::Int: |
405 | 1.86k | return T == C.UnsignedIntTy ? Match107 : NoMatch1.75k ; |
406 | 105 | case BuiltinType::UInt: |
407 | 105 | return T == C.IntTy ? Match59 : NoMatch46 ; |
408 | 120 | case BuiltinType::Long: |
409 | 120 | return T == C.UnsignedLongTy ? Match36 : NoMatch84 ; |
410 | 238 | case BuiltinType::ULong: |
411 | 238 | return T == C.LongTy ? Match171 : NoMatch67 ; |
412 | 27 | case BuiltinType::LongLong: |
413 | 27 | return T == C.UnsignedLongLongTy ? Match16 : NoMatch11 ; |
414 | 32 | case BuiltinType::ULongLong: |
415 | 32 | return T == C.LongLongTy ? Match28 : NoMatch4 ; |
416 | 2.73k | } |
417 | 374 | return NoMatch; |
418 | 2.92k | } |
419 | | |
420 | 4.80k | case CStrTy: { |
421 | 4.80k | const PointerType *PT = argTy->getAs<PointerType>(); |
422 | 4.80k | if (!PT) |
423 | 442 | return NoMatch; |
424 | 4.36k | QualType pointeeTy = PT->getPointeeType(); |
425 | 4.36k | if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>()) |
426 | 4.35k | switch (BT->getKind()) { |
427 | 16 | case BuiltinType::Char_U: |
428 | 20 | case BuiltinType::UChar: |
429 | 4.33k | case BuiltinType::Char_S: |
430 | 4.33k | case BuiltinType::SChar: |
431 | 4.33k | return Match; |
432 | 20 | default: |
433 | 20 | break; |
434 | 4.35k | } |
435 | | |
436 | 28 | return NoMatch; |
437 | 4.36k | } |
438 | | |
439 | 136 | case WCStrTy: { |
440 | 136 | const PointerType *PT = argTy->getAs<PointerType>(); |
441 | 136 | if (!PT) |
442 | 109 | return NoMatch; |
443 | 27 | QualType pointeeTy = |
444 | 27 | C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType(); |
445 | 27 | return pointeeTy == C.getWideCharType() ? Match20 : NoMatch7 ; |
446 | 136 | } |
447 | | |
448 | 26 | case WIntTy: { |
449 | 26 | QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType(); |
450 | | |
451 | 26 | if (C.getCanonicalType(argTy).getUnqualifiedType() == WInt) |
452 | 12 | return Match; |
453 | | |
454 | 14 | QualType PromoArg = argTy->isPromotableIntegerType() |
455 | 14 | ? C.getPromotedIntegerType(argTy)0 |
456 | 14 | : argTy; |
457 | 14 | PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType(); |
458 | | |
459 | | // If the promoted argument is the corresponding signed type of the |
460 | | // wint_t type, then it should match. |
461 | 14 | if (PromoArg->hasSignedIntegerRepresentation() && |
462 | 14 | C.getCorrespondingUnsignedType(PromoArg) == WInt4 ) |
463 | 2 | return Match; |
464 | | |
465 | 12 | return WInt == PromoArg ? Match0 : NoMatch; |
466 | 14 | } |
467 | | |
468 | 3.80k | case CPointerTy: |
469 | 3.80k | if (argTy->isVoidPointerType()) { |
470 | 161 | return Match; |
471 | 3.64k | } if (argTy->isPointerType() || argTy->isObjCObjectPointerType()60 || |
472 | 3.64k | argTy->isBlockPointerType()30 || argTy->isNullPtrType()28 ) { |
473 | 3.61k | return NoMatchPedantic; |
474 | 3.61k | } else { |
475 | 26 | return NoMatch; |
476 | 26 | } |
477 | | |
478 | 1.01k | case ObjCPointerTy: { |
479 | 1.01k | if (argTy->getAs<ObjCObjectPointerType>() || |
480 | 1.01k | argTy->getAs<BlockPointerType>()53 ) |
481 | 961 | return Match; |
482 | | |
483 | | // Handle implicit toll-free bridging. |
484 | 50 | if (const PointerType *PT = argTy->getAs<PointerType>()) { |
485 | | // Things such as CFTypeRef are really just opaque pointers |
486 | | // to C structs representing CF types that can often be bridged |
487 | | // to Objective-C objects. Since the compiler doesn't know which |
488 | | // structs can be toll-free bridged, we just accept them all. |
489 | 12 | QualType pointee = PT->getPointeeType(); |
490 | 12 | if (pointee->getAsStructureType() || pointee->isVoidType()3 ) |
491 | 9 | return Match; |
492 | 12 | } |
493 | 41 | return NoMatch; |
494 | 50 | } |
495 | 29.8k | } |
496 | | |
497 | 0 | llvm_unreachable("Invalid ArgType Kind!"); |
498 | 0 | } |
499 | | |
500 | 241 | ArgType ArgType::makeVectorType(ASTContext &C, unsigned NumElts) const { |
501 | | // Check for valid vector element types. |
502 | 241 | if (T.isNull()) |
503 | 20 | return ArgType::Invalid(); |
504 | | |
505 | 221 | QualType Vec = C.getExtVectorType(T, NumElts); |
506 | 221 | return ArgType(Vec, Name); |
507 | 241 | } |
508 | | |
509 | 4.53k | QualType ArgType::getRepresentativeType(ASTContext &C) const { |
510 | 4.53k | QualType Res; |
511 | 4.53k | switch (K) { |
512 | 0 | case InvalidTy: |
513 | 0 | llvm_unreachable("No representative type for Invalid ArgType"); |
514 | 0 | case UnknownTy: |
515 | 0 | llvm_unreachable("No representative type for Unknown ArgType"); |
516 | 35 | case AnyCharTy: |
517 | 35 | Res = C.CharTy; |
518 | 35 | break; |
519 | 686 | case SpecificTy: |
520 | 686 | Res = T; |
521 | 686 | break; |
522 | 152 | case CStrTy: |
523 | 152 | Res = C.getPointerType(C.CharTy); |
524 | 152 | break; |
525 | 17 | case WCStrTy: |
526 | 17 | Res = C.getPointerType(C.getWideCharType()); |
527 | 17 | break; |
528 | 23 | case ObjCPointerTy: |
529 | 23 | Res = C.ObjCBuiltinIdTy; |
530 | 23 | break; |
531 | 3.60k | case CPointerTy: |
532 | 3.60k | Res = C.VoidPtrTy; |
533 | 3.60k | break; |
534 | 10 | case WIntTy: { |
535 | 10 | Res = C.getWIntType(); |
536 | 10 | break; |
537 | 0 | } |
538 | 4.53k | } |
539 | | |
540 | 4.53k | if (Ptr) |
541 | 192 | Res = C.getPointerType(Res); |
542 | 4.53k | return Res; |
543 | 4.53k | } |
544 | | |
545 | 4.53k | std::string ArgType::getRepresentativeTypeName(ASTContext &C) const { |
546 | 4.53k | std::string S = getRepresentativeType(C).getAsString(C.getPrintingPolicy()); |
547 | | |
548 | 4.53k | std::string Alias; |
549 | 4.53k | if (Name) { |
550 | | // Use a specific name for this type, e.g. "size_t". |
551 | 116 | Alias = Name; |
552 | 116 | if (Ptr) { |
553 | | // If ArgType is actually a pointer to T, append an asterisk. |
554 | 39 | Alias += (Alias[Alias.size()-1] == '*') ? "*"5 : " *"34 ; |
555 | 39 | } |
556 | | // If Alias is the same as the underlying type, e.g. wchar_t, then drop it. |
557 | 116 | if (S == Alias) |
558 | 3 | Alias.clear(); |
559 | 116 | } |
560 | | |
561 | 4.53k | if (!Alias.empty()) |
562 | 113 | return std::string("'") + Alias + "' (aka '" + S + "')"; |
563 | 4.41k | return std::string("'") + S + "'"; |
564 | 4.53k | } |
565 | | |
566 | | |
567 | | //===----------------------------------------------------------------------===// |
568 | | // Methods on OptionalAmount. |
569 | | //===----------------------------------------------------------------------===// |
570 | | |
571 | | ArgType |
572 | 93 | analyze_format_string::OptionalAmount::getArgType(ASTContext &Ctx) const { |
573 | 93 | return Ctx.IntTy; |
574 | 93 | } |
575 | | |
576 | | //===----------------------------------------------------------------------===// |
577 | | // Methods on LengthModifier. |
578 | | //===----------------------------------------------------------------------===// |
579 | | |
580 | | const char * |
581 | 1.43k | analyze_format_string::LengthModifier::toString() const { |
582 | 1.43k | switch (kind) { |
583 | 49 | case AsChar: |
584 | 49 | return "hh"; |
585 | 77 | case AsShort: |
586 | 77 | return "h"; |
587 | 86 | case AsShortLong: |
588 | 86 | return "hl"; |
589 | 264 | case AsLong: // or AsWideChar |
590 | 264 | return "l"; |
591 | 165 | case AsLongLong: |
592 | 165 | return "ll"; |
593 | 34 | case AsQuad: |
594 | 34 | return "q"; |
595 | 8 | case AsIntMax: |
596 | 8 | return "j"; |
597 | 15 | case AsSizeT: |
598 | 15 | return "z"; |
599 | 4 | case AsPtrDiff: |
600 | 4 | return "t"; |
601 | 3 | case AsInt32: |
602 | 3 | return "I32"; |
603 | 5 | case AsInt3264: |
604 | 5 | return "I"; |
605 | 3 | case AsInt64: |
606 | 3 | return "I64"; |
607 | 84 | case AsLongDouble: |
608 | 84 | return "L"; |
609 | 6 | case AsAllocate: |
610 | 6 | return "a"; |
611 | 23 | case AsMAllocate: |
612 | 23 | return "m"; |
613 | 18 | case AsWide: |
614 | 18 | return "w"; |
615 | 586 | case None: |
616 | 586 | return ""; |
617 | 1.43k | } |
618 | 0 | return nullptr; |
619 | 1.43k | } |
620 | | |
621 | | //===----------------------------------------------------------------------===// |
622 | | // Methods on ConversionSpecifier. |
623 | | //===----------------------------------------------------------------------===// |
624 | | |
625 | 1.52k | const char *ConversionSpecifier::toString() const { |
626 | 1.52k | switch (kind) { |
627 | 496 | case dArg: return "d"; |
628 | 30 | case DArg: return "D"; |
629 | 9 | case iArg: return "i"; |
630 | 39 | case oArg: return "o"; |
631 | 20 | case OArg: return "O"; |
632 | 198 | case uArg: return "u"; |
633 | 18 | case UArg: return "U"; |
634 | 19 | case xArg: return "x"; |
635 | 4 | case XArg: return "X"; |
636 | 112 | case fArg: return "f"; |
637 | 2 | case FArg: return "F"; |
638 | 2 | case eArg: return "e"; |
639 | 2 | case EArg: return "E"; |
640 | 2 | case gArg: return "g"; |
641 | 2 | case GArg: return "G"; |
642 | 6 | case aArg: return "a"; |
643 | 2 | case AArg: return "A"; |
644 | 68 | case cArg: return "c"; |
645 | 248 | case sArg: return "s"; |
646 | 48 | case pArg: return "p"; |
647 | 0 | case PArg: |
648 | 0 | return "P"; |
649 | 18 | case nArg: return "n"; |
650 | 0 | case PercentArg: return "%"; |
651 | 4 | case ScanListArg: return "["; |
652 | 0 | case InvalidSpecifier: return nullptr; |
653 | | |
654 | | // POSIX unicode extensions. |
655 | 21 | case CArg: return "C"; |
656 | 28 | case SArg: return "S"; |
657 | | |
658 | | // Objective-C specific specifiers. |
659 | 44 | case ObjCObjArg: return "@"; |
660 | | |
661 | | // FreeBSD kernel specific specifiers. |
662 | 0 | case FreeBSDbArg: return "b"; |
663 | 0 | case FreeBSDDArg: return "D"; |
664 | 36 | case FreeBSDrArg: return "r"; |
665 | 36 | case FreeBSDyArg: return "y"; |
666 | | |
667 | | // GlibC specific specifiers. |
668 | 0 | case PrintErrno: return "m"; |
669 | | |
670 | | // MS specific specifiers. |
671 | 7 | case ZArg: return "Z"; |
672 | 1.52k | } |
673 | 0 | return nullptr; |
674 | 1.52k | } |
675 | | |
676 | | Optional<ConversionSpecifier> |
677 | 163 | ConversionSpecifier::getStandardSpecifier() const { |
678 | 163 | ConversionSpecifier::Kind NewKind; |
679 | | |
680 | 163 | switch (getKind()) { |
681 | 103 | default: |
682 | 103 | return None; |
683 | 24 | case DArg: |
684 | 24 | NewKind = dArg; |
685 | 24 | break; |
686 | 18 | case UArg: |
687 | 18 | NewKind = uArg; |
688 | 18 | break; |
689 | 18 | case OArg: |
690 | 18 | NewKind = oArg; |
691 | 18 | break; |
692 | 163 | } |
693 | | |
694 | 60 | ConversionSpecifier FixedCS(*this); |
695 | 60 | FixedCS.setKind(NewKind); |
696 | 60 | return FixedCS; |
697 | 163 | } |
698 | | |
699 | | //===----------------------------------------------------------------------===// |
700 | | // Methods on OptionalAmount. |
701 | | //===----------------------------------------------------------------------===// |
702 | | |
703 | 2.02k | void OptionalAmount::toString(raw_ostream &os) const { |
704 | 2.02k | switch (hs) { |
705 | 0 | case Invalid: |
706 | 2.00k | case NotSpecified: |
707 | 2.00k | return; |
708 | 4 | case Arg: |
709 | 4 | if (UsesDotPrefix) |
710 | 4 | os << "."; |
711 | 4 | if (usesPositionalArg()) |
712 | 2 | os << "*" << getPositionalArgIndex() << "$"; |
713 | 2 | else |
714 | 2 | os << "*"; |
715 | 4 | break; |
716 | 17 | case Constant: |
717 | 17 | if (UsesDotPrefix) |
718 | 10 | os << "."; |
719 | 17 | os << amt; |
720 | 17 | break; |
721 | 2.02k | } |
722 | 2.02k | } |
723 | | |
724 | | bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target, |
725 | 28.2k | const LangOptions &LO) const { |
726 | 28.2k | switch (LM.getKind()) { |
727 | 21.4k | case LengthModifier::None: |
728 | 21.4k | return true; |
729 | | |
730 | | // Handle most integer flags |
731 | 1.54k | case LengthModifier::AsShort: |
732 | | // Length modifier only applies to FP vectors. |
733 | 1.54k | if (LO.OpenCL && CS.isDoubleArg()41 ) |
734 | 10 | return !VectorNumElts.isInvalid(); |
735 | | |
736 | 1.53k | if (Target.getTriple().isOSMSVCRT()) { |
737 | 11 | switch (CS.getKind()) { |
738 | 2 | case ConversionSpecifier::cArg: |
739 | 4 | case ConversionSpecifier::CArg: |
740 | 6 | case ConversionSpecifier::sArg: |
741 | 8 | case ConversionSpecifier::SArg: |
742 | 9 | case ConversionSpecifier::ZArg: |
743 | 9 | return true; |
744 | 2 | default: |
745 | 2 | break; |
746 | 11 | } |
747 | 11 | } |
748 | 1.53k | LLVM_FALLTHROUGH1.52k ;1.52k |
749 | 1.75k | case LengthModifier::AsChar: |
750 | 3.35k | case LengthModifier::AsLongLong: |
751 | 3.38k | case LengthModifier::AsQuad: |
752 | 3.41k | case LengthModifier::AsIntMax: |
753 | 3.65k | case LengthModifier::AsSizeT: |
754 | 3.71k | case LengthModifier::AsPtrDiff: |
755 | 3.71k | switch (CS.getKind()) { |
756 | 1.45k | case ConversionSpecifier::dArg: |
757 | 1.46k | case ConversionSpecifier::DArg: |
758 | 1.47k | case ConversionSpecifier::iArg: |
759 | 1.47k | case ConversionSpecifier::oArg: |
760 | 1.48k | case ConversionSpecifier::OArg: |
761 | 3.12k | case ConversionSpecifier::uArg: |
762 | 3.12k | case ConversionSpecifier::UArg: |
763 | 3.47k | case ConversionSpecifier::xArg: |
764 | 3.48k | case ConversionSpecifier::XArg: |
765 | 3.58k | case ConversionSpecifier::nArg: |
766 | 3.58k | return true; |
767 | 8 | case ConversionSpecifier::FreeBSDrArg: |
768 | 16 | case ConversionSpecifier::FreeBSDyArg: |
769 | 16 | return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS()8 ; |
770 | 114 | default: |
771 | 114 | return false; |
772 | 3.71k | } |
773 | | |
774 | 86 | case LengthModifier::AsShortLong: |
775 | 86 | return LO.OpenCL && !VectorNumElts.isInvalid(); |
776 | | |
777 | | // Handle 'l' flag |
778 | 2.70k | case LengthModifier::AsLong: // or AsWideChar |
779 | 2.70k | if (CS.isDoubleArg()) { |
780 | | // Invalid for OpenCL FP scalars. |
781 | 650 | if (LO.OpenCL && VectorNumElts.isInvalid()31 ) |
782 | 1 | return false; |
783 | 649 | return true; |
784 | 650 | } |
785 | | |
786 | 2.05k | switch (CS.getKind()) { |
787 | 1.11k | case ConversionSpecifier::dArg: |
788 | 1.13k | case ConversionSpecifier::DArg: |
789 | 1.14k | case ConversionSpecifier::iArg: |
790 | 1.15k | case ConversionSpecifier::oArg: |
791 | 1.16k | case ConversionSpecifier::OArg: |
792 | 1.83k | case ConversionSpecifier::uArg: |
793 | 1.84k | case ConversionSpecifier::UArg: |
794 | 1.85k | case ConversionSpecifier::xArg: |
795 | 1.86k | case ConversionSpecifier::XArg: |
796 | 1.88k | case ConversionSpecifier::nArg: |
797 | 1.91k | case ConversionSpecifier::cArg: |
798 | 2.02k | case ConversionSpecifier::sArg: |
799 | 2.02k | case ConversionSpecifier::ScanListArg: |
800 | 2.02k | case ConversionSpecifier::ZArg: |
801 | 2.02k | return true; |
802 | 12 | case ConversionSpecifier::FreeBSDrArg: |
803 | 24 | case ConversionSpecifier::FreeBSDyArg: |
804 | 24 | return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS()12 ; |
805 | 10 | default: |
806 | 10 | return false; |
807 | 2.05k | } |
808 | | |
809 | 140 | case LengthModifier::AsLongDouble: |
810 | 140 | switch (CS.getKind()) { |
811 | 8 | case ConversionSpecifier::aArg: |
812 | 12 | case ConversionSpecifier::AArg: |
813 | 52 | case ConversionSpecifier::fArg: |
814 | 56 | case ConversionSpecifier::FArg: |
815 | 60 | case ConversionSpecifier::eArg: |
816 | 64 | case ConversionSpecifier::EArg: |
817 | 74 | case ConversionSpecifier::gArg: |
818 | 78 | case ConversionSpecifier::GArg: |
819 | 78 | return true; |
820 | | // GNU libc extension. |
821 | 22 | case ConversionSpecifier::dArg: |
822 | 23 | case ConversionSpecifier::iArg: |
823 | 24 | case ConversionSpecifier::oArg: |
824 | 33 | case ConversionSpecifier::uArg: |
825 | 42 | case ConversionSpecifier::xArg: |
826 | 43 | case ConversionSpecifier::XArg: |
827 | 43 | return !Target.getTriple().isOSDarwin() && |
828 | 43 | !Target.getTriple().isOSWindows()37 ; |
829 | 19 | default: |
830 | 19 | return false; |
831 | 140 | } |
832 | | |
833 | 6 | case LengthModifier::AsAllocate: |
834 | 6 | switch (CS.getKind()) { |
835 | 3 | case ConversionSpecifier::sArg: |
836 | 4 | case ConversionSpecifier::SArg: |
837 | 6 | case ConversionSpecifier::ScanListArg: |
838 | 6 | return true; |
839 | 0 | default: |
840 | 0 | return false; |
841 | 6 | } |
842 | | |
843 | 23 | case LengthModifier::AsMAllocate: |
844 | 23 | switch (CS.getKind()) { |
845 | 4 | case ConversionSpecifier::cArg: |
846 | 8 | case ConversionSpecifier::CArg: |
847 | 13 | case ConversionSpecifier::sArg: |
848 | 17 | case ConversionSpecifier::SArg: |
849 | 21 | case ConversionSpecifier::ScanListArg: |
850 | 21 | return true; |
851 | 2 | default: |
852 | 2 | return false; |
853 | 23 | } |
854 | 3 | case LengthModifier::AsInt32: |
855 | 8 | case LengthModifier::AsInt3264: |
856 | 11 | case LengthModifier::AsInt64: |
857 | 11 | switch (CS.getKind()) { |
858 | 8 | case ConversionSpecifier::dArg: |
859 | 8 | case ConversionSpecifier::iArg: |
860 | 8 | case ConversionSpecifier::oArg: |
861 | 11 | case ConversionSpecifier::uArg: |
862 | 11 | case ConversionSpecifier::xArg: |
863 | 11 | case ConversionSpecifier::XArg: |
864 | 11 | return Target.getTriple().isOSMSVCRT(); |
865 | 0 | default: |
866 | 0 | return false; |
867 | 11 | } |
868 | 18 | case LengthModifier::AsWide: |
869 | 18 | switch (CS.getKind()) { |
870 | 5 | case ConversionSpecifier::cArg: |
871 | 9 | case ConversionSpecifier::CArg: |
872 | 13 | case ConversionSpecifier::sArg: |
873 | 17 | case ConversionSpecifier::SArg: |
874 | 18 | case ConversionSpecifier::ZArg: |
875 | 18 | return Target.getTriple().isOSMSVCRT(); |
876 | 0 | default: |
877 | 0 | return false; |
878 | 18 | } |
879 | 28.2k | } |
880 | 0 | llvm_unreachable("Invalid LengthModifier Kind!"); |
881 | 0 | } |
882 | | |
883 | 27.3k | bool FormatSpecifier::hasStandardLengthModifier() const { |
884 | 27.3k | switch (LM.getKind()) { |
885 | 21.1k | case LengthModifier::None: |
886 | 21.3k | case LengthModifier::AsChar: |
887 | 22.7k | case LengthModifier::AsShort: |
888 | 25.2k | case LengthModifier::AsLong: |
889 | 26.8k | case LengthModifier::AsLongLong: |
890 | 26.8k | case LengthModifier::AsIntMax: |
891 | 27.0k | case LengthModifier::AsSizeT: |
892 | 27.1k | case LengthModifier::AsPtrDiff: |
893 | 27.2k | case LengthModifier::AsLongDouble: |
894 | 27.2k | return true; |
895 | 6 | case LengthModifier::AsAllocate: |
896 | 27 | case LengthModifier::AsMAllocate: |
897 | 57 | case LengthModifier::AsQuad: |
898 | 60 | case LengthModifier::AsInt32: |
899 | 65 | case LengthModifier::AsInt3264: |
900 | 68 | case LengthModifier::AsInt64: |
901 | 86 | case LengthModifier::AsWide: |
902 | 126 | case LengthModifier::AsShortLong: // ??? |
903 | 126 | return false; |
904 | 27.3k | } |
905 | 0 | llvm_unreachable("Invalid LengthModifier Kind!"); |
906 | 0 | } |
907 | | |
908 | | bool FormatSpecifier::hasStandardConversionSpecifier( |
909 | 27.4k | const LangOptions &LangOpt) const { |
910 | 27.4k | switch (CS.getKind()) { |
911 | 1.39k | case ConversionSpecifier::cArg: |
912 | 11.2k | case ConversionSpecifier::dArg: |
913 | 11.9k | case ConversionSpecifier::iArg: |
914 | 11.9k | case ConversionSpecifier::oArg: |
915 | 14.9k | case ConversionSpecifier::uArg: |
916 | 15.3k | case ConversionSpecifier::xArg: |
917 | 15.4k | case ConversionSpecifier::XArg: |
918 | 15.7k | case ConversionSpecifier::fArg: |
919 | 15.7k | case ConversionSpecifier::FArg: |
920 | 15.7k | case ConversionSpecifier::eArg: |
921 | 15.8k | case ConversionSpecifier::EArg: |
922 | 16.9k | case ConversionSpecifier::gArg: |
923 | 16.9k | case ConversionSpecifier::GArg: |
924 | 17.0k | case ConversionSpecifier::aArg: |
925 | 17.0k | case ConversionSpecifier::AArg: |
926 | 22.0k | case ConversionSpecifier::sArg: |
927 | 25.7k | case ConversionSpecifier::pArg: |
928 | 25.9k | case ConversionSpecifier::nArg: |
929 | 26.9k | case ConversionSpecifier::ObjCObjArg: |
930 | 27.0k | case ConversionSpecifier::ScanListArg: |
931 | 27.0k | case ConversionSpecifier::PercentArg: |
932 | 27.0k | case ConversionSpecifier::PArg: |
933 | 27.0k | return true; |
934 | 119 | case ConversionSpecifier::CArg: |
935 | 274 | case ConversionSpecifier::SArg: |
936 | 274 | return LangOpt.ObjC; |
937 | 0 | case ConversionSpecifier::InvalidSpecifier: |
938 | 0 | case ConversionSpecifier::FreeBSDbArg: |
939 | 0 | case ConversionSpecifier::FreeBSDDArg: |
940 | 24 | case ConversionSpecifier::FreeBSDrArg: |
941 | 48 | case ConversionSpecifier::FreeBSDyArg: |
942 | 48 | case ConversionSpecifier::PrintErrno: |
943 | 72 | case ConversionSpecifier::DArg: |
944 | 90 | case ConversionSpecifier::OArg: |
945 | 108 | case ConversionSpecifier::UArg: |
946 | 114 | case ConversionSpecifier::ZArg: |
947 | 114 | return false; |
948 | 27.4k | } |
949 | 0 | llvm_unreachable("Invalid ConversionSpecifier Kind!"); |
950 | 0 | } |
951 | | |
952 | 27.2k | bool FormatSpecifier::hasStandardLengthConversionCombination() const { |
953 | 27.2k | if (LM.getKind() == LengthModifier::AsLongDouble) { |
954 | 89 | switch(CS.getKind()) { |
955 | 12 | case ConversionSpecifier::dArg: |
956 | 13 | case ConversionSpecifier::iArg: |
957 | 14 | case ConversionSpecifier::oArg: |
958 | 23 | case ConversionSpecifier::uArg: |
959 | 32 | case ConversionSpecifier::xArg: |
960 | 33 | case ConversionSpecifier::XArg: |
961 | 33 | return false; |
962 | 56 | default: |
963 | 56 | return true; |
964 | 89 | } |
965 | 89 | } |
966 | 27.1k | return true; |
967 | 27.2k | } |
968 | | |
969 | 225 | Optional<LengthModifier> FormatSpecifier::getCorrectedLengthModifier() const { |
970 | 225 | if (CS.isAnyIntArg() || CS.getKind() == ConversionSpecifier::nArg127 ) { |
971 | 116 | if (LM.getKind() == LengthModifier::AsLongDouble || |
972 | 116 | LM.getKind() == LengthModifier::AsQuad73 ) { |
973 | 73 | LengthModifier FixedLM(LM); |
974 | 73 | FixedLM.setKind(LengthModifier::AsLongLong); |
975 | 73 | return FixedLM; |
976 | 73 | } |
977 | 116 | } |
978 | | |
979 | 152 | return None; |
980 | 225 | } |
981 | | |
982 | | bool FormatSpecifier::namedTypeToLengthModifier(QualType QT, |
983 | 59 | LengthModifier &LM) { |
984 | 59 | assert(isa<TypedefType>(QT) && "Expected a TypedefType"); |
985 | 0 | const TypedefNameDecl *Typedef = cast<TypedefType>(QT)->getDecl(); |
986 | | |
987 | 67 | for (;;) { |
988 | 67 | const IdentifierInfo *Identifier = Typedef->getIdentifier(); |
989 | 67 | if (Identifier->getName() == "size_t") { |
990 | 6 | LM.setKind(LengthModifier::AsSizeT); |
991 | 6 | return true; |
992 | 61 | } else if (Identifier->getName() == "ssize_t") { |
993 | | // Not C99, but common in Unix. |
994 | 2 | LM.setKind(LengthModifier::AsSizeT); |
995 | 2 | return true; |
996 | 59 | } else if (Identifier->getName() == "intmax_t") { |
997 | 4 | LM.setKind(LengthModifier::AsIntMax); |
998 | 4 | return true; |
999 | 55 | } else if (Identifier->getName() == "uintmax_t") { |
1000 | 4 | LM.setKind(LengthModifier::AsIntMax); |
1001 | 4 | return true; |
1002 | 51 | } else if (Identifier->getName() == "ptrdiff_t") { |
1003 | 4 | LM.setKind(LengthModifier::AsPtrDiff); |
1004 | 4 | return true; |
1005 | 4 | } |
1006 | | |
1007 | 47 | QualType T = Typedef->getUnderlyingType(); |
1008 | 47 | if (!isa<TypedefType>(T)) |
1009 | 39 | break; |
1010 | | |
1011 | 8 | Typedef = cast<TypedefType>(T)->getDecl(); |
1012 | 8 | } |
1013 | 39 | return false; |
1014 | 59 | } |