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