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