clang API Documentation
00001 //== PrintfFormatString.cpp - Analysis of printf format strings --*- C++ -*-==// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // Handling of format string in printf and friends. The structure of format 00011 // strings for fprintf() are described in C99 7.19.6.1. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "clang/Analysis/Analyses/FormatString.h" 00016 #include "FormatStringParsing.h" 00017 #include "clang/Basic/TargetInfo.h" 00018 00019 using clang::analyze_format_string::ArgType; 00020 using clang::analyze_format_string::FormatStringHandler; 00021 using clang::analyze_format_string::LengthModifier; 00022 using clang::analyze_format_string::OptionalAmount; 00023 using clang::analyze_format_string::ConversionSpecifier; 00024 using clang::analyze_printf::PrintfSpecifier; 00025 00026 using namespace clang; 00027 00028 typedef clang::analyze_format_string::SpecifierResult<PrintfSpecifier> 00029 PrintfSpecifierResult; 00030 00031 //===----------------------------------------------------------------------===// 00032 // Methods for parsing format strings. 00033 //===----------------------------------------------------------------------===// 00034 00035 using analyze_format_string::ParseNonPositionAmount; 00036 00037 static bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS, 00038 const char *Start, const char *&Beg, const char *E, 00039 unsigned *argIndex) { 00040 if (argIndex) { 00041 FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex)); 00042 } else { 00043 const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E, 00044 analyze_format_string::PrecisionPos); 00045 if (Amt.isInvalid()) 00046 return true; 00047 FS.setPrecision(Amt); 00048 } 00049 return false; 00050 } 00051 00052 static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H, 00053 const char *&Beg, 00054 const char *E, 00055 unsigned &argIndex, 00056 const LangOptions &LO, 00057 const TargetInfo &Target, 00058 bool Warn) { 00059 00060 using namespace clang::analyze_format_string; 00061 using namespace clang::analyze_printf; 00062 00063 const char *I = Beg; 00064 const char *Start = nullptr; 00065 UpdateOnReturn <const char*> UpdateBeg(Beg, I); 00066 00067 // Look for a '%' character that indicates the start of a format specifier. 00068 for ( ; I != E ; ++I) { 00069 char c = *I; 00070 if (c == '\0') { 00071 // Detect spurious null characters, which are likely errors. 00072 H.HandleNullChar(I); 00073 return true; 00074 } 00075 if (c == '%') { 00076 Start = I++; // Record the start of the format specifier. 00077 break; 00078 } 00079 } 00080 00081 // No format specifier found? 00082 if (!Start) 00083 return false; 00084 00085 if (I == E) { 00086 // No more characters left? 00087 if (Warn) 00088 H.HandleIncompleteSpecifier(Start, E - Start); 00089 return true; 00090 } 00091 00092 PrintfSpecifier FS; 00093 if (ParseArgPosition(H, FS, Start, I, E)) 00094 return true; 00095 00096 if (I == E) { 00097 // No more characters left? 00098 if (Warn) 00099 H.HandleIncompleteSpecifier(Start, E - Start); 00100 return true; 00101 } 00102 00103 // Look for flags (if any). 00104 bool hasMore = true; 00105 for ( ; I != E; ++I) { 00106 switch (*I) { 00107 default: hasMore = false; break; 00108 case '\'': 00109 // FIXME: POSIX specific. Always accept? 00110 FS.setHasThousandsGrouping(I); 00111 break; 00112 case '-': FS.setIsLeftJustified(I); break; 00113 case '+': FS.setHasPlusPrefix(I); break; 00114 case ' ': FS.setHasSpacePrefix(I); break; 00115 case '#': FS.setHasAlternativeForm(I); break; 00116 case '0': FS.setHasLeadingZeros(I); break; 00117 } 00118 if (!hasMore) 00119 break; 00120 } 00121 00122 if (I == E) { 00123 // No more characters left? 00124 if (Warn) 00125 H.HandleIncompleteSpecifier(Start, E - Start); 00126 return true; 00127 } 00128 00129 // Look for the field width (if any). 00130 if (ParseFieldWidth(H, FS, Start, I, E, 00131 FS.usesPositionalArg() ? nullptr : &argIndex)) 00132 return true; 00133 00134 if (I == E) { 00135 // No more characters left? 00136 if (Warn) 00137 H.HandleIncompleteSpecifier(Start, E - Start); 00138 return true; 00139 } 00140 00141 // Look for the precision (if any). 00142 if (*I == '.') { 00143 ++I; 00144 if (I == E) { 00145 if (Warn) 00146 H.HandleIncompleteSpecifier(Start, E - Start); 00147 return true; 00148 } 00149 00150 if (ParsePrecision(H, FS, Start, I, E, 00151 FS.usesPositionalArg() ? nullptr : &argIndex)) 00152 return true; 00153 00154 if (I == E) { 00155 // No more characters left? 00156 if (Warn) 00157 H.HandleIncompleteSpecifier(Start, E - Start); 00158 return true; 00159 } 00160 } 00161 00162 // Look for the length modifier. 00163 if (ParseLengthModifier(FS, I, E, LO) && I == E) { 00164 // No more characters left? 00165 if (Warn) 00166 H.HandleIncompleteSpecifier(Start, E - Start); 00167 return true; 00168 } 00169 00170 if (*I == '\0') { 00171 // Detect spurious null characters, which are likely errors. 00172 H.HandleNullChar(I); 00173 return true; 00174 } 00175 00176 // Finally, look for the conversion specifier. 00177 const char *conversionPosition = I++; 00178 ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier; 00179 switch (*conversionPosition) { 00180 default: 00181 break; 00182 // C99: 7.19.6.1 (section 8). 00183 case '%': k = ConversionSpecifier::PercentArg; break; 00184 case 'A': k = ConversionSpecifier::AArg; break; 00185 case 'E': k = ConversionSpecifier::EArg; break; 00186 case 'F': k = ConversionSpecifier::FArg; break; 00187 case 'G': k = ConversionSpecifier::GArg; break; 00188 case 'X': k = ConversionSpecifier::XArg; break; 00189 case 'a': k = ConversionSpecifier::aArg; break; 00190 case 'c': k = ConversionSpecifier::cArg; break; 00191 case 'd': k = ConversionSpecifier::dArg; break; 00192 case 'e': k = ConversionSpecifier::eArg; break; 00193 case 'f': k = ConversionSpecifier::fArg; break; 00194 case 'g': k = ConversionSpecifier::gArg; break; 00195 case 'i': k = ConversionSpecifier::iArg; break; 00196 case 'n': k = ConversionSpecifier::nArg; break; 00197 case 'o': k = ConversionSpecifier::oArg; break; 00198 case 'p': k = ConversionSpecifier::pArg; break; 00199 case 's': k = ConversionSpecifier::sArg; break; 00200 case 'u': k = ConversionSpecifier::uArg; break; 00201 case 'x': k = ConversionSpecifier::xArg; break; 00202 // POSIX specific. 00203 case 'C': k = ConversionSpecifier::CArg; break; 00204 case 'S': k = ConversionSpecifier::SArg; break; 00205 // Objective-C. 00206 case '@': k = ConversionSpecifier::ObjCObjArg; break; 00207 // Glibc specific. 00208 case 'm': k = ConversionSpecifier::PrintErrno; break; 00209 // Apple-specific. 00210 case 'D': 00211 if (Target.getTriple().isOSDarwin()) 00212 k = ConversionSpecifier::DArg; 00213 break; 00214 case 'O': 00215 if (Target.getTriple().isOSDarwin()) 00216 k = ConversionSpecifier::OArg; 00217 break; 00218 case 'U': 00219 if (Target.getTriple().isOSDarwin()) 00220 k = ConversionSpecifier::UArg; 00221 break; 00222 // MS specific. 00223 case 'Z': 00224 if (Target.getTriple().isOSMSVCRT()) 00225 k = ConversionSpecifier::ZArg; 00226 } 00227 PrintfConversionSpecifier CS(conversionPosition, k); 00228 FS.setConversionSpecifier(CS); 00229 if (CS.consumesDataArgument() && !FS.usesPositionalArg()) 00230 FS.setArgIndex(argIndex++); 00231 00232 if (k == ConversionSpecifier::InvalidSpecifier) { 00233 // Assume the conversion takes one argument. 00234 return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, I - Start); 00235 } 00236 return PrintfSpecifierResult(Start, FS); 00237 } 00238 00239 bool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H, 00240 const char *I, 00241 const char *E, 00242 const LangOptions &LO, 00243 const TargetInfo &Target) { 00244 00245 unsigned argIndex = 0; 00246 00247 // Keep looking for a format specifier until we have exhausted the string. 00248 while (I != E) { 00249 const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex, 00250 LO, Target, true); 00251 // Did a fail-stop error of any kind occur when parsing the specifier? 00252 // If so, don't do any more processing. 00253 if (FSR.shouldStop()) 00254 return true; 00255 // Did we exhaust the string or encounter an error that 00256 // we can recover from? 00257 if (!FSR.hasValue()) 00258 continue; 00259 // We have a format specifier. Pass it to the callback. 00260 if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(), 00261 I - FSR.getStart())) 00262 return true; 00263 } 00264 assert(I == E && "Format string not exhausted"); 00265 return false; 00266 } 00267 00268 bool clang::analyze_format_string::ParseFormatStringHasSArg(const char *I, 00269 const char *E, 00270 const LangOptions &LO, 00271 const TargetInfo &Target) { 00272 00273 unsigned argIndex = 0; 00274 00275 // Keep looking for a %s format specifier until we have exhausted the string. 00276 FormatStringHandler H; 00277 while (I != E) { 00278 const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex, 00279 LO, Target, false); 00280 // Did a fail-stop error of any kind occur when parsing the specifier? 00281 // If so, don't do any more processing. 00282 if (FSR.shouldStop()) 00283 return false; 00284 // Did we exhaust the string or encounter an error that 00285 // we can recover from? 00286 if (!FSR.hasValue()) 00287 continue; 00288 const analyze_printf::PrintfSpecifier &FS = FSR.getValue(); 00289 // Return true if this a %s format specifier. 00290 if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::Kind::sArg) 00291 return true; 00292 } 00293 return false; 00294 } 00295 00296 //===----------------------------------------------------------------------===// 00297 // Methods on PrintfSpecifier. 00298 //===----------------------------------------------------------------------===// 00299 00300 ArgType PrintfSpecifier::getArgType(ASTContext &Ctx, 00301 bool IsObjCLiteral) const { 00302 const PrintfConversionSpecifier &CS = getConversionSpecifier(); 00303 00304 if (!CS.consumesDataArgument()) 00305 return ArgType::Invalid(); 00306 00307 if (CS.getKind() == ConversionSpecifier::cArg) 00308 switch (LM.getKind()) { 00309 case LengthModifier::None: 00310 return Ctx.IntTy; 00311 case LengthModifier::AsLong: 00312 case LengthModifier::AsWide: 00313 return ArgType(ArgType::WIntTy, "wint_t"); 00314 case LengthModifier::AsShort: 00315 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT()) 00316 return Ctx.IntTy; 00317 default: 00318 return ArgType::Invalid(); 00319 } 00320 00321 if (CS.isIntArg()) 00322 switch (LM.getKind()) { 00323 case LengthModifier::AsLongDouble: 00324 // GNU extension. 00325 return Ctx.LongLongTy; 00326 case LengthModifier::None: 00327 return Ctx.IntTy; 00328 case LengthModifier::AsInt32: 00329 return ArgType(Ctx.IntTy, "__int32"); 00330 case LengthModifier::AsChar: return ArgType::AnyCharTy; 00331 case LengthModifier::AsShort: return Ctx.ShortTy; 00332 case LengthModifier::AsLong: return Ctx.LongTy; 00333 case LengthModifier::AsLongLong: 00334 case LengthModifier::AsQuad: 00335 return Ctx.LongLongTy; 00336 case LengthModifier::AsInt64: 00337 return ArgType(Ctx.LongLongTy, "__int64"); 00338 case LengthModifier::AsIntMax: 00339 return ArgType(Ctx.getIntMaxType(), "intmax_t"); 00340 case LengthModifier::AsSizeT: 00341 // FIXME: How to get the corresponding signed version of size_t? 00342 return ArgType(); 00343 case LengthModifier::AsInt3264: 00344 return Ctx.getTargetInfo().getTriple().isArch64Bit() 00345 ? ArgType(Ctx.LongLongTy, "__int64") 00346 : ArgType(Ctx.IntTy, "__int32"); 00347 case LengthModifier::AsPtrDiff: 00348 return ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"); 00349 case LengthModifier::AsAllocate: 00350 case LengthModifier::AsMAllocate: 00351 case LengthModifier::AsWide: 00352 return ArgType::Invalid(); 00353 } 00354 00355 if (CS.isUIntArg()) 00356 switch (LM.getKind()) { 00357 case LengthModifier::AsLongDouble: 00358 // GNU extension. 00359 return Ctx.UnsignedLongLongTy; 00360 case LengthModifier::None: 00361 return Ctx.UnsignedIntTy; 00362 case LengthModifier::AsInt32: 00363 return ArgType(Ctx.UnsignedIntTy, "unsigned __int32"); 00364 case LengthModifier::AsChar: return Ctx.UnsignedCharTy; 00365 case LengthModifier::AsShort: return Ctx.UnsignedShortTy; 00366 case LengthModifier::AsLong: return Ctx.UnsignedLongTy; 00367 case LengthModifier::AsLongLong: 00368 case LengthModifier::AsQuad: 00369 return Ctx.UnsignedLongLongTy; 00370 case LengthModifier::AsInt64: 00371 return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64"); 00372 case LengthModifier::AsIntMax: 00373 return ArgType(Ctx.getUIntMaxType(), "uintmax_t"); 00374 case LengthModifier::AsSizeT: 00375 return ArgType(Ctx.getSizeType(), "size_t"); 00376 case LengthModifier::AsInt3264: 00377 return Ctx.getTargetInfo().getTriple().isArch64Bit() 00378 ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64") 00379 : ArgType(Ctx.UnsignedIntTy, "unsigned __int32"); 00380 case LengthModifier::AsPtrDiff: 00381 // FIXME: How to get the corresponding unsigned 00382 // version of ptrdiff_t? 00383 return ArgType(); 00384 case LengthModifier::AsAllocate: 00385 case LengthModifier::AsMAllocate: 00386 case LengthModifier::AsWide: 00387 return ArgType::Invalid(); 00388 } 00389 00390 if (CS.isDoubleArg()) { 00391 if (LM.getKind() == LengthModifier::AsLongDouble) 00392 return Ctx.LongDoubleTy; 00393 return Ctx.DoubleTy; 00394 } 00395 00396 if (CS.getKind() == ConversionSpecifier::nArg) { 00397 switch (LM.getKind()) { 00398 case LengthModifier::None: 00399 return ArgType::PtrTo(Ctx.IntTy); 00400 case LengthModifier::AsChar: 00401 return ArgType::PtrTo(Ctx.SignedCharTy); 00402 case LengthModifier::AsShort: 00403 return ArgType::PtrTo(Ctx.ShortTy); 00404 case LengthModifier::AsLong: 00405 return ArgType::PtrTo(Ctx.LongTy); 00406 case LengthModifier::AsLongLong: 00407 case LengthModifier::AsQuad: 00408 return ArgType::PtrTo(Ctx.LongLongTy); 00409 case LengthModifier::AsIntMax: 00410 return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t")); 00411 case LengthModifier::AsSizeT: 00412 return ArgType(); // FIXME: ssize_t 00413 case LengthModifier::AsPtrDiff: 00414 return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t")); 00415 case LengthModifier::AsLongDouble: 00416 return ArgType(); // FIXME: Is this a known extension? 00417 case LengthModifier::AsAllocate: 00418 case LengthModifier::AsMAllocate: 00419 case LengthModifier::AsInt32: 00420 case LengthModifier::AsInt3264: 00421 case LengthModifier::AsInt64: 00422 case LengthModifier::AsWide: 00423 return ArgType::Invalid(); 00424 } 00425 } 00426 00427 switch (CS.getKind()) { 00428 case ConversionSpecifier::sArg: 00429 if (LM.getKind() == LengthModifier::AsWideChar) { 00430 if (IsObjCLiteral) 00431 return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()), 00432 "const unichar *"); 00433 return ArgType(ArgType::WCStrTy, "wchar_t *"); 00434 } 00435 if (LM.getKind() == LengthModifier::AsWide) 00436 return ArgType(ArgType::WCStrTy, "wchar_t *"); 00437 return ArgType::CStrTy; 00438 case ConversionSpecifier::SArg: 00439 if (IsObjCLiteral) 00440 return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()), 00441 "const unichar *"); 00442 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() && 00443 LM.getKind() == LengthModifier::AsShort) 00444 return ArgType::CStrTy; 00445 return ArgType(ArgType::WCStrTy, "wchar_t *"); 00446 case ConversionSpecifier::CArg: 00447 if (IsObjCLiteral) 00448 return ArgType(Ctx.UnsignedShortTy, "unichar"); 00449 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() && 00450 LM.getKind() == LengthModifier::AsShort) 00451 return Ctx.IntTy; 00452 return ArgType(Ctx.WideCharTy, "wchar_t"); 00453 case ConversionSpecifier::pArg: 00454 return ArgType::CPointerTy; 00455 case ConversionSpecifier::ObjCObjArg: 00456 return ArgType::ObjCPointerTy; 00457 default: 00458 break; 00459 } 00460 00461 // FIXME: Handle other cases. 00462 return ArgType(); 00463 } 00464 00465 bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt, 00466 ASTContext &Ctx, bool IsObjCLiteral) { 00467 // %n is different from other conversion specifiers; don't try to fix it. 00468 if (CS.getKind() == ConversionSpecifier::nArg) 00469 return false; 00470 00471 // Handle Objective-C objects first. Note that while the '%@' specifier will 00472 // not warn for structure pointer or void pointer arguments (because that's 00473 // how CoreFoundation objects are implemented), we only show a fixit for '%@' 00474 // if we know it's an object (block, id, class, or __attribute__((NSObject))). 00475 if (QT->isObjCRetainableType()) { 00476 if (!IsObjCLiteral) 00477 return false; 00478 00479 CS.setKind(ConversionSpecifier::ObjCObjArg); 00480 00481 // Disable irrelevant flags 00482 HasThousandsGrouping = false; 00483 HasPlusPrefix = false; 00484 HasSpacePrefix = false; 00485 HasAlternativeForm = false; 00486 HasLeadingZeroes = false; 00487 Precision.setHowSpecified(OptionalAmount::NotSpecified); 00488 LM.setKind(LengthModifier::None); 00489 00490 return true; 00491 } 00492 00493 // Handle strings next (char *, wchar_t *) 00494 if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) { 00495 CS.setKind(ConversionSpecifier::sArg); 00496 00497 // Disable irrelevant flags 00498 HasAlternativeForm = 0; 00499 HasLeadingZeroes = 0; 00500 00501 // Set the long length modifier for wide characters 00502 if (QT->getPointeeType()->isWideCharType()) 00503 LM.setKind(LengthModifier::AsWideChar); 00504 else 00505 LM.setKind(LengthModifier::None); 00506 00507 return true; 00508 } 00509 00510 // If it's an enum, get its underlying type. 00511 if (const EnumType *ETy = QT->getAs<EnumType>()) 00512 QT = ETy->getDecl()->getIntegerType(); 00513 00514 // We can only work with builtin types. 00515 const BuiltinType *BT = QT->getAs<BuiltinType>(); 00516 if (!BT) 00517 return false; 00518 00519 // Set length modifier 00520 switch (BT->getKind()) { 00521 case BuiltinType::Bool: 00522 case BuiltinType::WChar_U: 00523 case BuiltinType::WChar_S: 00524 case BuiltinType::Char16: 00525 case BuiltinType::Char32: 00526 case BuiltinType::UInt128: 00527 case BuiltinType::Int128: 00528 case BuiltinType::Half: 00529 // Various types which are non-trivial to correct. 00530 return false; 00531 00532 #define SIGNED_TYPE(Id, SingletonId) 00533 #define UNSIGNED_TYPE(Id, SingletonId) 00534 #define FLOATING_TYPE(Id, SingletonId) 00535 #define BUILTIN_TYPE(Id, SingletonId) \ 00536 case BuiltinType::Id: 00537 #include "clang/AST/BuiltinTypes.def" 00538 // Misc other stuff which doesn't make sense here. 00539 return false; 00540 00541 case BuiltinType::UInt: 00542 case BuiltinType::Int: 00543 case BuiltinType::Float: 00544 case BuiltinType::Double: 00545 LM.setKind(LengthModifier::None); 00546 break; 00547 00548 case BuiltinType::Char_U: 00549 case BuiltinType::UChar: 00550 case BuiltinType::Char_S: 00551 case BuiltinType::SChar: 00552 LM.setKind(LengthModifier::AsChar); 00553 break; 00554 00555 case BuiltinType::Short: 00556 case BuiltinType::UShort: 00557 LM.setKind(LengthModifier::AsShort); 00558 break; 00559 00560 case BuiltinType::Long: 00561 case BuiltinType::ULong: 00562 LM.setKind(LengthModifier::AsLong); 00563 break; 00564 00565 case BuiltinType::LongLong: 00566 case BuiltinType::ULongLong: 00567 LM.setKind(LengthModifier::AsLongLong); 00568 break; 00569 00570 case BuiltinType::LongDouble: 00571 LM.setKind(LengthModifier::AsLongDouble); 00572 break; 00573 } 00574 00575 // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99. 00576 if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11)) 00577 namedTypeToLengthModifier(QT, LM); 00578 00579 // If fixing the length modifier was enough, we might be done. 00580 if (hasValidLengthModifier(Ctx.getTargetInfo())) { 00581 // If we're going to offer a fix anyway, make sure the sign matches. 00582 switch (CS.getKind()) { 00583 case ConversionSpecifier::uArg: 00584 case ConversionSpecifier::UArg: 00585 if (QT->isSignedIntegerType()) 00586 CS.setKind(clang::analyze_format_string::ConversionSpecifier::dArg); 00587 break; 00588 case ConversionSpecifier::dArg: 00589 case ConversionSpecifier::DArg: 00590 case ConversionSpecifier::iArg: 00591 if (QT->isUnsignedIntegerType() && !HasPlusPrefix) 00592 CS.setKind(clang::analyze_format_string::ConversionSpecifier::uArg); 00593 break; 00594 default: 00595 // Other specifiers do not have signed/unsigned variants. 00596 break; 00597 } 00598 00599 const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral); 00600 if (ATR.isValid() && ATR.matchesType(Ctx, QT)) 00601 return true; 00602 } 00603 00604 // Set conversion specifier and disable any flags which do not apply to it. 00605 // Let typedefs to char fall through to int, as %c is silly for uint8_t. 00606 if (!isa<TypedefType>(QT) && QT->isCharType()) { 00607 CS.setKind(ConversionSpecifier::cArg); 00608 LM.setKind(LengthModifier::None); 00609 Precision.setHowSpecified(OptionalAmount::NotSpecified); 00610 HasAlternativeForm = 0; 00611 HasLeadingZeroes = 0; 00612 HasPlusPrefix = 0; 00613 } 00614 // Test for Floating type first as LongDouble can pass isUnsignedIntegerType 00615 else if (QT->isRealFloatingType()) { 00616 CS.setKind(ConversionSpecifier::fArg); 00617 } 00618 else if (QT->isSignedIntegerType()) { 00619 CS.setKind(ConversionSpecifier::dArg); 00620 HasAlternativeForm = 0; 00621 } 00622 else if (QT->isUnsignedIntegerType()) { 00623 CS.setKind(ConversionSpecifier::uArg); 00624 HasAlternativeForm = 0; 00625 HasPlusPrefix = 0; 00626 } else { 00627 llvm_unreachable("Unexpected type"); 00628 } 00629 00630 return true; 00631 } 00632 00633 void PrintfSpecifier::toString(raw_ostream &os) const { 00634 // Whilst some features have no defined order, we are using the order 00635 // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1) 00636 os << "%"; 00637 00638 // Positional args 00639 if (usesPositionalArg()) { 00640 os << getPositionalArgIndex() << "$"; 00641 } 00642 00643 // Conversion flags 00644 if (IsLeftJustified) os << "-"; 00645 if (HasPlusPrefix) os << "+"; 00646 if (HasSpacePrefix) os << " "; 00647 if (HasAlternativeForm) os << "#"; 00648 if (HasLeadingZeroes) os << "0"; 00649 00650 // Minimum field width 00651 FieldWidth.toString(os); 00652 // Precision 00653 Precision.toString(os); 00654 // Length modifier 00655 os << LM.toString(); 00656 // Conversion specifier 00657 os << CS.toString(); 00658 } 00659 00660 bool PrintfSpecifier::hasValidPlusPrefix() const { 00661 if (!HasPlusPrefix) 00662 return true; 00663 00664 // The plus prefix only makes sense for signed conversions 00665 switch (CS.getKind()) { 00666 case ConversionSpecifier::dArg: 00667 case ConversionSpecifier::DArg: 00668 case ConversionSpecifier::iArg: 00669 case ConversionSpecifier::fArg: 00670 case ConversionSpecifier::FArg: 00671 case ConversionSpecifier::eArg: 00672 case ConversionSpecifier::EArg: 00673 case ConversionSpecifier::gArg: 00674 case ConversionSpecifier::GArg: 00675 case ConversionSpecifier::aArg: 00676 case ConversionSpecifier::AArg: 00677 return true; 00678 00679 default: 00680 return false; 00681 } 00682 } 00683 00684 bool PrintfSpecifier::hasValidAlternativeForm() const { 00685 if (!HasAlternativeForm) 00686 return true; 00687 00688 // Alternate form flag only valid with the oxXaAeEfFgG conversions 00689 switch (CS.getKind()) { 00690 case ConversionSpecifier::oArg: 00691 case ConversionSpecifier::OArg: 00692 case ConversionSpecifier::xArg: 00693 case ConversionSpecifier::XArg: 00694 case ConversionSpecifier::aArg: 00695 case ConversionSpecifier::AArg: 00696 case ConversionSpecifier::eArg: 00697 case ConversionSpecifier::EArg: 00698 case ConversionSpecifier::fArg: 00699 case ConversionSpecifier::FArg: 00700 case ConversionSpecifier::gArg: 00701 case ConversionSpecifier::GArg: 00702 return true; 00703 00704 default: 00705 return false; 00706 } 00707 } 00708 00709 bool PrintfSpecifier::hasValidLeadingZeros() const { 00710 if (!HasLeadingZeroes) 00711 return true; 00712 00713 // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions 00714 switch (CS.getKind()) { 00715 case ConversionSpecifier::dArg: 00716 case ConversionSpecifier::DArg: 00717 case ConversionSpecifier::iArg: 00718 case ConversionSpecifier::oArg: 00719 case ConversionSpecifier::OArg: 00720 case ConversionSpecifier::uArg: 00721 case ConversionSpecifier::UArg: 00722 case ConversionSpecifier::xArg: 00723 case ConversionSpecifier::XArg: 00724 case ConversionSpecifier::aArg: 00725 case ConversionSpecifier::AArg: 00726 case ConversionSpecifier::eArg: 00727 case ConversionSpecifier::EArg: 00728 case ConversionSpecifier::fArg: 00729 case ConversionSpecifier::FArg: 00730 case ConversionSpecifier::gArg: 00731 case ConversionSpecifier::GArg: 00732 return true; 00733 00734 default: 00735 return false; 00736 } 00737 } 00738 00739 bool PrintfSpecifier::hasValidSpacePrefix() const { 00740 if (!HasSpacePrefix) 00741 return true; 00742 00743 // The space prefix only makes sense for signed conversions 00744 switch (CS.getKind()) { 00745 case ConversionSpecifier::dArg: 00746 case ConversionSpecifier::DArg: 00747 case ConversionSpecifier::iArg: 00748 case ConversionSpecifier::fArg: 00749 case ConversionSpecifier::FArg: 00750 case ConversionSpecifier::eArg: 00751 case ConversionSpecifier::EArg: 00752 case ConversionSpecifier::gArg: 00753 case ConversionSpecifier::GArg: 00754 case ConversionSpecifier::aArg: 00755 case ConversionSpecifier::AArg: 00756 return true; 00757 00758 default: 00759 return false; 00760 } 00761 } 00762 00763 bool PrintfSpecifier::hasValidLeftJustified() const { 00764 if (!IsLeftJustified) 00765 return true; 00766 00767 // The left justified flag is valid for all conversions except n 00768 switch (CS.getKind()) { 00769 case ConversionSpecifier::nArg: 00770 return false; 00771 00772 default: 00773 return true; 00774 } 00775 } 00776 00777 bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const { 00778 if (!HasThousandsGrouping) 00779 return true; 00780 00781 switch (CS.getKind()) { 00782 case ConversionSpecifier::dArg: 00783 case ConversionSpecifier::DArg: 00784 case ConversionSpecifier::iArg: 00785 case ConversionSpecifier::uArg: 00786 case ConversionSpecifier::UArg: 00787 case ConversionSpecifier::fArg: 00788 case ConversionSpecifier::FArg: 00789 case ConversionSpecifier::gArg: 00790 case ConversionSpecifier::GArg: 00791 return true; 00792 default: 00793 return false; 00794 } 00795 } 00796 00797 bool PrintfSpecifier::hasValidPrecision() const { 00798 if (Precision.getHowSpecified() == OptionalAmount::NotSpecified) 00799 return true; 00800 00801 // Precision is only valid with the diouxXaAeEfFgGs conversions 00802 switch (CS.getKind()) { 00803 case ConversionSpecifier::dArg: 00804 case ConversionSpecifier::DArg: 00805 case ConversionSpecifier::iArg: 00806 case ConversionSpecifier::oArg: 00807 case ConversionSpecifier::OArg: 00808 case ConversionSpecifier::uArg: 00809 case ConversionSpecifier::UArg: 00810 case ConversionSpecifier::xArg: 00811 case ConversionSpecifier::XArg: 00812 case ConversionSpecifier::aArg: 00813 case ConversionSpecifier::AArg: 00814 case ConversionSpecifier::eArg: 00815 case ConversionSpecifier::EArg: 00816 case ConversionSpecifier::fArg: 00817 case ConversionSpecifier::FArg: 00818 case ConversionSpecifier::gArg: 00819 case ConversionSpecifier::GArg: 00820 case ConversionSpecifier::sArg: 00821 return true; 00822 00823 default: 00824 return false; 00825 } 00826 } 00827 bool PrintfSpecifier::hasValidFieldWidth() const { 00828 if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified) 00829 return true; 00830 00831 // The field width is valid for all conversions except n 00832 switch (CS.getKind()) { 00833 case ConversionSpecifier::nArg: 00834 return false; 00835 00836 default: 00837 return true; 00838 } 00839 }