1 //== PrintfFormatString.cpp - Analysis of printf format strings --*- C++ -*-==//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Handling of format string in printf and friends. The structure of format
11 // strings for fprintf() are described in C99 7.19.6.1.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "clang/Analysis/Analyses/FormatString.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 // Methods for parsing format strings.
33 //===----------------------------------------------------------------------===//
34
35 using analyze_format_string::ParseNonPositionAmount;
36
ParsePrecision(FormatStringHandler & H,PrintfSpecifier & FS,const char * Start,const char * & Beg,const char * E,unsigned * argIndex)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
ParseObjCFlags(FormatStringHandler & H,PrintfSpecifier & FS,const char * FlagBeg,const char * E,bool Warn)52 static bool ParseObjCFlags(FormatStringHandler &H, PrintfSpecifier &FS,
53 const char *FlagBeg, const char *E, bool Warn) {
54 StringRef Flag(FlagBeg, E - FlagBeg);
55 // Currently there is only one flag.
56 if (Flag == "tt") {
57 FS.setHasObjCTechnicalTerm(FlagBeg);
58 return false;
59 }
60 // Handle either the case of no flag or an invalid flag.
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
ParsePrintfSpecifier(FormatStringHandler & H,const char * & Beg,const char * E,unsigned & argIndex,const LangOptions & LO,const TargetInfo & Target,bool Warn,bool isFreeBSDKPrintf)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 // Look for a '%' character that indicates the start of a format specifier.
87 for ( ; I != E ; ++I) {
88 char c = *I;
89 if (c == '\0') {
90 // Detect spurious null characters, which are likely errors.
91 H.HandleNullChar(I);
92 return true;
93 }
94 if (c == '%') {
95 Start = I++; // Record the start of the format specifier.
96 break;
97 }
98 }
99
100 // No format specifier found?
101 if (!Start)
102 return false;
103
104 if (I == E) {
105 // No more characters left?
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 // No more characters left?
117 if (Warn)
118 H.HandleIncompleteSpecifier(Start, E - Start);
119 return true;
120 }
121
122 // Look for flags (if any).
123 bool hasMore = true;
124 for ( ; I != E; ++I) {
125 switch (*I) {
126 default: hasMore = false; break;
127 case '\'':
128 // FIXME: POSIX specific. Always accept?
129 FS.setHasThousandsGrouping(I);
130 break;
131 case '-': FS.setIsLeftJustified(I); break;
132 case '+': FS.setHasPlusPrefix(I); break;
133 case ' ': FS.setHasSpacePrefix(I); break;
134 case '#': FS.setHasAlternativeForm(I); break;
135 case '0': FS.setHasLeadingZeros(I); break;
136 }
137 if (!hasMore)
138 break;
139 }
140
141 if (I == E) {
142 // No more characters left?
143 if (Warn)
144 H.HandleIncompleteSpecifier(Start, E - Start);
145 return true;
146 }
147
148 // Look for the field width (if any).
149 if (ParseFieldWidth(H, FS, Start, I, E,
150 FS.usesPositionalArg() ? nullptr : &argIndex))
151 return true;
152
153 if (I == E) {
154 // No more characters left?
155 if (Warn)
156 H.HandleIncompleteSpecifier(Start, E - Start);
157 return true;
158 }
159
160 // Look for the precision (if any).
161 if (*I == '.') {
162 ++I;
163 if (I == E) {
164 if (Warn)
165 H.HandleIncompleteSpecifier(Start, E - Start);
166 return true;
167 }
168
169 if (ParsePrecision(H, FS, Start, I, E,
170 FS.usesPositionalArg() ? nullptr : &argIndex))
171 return true;
172
173 if (I == E) {
174 // No more characters left?
175 if (Warn)
176 H.HandleIncompleteSpecifier(Start, E - Start);
177 return true;
178 }
179 }
180
181 // Look for the length modifier.
182 if (ParseLengthModifier(FS, I, E, LO) && I == E) {
183 // No more characters left?
184 if (Warn)
185 H.HandleIncompleteSpecifier(Start, E - Start);
186 return true;
187 }
188
189 // Look for the Objective-C modifier flags, if any.
190 // We parse these here, even if they don't apply to
191 // the conversion specifier, and then emit an error
192 // later if the conversion specifier isn't '@'. This
193 // enables better recovery, and we don't know if
194 // these flags are applicable until later.
195 const char *ObjCModifierFlagsStart = nullptr,
196 *ObjCModifierFlagsEnd = nullptr;
197 if (*I == '[') {
198 ObjCModifierFlagsStart = I;
199 ++I;
200 auto flagStart = I;
201 for (;; ++I) {
202 ObjCModifierFlagsEnd = I;
203 if (I == E) {
204 if (Warn)
205 H.HandleIncompleteSpecifier(Start, E - Start);
206 return true;
207 }
208 // Did we find the closing ']'?
209 if (*I == ']') {
210 if (ParseObjCFlags(H, FS, flagStart, I, Warn))
211 return true;
212 ++I;
213 break;
214 }
215 // There are no separators defined yet for multiple
216 // Objective-C modifier flags. When those are
217 // defined, this is the place to check.
218 }
219 }
220
221 if (*I == '\0') {
222 // Detect spurious null characters, which are likely errors.
223 H.HandleNullChar(I);
224 return true;
225 }
226
227 // Finally, look for the conversion specifier.
228 const char *conversionPosition = I++;
229 ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier;
230 switch (*conversionPosition) {
231 default:
232 break;
233 // C99: 7.19.6.1 (section 8).
234 case '%': k = ConversionSpecifier::PercentArg; break;
235 case 'A': k = ConversionSpecifier::AArg; break;
236 case 'E': k = ConversionSpecifier::EArg; break;
237 case 'F': k = ConversionSpecifier::FArg; break;
238 case 'G': k = ConversionSpecifier::GArg; break;
239 case 'X': k = ConversionSpecifier::XArg; break;
240 case 'a': k = ConversionSpecifier::aArg; break;
241 case 'c': k = ConversionSpecifier::cArg; break;
242 case 'd': k = ConversionSpecifier::dArg; break;
243 case 'e': k = ConversionSpecifier::eArg; break;
244 case 'f': k = ConversionSpecifier::fArg; break;
245 case 'g': k = ConversionSpecifier::gArg; break;
246 case 'i': k = ConversionSpecifier::iArg; break;
247 case 'n': k = ConversionSpecifier::nArg; break;
248 case 'o': k = ConversionSpecifier::oArg; break;
249 case 'p': k = ConversionSpecifier::pArg; break;
250 case 's': k = ConversionSpecifier::sArg; break;
251 case 'u': k = ConversionSpecifier::uArg; break;
252 case 'x': k = ConversionSpecifier::xArg; break;
253 // POSIX specific.
254 case 'C': k = ConversionSpecifier::CArg; break;
255 case 'S': k = ConversionSpecifier::SArg; break;
256 // Objective-C.
257 case '@': k = ConversionSpecifier::ObjCObjArg; break;
258 // Glibc specific.
259 case 'm': k = ConversionSpecifier::PrintErrno; break;
260 // FreeBSD kernel specific.
261 case 'b':
262 if (isFreeBSDKPrintf)
263 k = ConversionSpecifier::FreeBSDbArg; // int followed by char *
264 break;
265 case 'r':
266 if (isFreeBSDKPrintf)
267 k = ConversionSpecifier::FreeBSDrArg; // int
268 break;
269 case 'y':
270 if (isFreeBSDKPrintf)
271 k = ConversionSpecifier::FreeBSDyArg; // int
272 break;
273 // Apple-specific.
274 case 'D':
275 if (isFreeBSDKPrintf)
276 k = ConversionSpecifier::FreeBSDDArg; // void * followed by char *
277 else if (Target.getTriple().isOSDarwin())
278 k = ConversionSpecifier::DArg;
279 break;
280 case 'O':
281 if (Target.getTriple().isOSDarwin())
282 k = ConversionSpecifier::OArg;
283 break;
284 case 'U':
285 if (Target.getTriple().isOSDarwin())
286 k = ConversionSpecifier::UArg;
287 break;
288 // MS specific.
289 case 'Z':
290 if (Target.getTriple().isOSMSVCRT())
291 k = ConversionSpecifier::ZArg;
292 }
293
294 // Check to see if we used the Objective-C modifier flags with
295 // a conversion specifier other than '@'.
296 if (k != ConversionSpecifier::ObjCObjArg &&
297 k != ConversionSpecifier::InvalidSpecifier &&
298 ObjCModifierFlagsStart) {
299 H.HandleObjCFlagsWithNonObjCConversion(ObjCModifierFlagsStart,
300 ObjCModifierFlagsEnd + 1,
301 conversionPosition);
302 return true;
303 }
304
305 PrintfConversionSpecifier CS(conversionPosition, k);
306 FS.setConversionSpecifier(CS);
307 if (CS.consumesDataArgument() && !FS.usesPositionalArg())
308 FS.setArgIndex(argIndex++);
309 // FreeBSD kernel specific.
310 if (k == ConversionSpecifier::FreeBSDbArg ||
311 k == ConversionSpecifier::FreeBSDDArg)
312 argIndex++;
313
314 if (k == ConversionSpecifier::InvalidSpecifier) {
315 // Assume the conversion takes one argument.
316 return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, I - Start);
317 }
318 return PrintfSpecifierResult(Start, FS);
319 }
320
ParsePrintfString(FormatStringHandler & H,const char * I,const char * E,const LangOptions & LO,const TargetInfo & Target,bool isFreeBSDKPrintf)321 bool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H,
322 const char *I,
323 const char *E,
324 const LangOptions &LO,
325 const TargetInfo &Target,
326 bool isFreeBSDKPrintf) {
327
328 unsigned argIndex = 0;
329
330 // Keep looking for a format specifier until we have exhausted the string.
331 while (I != E) {
332 const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
333 LO, Target, true,
334 isFreeBSDKPrintf);
335 // Did a fail-stop error of any kind occur when parsing the specifier?
336 // If so, don't do any more processing.
337 if (FSR.shouldStop())
338 return true;
339 // Did we exhaust the string or encounter an error that
340 // we can recover from?
341 if (!FSR.hasValue())
342 continue;
343 // We have a format specifier. Pass it to the callback.
344 if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),
345 I - FSR.getStart()))
346 return true;
347 }
348 assert(I == E && "Format string not exhausted");
349 return false;
350 }
351
ParseFormatStringHasSArg(const char * I,const char * E,const LangOptions & LO,const TargetInfo & Target)352 bool clang::analyze_format_string::ParseFormatStringHasSArg(const char *I,
353 const char *E,
354 const LangOptions &LO,
355 const TargetInfo &Target) {
356
357 unsigned argIndex = 0;
358
359 // Keep looking for a %s format specifier until we have exhausted the string.
360 FormatStringHandler H;
361 while (I != E) {
362 const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
363 LO, Target, false,
364 false);
365 // Did a fail-stop error of any kind occur when parsing the specifier?
366 // If so, don't do any more processing.
367 if (FSR.shouldStop())
368 return false;
369 // Did we exhaust the string or encounter an error that
370 // we can recover from?
371 if (!FSR.hasValue())
372 continue;
373 const analyze_printf::PrintfSpecifier &FS = FSR.getValue();
374 // Return true if this a %s format specifier.
375 if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::Kind::sArg)
376 return true;
377 }
378 return false;
379 }
380
381 //===----------------------------------------------------------------------===//
382 // Methods on PrintfSpecifier.
383 //===----------------------------------------------------------------------===//
384
getArgType(ASTContext & Ctx,bool IsObjCLiteral) const385 ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
386 bool IsObjCLiteral) const {
387 const PrintfConversionSpecifier &CS = getConversionSpecifier();
388
389 if (!CS.consumesDataArgument())
390 return ArgType::Invalid();
391
392 if (CS.getKind() == ConversionSpecifier::cArg)
393 switch (LM.getKind()) {
394 case LengthModifier::None:
395 return Ctx.IntTy;
396 case LengthModifier::AsLong:
397 case LengthModifier::AsWide:
398 return ArgType(ArgType::WIntTy, "wint_t");
399 case LengthModifier::AsShort:
400 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
401 return Ctx.IntTy;
402 default:
403 return ArgType::Invalid();
404 }
405
406 if (CS.isIntArg())
407 switch (LM.getKind()) {
408 case LengthModifier::AsLongDouble:
409 // GNU extension.
410 return Ctx.LongLongTy;
411 case LengthModifier::None:
412 return Ctx.IntTy;
413 case LengthModifier::AsInt32:
414 return ArgType(Ctx.IntTy, "__int32");
415 case LengthModifier::AsChar: return ArgType::AnyCharTy;
416 case LengthModifier::AsShort: return Ctx.ShortTy;
417 case LengthModifier::AsLong: return Ctx.LongTy;
418 case LengthModifier::AsLongLong:
419 case LengthModifier::AsQuad:
420 return Ctx.LongLongTy;
421 case LengthModifier::AsInt64:
422 return ArgType(Ctx.LongLongTy, "__int64");
423 case LengthModifier::AsIntMax:
424 return ArgType(Ctx.getIntMaxType(), "intmax_t");
425 case LengthModifier::AsSizeT:
426 // FIXME: How to get the corresponding signed version of size_t?
427 return ArgType();
428 case LengthModifier::AsInt3264:
429 return Ctx.getTargetInfo().getTriple().isArch64Bit()
430 ? ArgType(Ctx.LongLongTy, "__int64")
431 : ArgType(Ctx.IntTy, "__int32");
432 case LengthModifier::AsPtrDiff:
433 return ArgType(Ctx.getPointerDiffType(), "ptrdiff_t");
434 case LengthModifier::AsAllocate:
435 case LengthModifier::AsMAllocate:
436 case LengthModifier::AsWide:
437 return ArgType::Invalid();
438 }
439
440 if (CS.isUIntArg())
441 switch (LM.getKind()) {
442 case LengthModifier::AsLongDouble:
443 // GNU extension.
444 return Ctx.UnsignedLongLongTy;
445 case LengthModifier::None:
446 return Ctx.UnsignedIntTy;
447 case LengthModifier::AsInt32:
448 return ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
449 case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
450 case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
451 case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
452 case LengthModifier::AsLongLong:
453 case LengthModifier::AsQuad:
454 return Ctx.UnsignedLongLongTy;
455 case LengthModifier::AsInt64:
456 return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64");
457 case LengthModifier::AsIntMax:
458 return ArgType(Ctx.getUIntMaxType(), "uintmax_t");
459 case LengthModifier::AsSizeT:
460 return ArgType(Ctx.getSizeType(), "size_t");
461 case LengthModifier::AsInt3264:
462 return Ctx.getTargetInfo().getTriple().isArch64Bit()
463 ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")
464 : ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
465 case LengthModifier::AsPtrDiff:
466 // FIXME: How to get the corresponding unsigned
467 // version of ptrdiff_t?
468 return ArgType();
469 case LengthModifier::AsAllocate:
470 case LengthModifier::AsMAllocate:
471 case LengthModifier::AsWide:
472 return ArgType::Invalid();
473 }
474
475 if (CS.isDoubleArg()) {
476 if (LM.getKind() == LengthModifier::AsLongDouble)
477 return Ctx.LongDoubleTy;
478 return Ctx.DoubleTy;
479 }
480
481 if (CS.getKind() == ConversionSpecifier::nArg) {
482 switch (LM.getKind()) {
483 case LengthModifier::None:
484 return ArgType::PtrTo(Ctx.IntTy);
485 case LengthModifier::AsChar:
486 return ArgType::PtrTo(Ctx.SignedCharTy);
487 case LengthModifier::AsShort:
488 return ArgType::PtrTo(Ctx.ShortTy);
489 case LengthModifier::AsLong:
490 return ArgType::PtrTo(Ctx.LongTy);
491 case LengthModifier::AsLongLong:
492 case LengthModifier::AsQuad:
493 return ArgType::PtrTo(Ctx.LongLongTy);
494 case LengthModifier::AsIntMax:
495 return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
496 case LengthModifier::AsSizeT:
497 return ArgType(); // FIXME: ssize_t
498 case LengthModifier::AsPtrDiff:
499 return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
500 case LengthModifier::AsLongDouble:
501 return ArgType(); // FIXME: Is this a known extension?
502 case LengthModifier::AsAllocate:
503 case LengthModifier::AsMAllocate:
504 case LengthModifier::AsInt32:
505 case LengthModifier::AsInt3264:
506 case LengthModifier::AsInt64:
507 case LengthModifier::AsWide:
508 return ArgType::Invalid();
509 }
510 }
511
512 switch (CS.getKind()) {
513 case ConversionSpecifier::sArg:
514 if (LM.getKind() == LengthModifier::AsWideChar) {
515 if (IsObjCLiteral)
516 return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
517 "const unichar *");
518 return ArgType(ArgType::WCStrTy, "wchar_t *");
519 }
520 if (LM.getKind() == LengthModifier::AsWide)
521 return ArgType(ArgType::WCStrTy, "wchar_t *");
522 return ArgType::CStrTy;
523 case ConversionSpecifier::SArg:
524 if (IsObjCLiteral)
525 return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
526 "const unichar *");
527 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
528 LM.getKind() == LengthModifier::AsShort)
529 return ArgType::CStrTy;
530 return ArgType(ArgType::WCStrTy, "wchar_t *");
531 case ConversionSpecifier::CArg:
532 if (IsObjCLiteral)
533 return ArgType(Ctx.UnsignedShortTy, "unichar");
534 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
535 LM.getKind() == LengthModifier::AsShort)
536 return Ctx.IntTy;
537 return ArgType(Ctx.WideCharTy, "wchar_t");
538 case ConversionSpecifier::pArg:
539 return ArgType::CPointerTy;
540 case ConversionSpecifier::ObjCObjArg:
541 return ArgType::ObjCPointerTy;
542 default:
543 break;
544 }
545
546 // FIXME: Handle other cases.
547 return ArgType();
548 }
549
fixType(QualType QT,const LangOptions & LangOpt,ASTContext & Ctx,bool IsObjCLiteral)550 bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
551 ASTContext &Ctx, bool IsObjCLiteral) {
552 // %n is different from other conversion specifiers; don't try to fix it.
553 if (CS.getKind() == ConversionSpecifier::nArg)
554 return false;
555
556 // Handle Objective-C objects first. Note that while the '%@' specifier will
557 // not warn for structure pointer or void pointer arguments (because that's
558 // how CoreFoundation objects are implemented), we only show a fixit for '%@'
559 // if we know it's an object (block, id, class, or __attribute__((NSObject))).
560 if (QT->isObjCRetainableType()) {
561 if (!IsObjCLiteral)
562 return false;
563
564 CS.setKind(ConversionSpecifier::ObjCObjArg);
565
566 // Disable irrelevant flags
567 HasThousandsGrouping = false;
568 HasPlusPrefix = false;
569 HasSpacePrefix = false;
570 HasAlternativeForm = false;
571 HasLeadingZeroes = false;
572 Precision.setHowSpecified(OptionalAmount::NotSpecified);
573 LM.setKind(LengthModifier::None);
574
575 return true;
576 }
577
578 // Handle strings next (char *, wchar_t *)
579 if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
580 CS.setKind(ConversionSpecifier::sArg);
581
582 // Disable irrelevant flags
583 HasAlternativeForm = 0;
584 HasLeadingZeroes = 0;
585
586 // Set the long length modifier for wide characters
587 if (QT->getPointeeType()->isWideCharType())
588 LM.setKind(LengthModifier::AsWideChar);
589 else
590 LM.setKind(LengthModifier::None);
591
592 return true;
593 }
594
595 // If it's an enum, get its underlying type.
596 if (const EnumType *ETy = QT->getAs<EnumType>())
597 QT = ETy->getDecl()->getIntegerType();
598
599 // We can only work with builtin types.
600 const BuiltinType *BT = QT->getAs<BuiltinType>();
601 if (!BT)
602 return false;
603
604 // Set length modifier
605 switch (BT->getKind()) {
606 case BuiltinType::Bool:
607 case BuiltinType::WChar_U:
608 case BuiltinType::WChar_S:
609 case BuiltinType::Char16:
610 case BuiltinType::Char32:
611 case BuiltinType::UInt128:
612 case BuiltinType::Int128:
613 case BuiltinType::Half:
614 // Various types which are non-trivial to correct.
615 return false;
616
617 #define SIGNED_TYPE(Id, SingletonId)
618 #define UNSIGNED_TYPE(Id, SingletonId)
619 #define FLOATING_TYPE(Id, SingletonId)
620 #define BUILTIN_TYPE(Id, SingletonId) \
621 case BuiltinType::Id:
622 #include "clang/AST/BuiltinTypes.def"
623 // Misc other stuff which doesn't make sense here.
624 return false;
625
626 case BuiltinType::UInt:
627 case BuiltinType::Int:
628 case BuiltinType::Float:
629 case BuiltinType::Double:
630 LM.setKind(LengthModifier::None);
631 break;
632
633 case BuiltinType::Char_U:
634 case BuiltinType::UChar:
635 case BuiltinType::Char_S:
636 case BuiltinType::SChar:
637 LM.setKind(LengthModifier::AsChar);
638 break;
639
640 case BuiltinType::Short:
641 case BuiltinType::UShort:
642 LM.setKind(LengthModifier::AsShort);
643 break;
644
645 case BuiltinType::Long:
646 case BuiltinType::ULong:
647 LM.setKind(LengthModifier::AsLong);
648 break;
649
650 case BuiltinType::LongLong:
651 case BuiltinType::ULongLong:
652 LM.setKind(LengthModifier::AsLongLong);
653 break;
654
655 case BuiltinType::LongDouble:
656 LM.setKind(LengthModifier::AsLongDouble);
657 break;
658 }
659
660 // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
661 if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11))
662 namedTypeToLengthModifier(QT, LM);
663
664 // If fixing the length modifier was enough, we might be done.
665 if (hasValidLengthModifier(Ctx.getTargetInfo())) {
666 // If we're going to offer a fix anyway, make sure the sign matches.
667 switch (CS.getKind()) {
668 case ConversionSpecifier::uArg:
669 case ConversionSpecifier::UArg:
670 if (QT->isSignedIntegerType())
671 CS.setKind(clang::analyze_format_string::ConversionSpecifier::dArg);
672 break;
673 case ConversionSpecifier::dArg:
674 case ConversionSpecifier::DArg:
675 case ConversionSpecifier::iArg:
676 if (QT->isUnsignedIntegerType() && !HasPlusPrefix)
677 CS.setKind(clang::analyze_format_string::ConversionSpecifier::uArg);
678 break;
679 default:
680 // Other specifiers do not have signed/unsigned variants.
681 break;
682 }
683
684 const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral);
685 if (ATR.isValid() && ATR.matchesType(Ctx, QT))
686 return true;
687 }
688
689 // Set conversion specifier and disable any flags which do not apply to it.
690 // Let typedefs to char fall through to int, as %c is silly for uint8_t.
691 if (!isa<TypedefType>(QT) && QT->isCharType()) {
692 CS.setKind(ConversionSpecifier::cArg);
693 LM.setKind(LengthModifier::None);
694 Precision.setHowSpecified(OptionalAmount::NotSpecified);
695 HasAlternativeForm = 0;
696 HasLeadingZeroes = 0;
697 HasPlusPrefix = 0;
698 }
699 // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
700 else if (QT->isRealFloatingType()) {
701 CS.setKind(ConversionSpecifier::fArg);
702 }
703 else if (QT->isSignedIntegerType()) {
704 CS.setKind(ConversionSpecifier::dArg);
705 HasAlternativeForm = 0;
706 }
707 else if (QT->isUnsignedIntegerType()) {
708 CS.setKind(ConversionSpecifier::uArg);
709 HasAlternativeForm = 0;
710 HasPlusPrefix = 0;
711 } else {
712 llvm_unreachable("Unexpected type");
713 }
714
715 return true;
716 }
717
toString(raw_ostream & os) const718 void PrintfSpecifier::toString(raw_ostream &os) const {
719 // Whilst some features have no defined order, we are using the order
720 // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
721 os << "%";
722
723 // Positional args
724 if (usesPositionalArg()) {
725 os << getPositionalArgIndex() << "$";
726 }
727
728 // Conversion flags
729 if (IsLeftJustified) os << "-";
730 if (HasPlusPrefix) os << "+";
731 if (HasSpacePrefix) os << " ";
732 if (HasAlternativeForm) os << "#";
733 if (HasLeadingZeroes) os << "0";
734
735 // Minimum field width
736 FieldWidth.toString(os);
737 // Precision
738 Precision.toString(os);
739 // Length modifier
740 os << LM.toString();
741 // Conversion specifier
742 os << CS.toString();
743 }
744
hasValidPlusPrefix() const745 bool PrintfSpecifier::hasValidPlusPrefix() const {
746 if (!HasPlusPrefix)
747 return true;
748
749 // The plus prefix only makes sense for signed conversions
750 switch (CS.getKind()) {
751 case ConversionSpecifier::dArg:
752 case ConversionSpecifier::DArg:
753 case ConversionSpecifier::iArg:
754 case ConversionSpecifier::fArg:
755 case ConversionSpecifier::FArg:
756 case ConversionSpecifier::eArg:
757 case ConversionSpecifier::EArg:
758 case ConversionSpecifier::gArg:
759 case ConversionSpecifier::GArg:
760 case ConversionSpecifier::aArg:
761 case ConversionSpecifier::AArg:
762 case ConversionSpecifier::FreeBSDrArg:
763 case ConversionSpecifier::FreeBSDyArg:
764 return true;
765
766 default:
767 return false;
768 }
769 }
770
hasValidAlternativeForm() const771 bool PrintfSpecifier::hasValidAlternativeForm() const {
772 if (!HasAlternativeForm)
773 return true;
774
775 // Alternate form flag only valid with the oxXaAeEfFgG conversions
776 switch (CS.getKind()) {
777 case ConversionSpecifier::oArg:
778 case ConversionSpecifier::OArg:
779 case ConversionSpecifier::xArg:
780 case ConversionSpecifier::XArg:
781 case ConversionSpecifier::aArg:
782 case ConversionSpecifier::AArg:
783 case ConversionSpecifier::eArg:
784 case ConversionSpecifier::EArg:
785 case ConversionSpecifier::fArg:
786 case ConversionSpecifier::FArg:
787 case ConversionSpecifier::gArg:
788 case ConversionSpecifier::GArg:
789 case ConversionSpecifier::FreeBSDrArg:
790 case ConversionSpecifier::FreeBSDyArg:
791 return true;
792
793 default:
794 return false;
795 }
796 }
797
hasValidLeadingZeros() const798 bool PrintfSpecifier::hasValidLeadingZeros() const {
799 if (!HasLeadingZeroes)
800 return true;
801
802 // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
803 switch (CS.getKind()) {
804 case ConversionSpecifier::dArg:
805 case ConversionSpecifier::DArg:
806 case ConversionSpecifier::iArg:
807 case ConversionSpecifier::oArg:
808 case ConversionSpecifier::OArg:
809 case ConversionSpecifier::uArg:
810 case ConversionSpecifier::UArg:
811 case ConversionSpecifier::xArg:
812 case ConversionSpecifier::XArg:
813 case ConversionSpecifier::aArg:
814 case ConversionSpecifier::AArg:
815 case ConversionSpecifier::eArg:
816 case ConversionSpecifier::EArg:
817 case ConversionSpecifier::fArg:
818 case ConversionSpecifier::FArg:
819 case ConversionSpecifier::gArg:
820 case ConversionSpecifier::GArg:
821 case ConversionSpecifier::FreeBSDrArg:
822 case ConversionSpecifier::FreeBSDyArg:
823 return true;
824
825 default:
826 return false;
827 }
828 }
829
hasValidSpacePrefix() const830 bool PrintfSpecifier::hasValidSpacePrefix() const {
831 if (!HasSpacePrefix)
832 return true;
833
834 // The space prefix only makes sense for signed conversions
835 switch (CS.getKind()) {
836 case ConversionSpecifier::dArg:
837 case ConversionSpecifier::DArg:
838 case ConversionSpecifier::iArg:
839 case ConversionSpecifier::fArg:
840 case ConversionSpecifier::FArg:
841 case ConversionSpecifier::eArg:
842 case ConversionSpecifier::EArg:
843 case ConversionSpecifier::gArg:
844 case ConversionSpecifier::GArg:
845 case ConversionSpecifier::aArg:
846 case ConversionSpecifier::AArg:
847 case ConversionSpecifier::FreeBSDrArg:
848 case ConversionSpecifier::FreeBSDyArg:
849 return true;
850
851 default:
852 return false;
853 }
854 }
855
hasValidLeftJustified() const856 bool PrintfSpecifier::hasValidLeftJustified() const {
857 if (!IsLeftJustified)
858 return true;
859
860 // The left justified flag is valid for all conversions except n
861 switch (CS.getKind()) {
862 case ConversionSpecifier::nArg:
863 return false;
864
865 default:
866 return true;
867 }
868 }
869
hasValidThousandsGroupingPrefix() const870 bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
871 if (!HasThousandsGrouping)
872 return true;
873
874 switch (CS.getKind()) {
875 case ConversionSpecifier::dArg:
876 case ConversionSpecifier::DArg:
877 case ConversionSpecifier::iArg:
878 case ConversionSpecifier::uArg:
879 case ConversionSpecifier::UArg:
880 case ConversionSpecifier::fArg:
881 case ConversionSpecifier::FArg:
882 case ConversionSpecifier::gArg:
883 case ConversionSpecifier::GArg:
884 return true;
885 default:
886 return false;
887 }
888 }
889
hasValidPrecision() const890 bool PrintfSpecifier::hasValidPrecision() const {
891 if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
892 return true;
893
894 // Precision is only valid with the diouxXaAeEfFgGs conversions
895 switch (CS.getKind()) {
896 case ConversionSpecifier::dArg:
897 case ConversionSpecifier::DArg:
898 case ConversionSpecifier::iArg:
899 case ConversionSpecifier::oArg:
900 case ConversionSpecifier::OArg:
901 case ConversionSpecifier::uArg:
902 case ConversionSpecifier::UArg:
903 case ConversionSpecifier::xArg:
904 case ConversionSpecifier::XArg:
905 case ConversionSpecifier::aArg:
906 case ConversionSpecifier::AArg:
907 case ConversionSpecifier::eArg:
908 case ConversionSpecifier::EArg:
909 case ConversionSpecifier::fArg:
910 case ConversionSpecifier::FArg:
911 case ConversionSpecifier::gArg:
912 case ConversionSpecifier::GArg:
913 case ConversionSpecifier::sArg:
914 case ConversionSpecifier::FreeBSDrArg:
915 case ConversionSpecifier::FreeBSDyArg:
916 return true;
917
918 default:
919 return false;
920 }
921 }
hasValidFieldWidth() const922 bool PrintfSpecifier::hasValidFieldWidth() const {
923 if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
924 return true;
925
926 // The field width is valid for all conversions except n
927 switch (CS.getKind()) {
928 case ConversionSpecifier::nArg:
929 return false;
930
931 default:
932 return true;
933 }
934 }
935