PrintfFormatString.cpp revision 360784
1139804Simp//== PrintfFormatString.cpp - Analysis of printf format strings --*- C++ -*-==// 2139013Sdavidxu// 3112904Sjeff// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4112904Sjeff// See https://llvm.org/LICENSE.txt for license information. 5112904Sjeff// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6112904Sjeff// 7112904Sjeff//===----------------------------------------------------------------------===// 8112904Sjeff// 9112904Sjeff// Handling of format string in printf and friends. The structure of format 10112904Sjeff// strings for fprintf() are described in C99 7.19.6.1. 11112904Sjeff// 12112904Sjeff//===----------------------------------------------------------------------===// 13112904Sjeff 14112904Sjeff#include "clang/AST/FormatString.h" 15112904Sjeff#include "clang/AST/OSLog.h" 16112904Sjeff#include "FormatStringParsing.h" 17112904Sjeff#include "clang/Basic/TargetInfo.h" 18112904Sjeff 19112904Sjeffusing clang::analyze_format_string::ArgType; 20112904Sjeffusing clang::analyze_format_string::FormatStringHandler; 21112904Sjeffusing clang::analyze_format_string::LengthModifier; 22112904Sjeffusing clang::analyze_format_string::OptionalAmount; 23112904Sjeffusing clang::analyze_format_string::ConversionSpecifier; 24112904Sjeffusing clang::analyze_printf::PrintfSpecifier; 25112904Sjeff 26112904Sjeffusing namespace clang; 27112904Sjeff 28116182Sobrientypedef clang::analyze_format_string::SpecifierResult<PrintfSpecifier> 29116182Sobrien PrintfSpecifierResult; 30116182Sobrien 31162536Sdavidxu//===----------------------------------------------------------------------===// 32233045Sdavide// Methods for parsing format strings. 33233045Sdavide//===----------------------------------------------------------------------===// 34112904Sjeff 35112904Sjeffusing analyze_format_string::ParseNonPositionAmount; 36131431Smarcel 37112904Sjeffstatic bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS, 38115765Sjeff const char *Start, const char *&Beg, const char *E, 39112904Sjeff unsigned *argIndex) { 40164033Srwatson if (argIndex) { 41112904Sjeff FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex)); 42161678Sdavidxu } else { 43165369Sdavidxu const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E, 44161678Sdavidxu analyze_format_string::PrecisionPos); 45112904Sjeff if (Amt.isInvalid()) 46112904Sjeff return true; 47112904Sjeff FS.setPrecision(Amt); 48216641Sdavidxu } 49139013Sdavidxu return false; 50112904Sjeff} 51112904Sjeff 52139013Sdavidxustatic bool ParseObjCFlags(FormatStringHandler &H, PrintfSpecifier &FS, 53139013Sdavidxu const char *FlagBeg, const char *E, bool Warn) { 54139013Sdavidxu StringRef Flag(FlagBeg, E - FlagBeg); 55139013Sdavidxu // Currently there is only one flag. 56139013Sdavidxu if (Flag == "tt") { 57139013Sdavidxu FS.setHasObjCTechnicalTerm(FlagBeg); 58165369Sdavidxu return false; 59165369Sdavidxu } 60205014Snwhitehorn // Handle either the case of no flag or an invalid flag. 61162536Sdavidxu if (Warn) { 62162536Sdavidxu if (Flag == "") 63162536Sdavidxu H.HandleEmptyObjCModifierFlag(FlagBeg, E - FlagBeg); 64179970Sdavidxu else 65179970Sdavidxu H.HandleInvalidObjCModifierFlag(FlagBeg, E - FlagBeg); 66179970Sdavidxu } 67161678Sdavidxu return true; 68161678Sdavidxu} 69161678Sdavidxu 70161678Sdavidxustatic PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H, 71161678Sdavidxu const char *&Beg, 72161678Sdavidxu const char *E, 73161678Sdavidxu unsigned &argIndex, 74161678Sdavidxu const LangOptions &LO, 75161678Sdavidxu const TargetInfo &Target, 76161678Sdavidxu bool Warn, 77161678Sdavidxu bool isFreeBSDKPrintf) { 78161678Sdavidxu 79161678Sdavidxu using namespace clang::analyze_format_string; 80161678Sdavidxu using namespace clang::analyze_printf; 81161678Sdavidxu 82161678Sdavidxu const char *I = Beg; 83161678Sdavidxu const char *Start = nullptr; 84161678Sdavidxu UpdateOnReturn <const char*> UpdateBeg(Beg, I); 85161678Sdavidxu 86161678Sdavidxu // Look for a '%' character that indicates the start of a format specifier. 87161678Sdavidxu for ( ; I != E ; ++I) { 88161678Sdavidxu char c = *I; 89115765Sjeff if (c == '\0') { 90161678Sdavidxu // Detect spurious null characters, which are likely errors. 91161678Sdavidxu H.HandleNullChar(I); 92161678Sdavidxu return true; 93161678Sdavidxu } 94161678Sdavidxu if (c == '%') { 95161678Sdavidxu Start = I++; // Record the start of the format specifier. 96161678Sdavidxu break; 97161678Sdavidxu } 98161678Sdavidxu } 99161678Sdavidxu 100161678Sdavidxu // No format specifier found? 101161678Sdavidxu if (!Start) 102161678Sdavidxu return false; 103161678Sdavidxu 104161678Sdavidxu if (I == E) { 105170300Sjeff // No more characters left? 106170300Sjeff if (Warn) 107161678Sdavidxu H.HandleIncompleteSpecifier(Start, E - Start); 108161678Sdavidxu return true; 109161678Sdavidxu } 110161678Sdavidxu 111161678Sdavidxu PrintfSpecifier FS; 112161678Sdavidxu if (ParseArgPosition(H, FS, Start, I, E)) 113161678Sdavidxu return true; 114161678Sdavidxu 115161678Sdavidxu if (I == E) { 116161742Sdavidxu // No more characters left? 117161678Sdavidxu if (Warn) 118201991Sdavidxu H.HandleIncompleteSpecifier(Start, E - Start); 119201991Sdavidxu return true; 120201991Sdavidxu } 121201991Sdavidxu 122201991Sdavidxu if (*I == '{') { 123201991Sdavidxu ++I; 124115765Sjeff unsigned char PrivacyFlags = 0; 125115765Sjeff StringRef MatchedStr; 126161678Sdavidxu 127161678Sdavidxu do { 128201991Sdavidxu StringRef Str(I, E - I); 129201991Sdavidxu std::string Match = "^[[:space:]]*" 130201991Sdavidxu "(private|public|sensitive|mask\\.[^[:space:],}]*)" 131201991Sdavidxu "[[:space:]]*(,|})"; 132201991Sdavidxu llvm::Regex R(Match); 133201991Sdavidxu SmallVector<StringRef, 2> Matches; 134201991Sdavidxu 135201991Sdavidxu if (R.match(Str, &Matches)) { 136201991Sdavidxu MatchedStr = Matches[1]; 137201991Sdavidxu I += Matches[0].size(); 138161678Sdavidxu 139138224Sdavidxu // Set the privacy flag if the privacy annotation in the 140161678Sdavidxu // comma-delimited segment is at least as strict as the privacy 141161678Sdavidxu // annotations in previous comma-delimited segments. 142161678Sdavidxu if (MatchedStr.startswith("mask")) { 143161678Sdavidxu StringRef MaskType = MatchedStr.substr(sizeof("mask.") - 1); 144201991Sdavidxu unsigned Size = MaskType.size(); 145177848Sdavidxu if (Warn && (Size == 0 || Size > 8)) 146177848Sdavidxu H.handleInvalidMaskType(MaskType); 147161678Sdavidxu FS.setMaskType(MaskType); 148201991Sdavidxu } else if (MatchedStr.equals("sensitive")) 149201991Sdavidxu PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsSensitive; 150161678Sdavidxu else if (PrivacyFlags != 151161678Sdavidxu clang::analyze_os_log::OSLogBufferItem::IsSensitive && 152161678Sdavidxu MatchedStr.equals("private")) 153161678Sdavidxu PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPrivate; 154158377Sdavidxu else if (PrivacyFlags == 0 && MatchedStr.equals("public")) 155161678Sdavidxu PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPublic; 156161678Sdavidxu } else { 157161678Sdavidxu size_t CommaOrBracePos = 158201991Sdavidxu Str.find_if([](char c) { return c == ',' || c == '}'; }); 159233045Sdavide 160233045Sdavide if (CommaOrBracePos == StringRef::npos) { 161233045Sdavide // Neither a comma nor the closing brace was found. 162233045Sdavide if (Warn) 163138224Sdavidxu H.HandleIncompleteSpecifier(Start, E - Start); 164115765Sjeff return true; 165161678Sdavidxu } 166189756Sdavidxu 167161678Sdavidxu I += CommaOrBracePos + 1; 168161678Sdavidxu } 169161678Sdavidxu // Continue until the closing brace is found. 170161678Sdavidxu } while (*(I - 1) == ','); 171161678Sdavidxu 172161678Sdavidxu // Set the privacy flag. 173161678Sdavidxu switch (PrivacyFlags) { 174161678Sdavidxu case 0: 175161678Sdavidxu break; 176161678Sdavidxu case clang::analyze_os_log::OSLogBufferItem::IsPrivate: 177163709Sjb FS.setIsPrivate(MatchedStr.data()); 178163709Sjb break; 179163709Sjb case clang::analyze_os_log::OSLogBufferItem::IsPublic: 180161678Sdavidxu FS.setIsPublic(MatchedStr.data()); 181138224Sdavidxu break; 182216678Sdavidxu case clang::analyze_os_log::OSLogBufferItem::IsSensitive: 183216678Sdavidxu FS.setIsSensitive(MatchedStr.data()); 184115765Sjeff break; 185161678Sdavidxu default: 186161678Sdavidxu llvm_unreachable("Unexpected privacy flag value"); 187161678Sdavidxu } 188177848Sdavidxu } 189177848Sdavidxu 190161678Sdavidxu // Look for flags (if any). 191179421Sdavidxu bool hasMore = true; 192138224Sdavidxu for ( ; I != E; ++I) { 193161678Sdavidxu switch (*I) { 194115310Sjeff default: hasMore = false; break; 195227309Sed case '\'': 196161678Sdavidxu // FIXME: POSIX specific. Always accept? 197161678Sdavidxu FS.setHasThousandsGrouping(I); 198161678Sdavidxu break; 199233045Sdavide case '-': FS.setIsLeftJustified(I); break; 200233045Sdavide case '+': FS.setHasPlusPrefix(I); break; 201233045Sdavide case ' ': FS.setHasSpacePrefix(I); break; 202233045Sdavide case '#': FS.setHasAlternativeForm(I); break; 203233045Sdavide case '0': FS.setHasLeadingZeros(I); break; 204233045Sdavide } 205161678Sdavidxu if (!hasMore) 206161678Sdavidxu break; 207161678Sdavidxu } 208139013Sdavidxu 209139013Sdavidxu if (I == E) { 210139257Sdavidxu // No more characters left? 211139257Sdavidxu if (Warn) 212177848Sdavidxu H.HandleIncompleteSpecifier(Start, E - Start); 213177848Sdavidxu return true; 214161678Sdavidxu } 215139257Sdavidxu 216163697Sdavidxu // Look for the field width (if any). 217161678Sdavidxu if (ParseFieldWidth(H, FS, Start, I, E, 218161678Sdavidxu FS.usesPositionalArg() ? nullptr : &argIndex)) 219161678Sdavidxu return true; 220161678Sdavidxu 221161678Sdavidxu if (I == E) { 222161678Sdavidxu // No more characters left? 223115310Sjeff if (Warn) 224177848Sdavidxu H.HandleIncompleteSpecifier(Start, E - Start); 225177848Sdavidxu return true; 226177848Sdavidxu } 227177848Sdavidxu 228170300Sjeff // Look for the precision (if any). 229170300Sjeff if (*I == '.') { 230233045Sdavide ++I; 231161678Sdavidxu if (I == E) { 232233045Sdavide if (Warn) 233233045Sdavide H.HandleIncompleteSpecifier(Start, E - Start); 234233045Sdavide return true; 235233045Sdavide } 236233045Sdavide 237233045Sdavide if (ParsePrecision(H, FS, Start, I, E, 238233045Sdavide FS.usesPositionalArg() ? nullptr : &argIndex)) 239233045Sdavide return true; 240233045Sdavide 241233045Sdavide if (I == E) { 242233045Sdavide // No more characters left? 243233045Sdavide if (Warn) 244233045Sdavide H.HandleIncompleteSpecifier(Start, E - Start); 245233045Sdavide return true; 246233045Sdavide } 247233045Sdavide } 248233045Sdavide 249233045Sdavide if (ParseVectorModifier(H, FS, I, E, LO)) 250233045Sdavide return true; 251233045Sdavide 252161678Sdavidxu // Look for the length modifier. 253161678Sdavidxu if (ParseLengthModifier(FS, I, E, LO) && I == E) { 254179421Sdavidxu // No more characters left? 255138224Sdavidxu if (Warn) 256161678Sdavidxu H.HandleIncompleteSpecifier(Start, E - Start); 257161678Sdavidxu return true; 258179421Sdavidxu } 259179421Sdavidxu 260179421Sdavidxu // Look for the Objective-C modifier flags, if any. 261179421Sdavidxu // We parse these here, even if they don't apply to 262201991Sdavidxu // the conversion specifier, and then emit an error 263201991Sdavidxu // later if the conversion specifier isn't '@'. This 264201991Sdavidxu // enables better recovery, and we don't know if 265179421Sdavidxu // these flags are applicable until later. 266179421Sdavidxu const char *ObjCModifierFlagsStart = nullptr, 267179421Sdavidxu *ObjCModifierFlagsEnd = nullptr; 268233045Sdavide if (*I == '[') { 269233045Sdavide ObjCModifierFlagsStart = I; 270233045Sdavide ++I; 271233045Sdavide auto flagStart = I; 272179421Sdavidxu for (;; ++I) { 273161678Sdavidxu ObjCModifierFlagsEnd = I; 274233045Sdavide if (I == E) { 275233045Sdavide if (Warn) 276233045Sdavide H.HandleIncompleteSpecifier(Start, E - Start); 277170300Sjeff return true; 278161678Sdavidxu } 279161678Sdavidxu // Did we find the closing ']'? 280161678Sdavidxu if (*I == ']') { 281161678Sdavidxu if (ParseObjCFlags(H, FS, flagStart, I, Warn)) 282143149Sdavidxu return true; 283143149Sdavidxu ++I; 284143149Sdavidxu break; 285161678Sdavidxu } 286161678Sdavidxu // There are no separators defined yet for multiple 287161678Sdavidxu // Objective-C modifier flags. When those are 288201991Sdavidxu // defined, this is the place to check. 289201991Sdavidxu } 290161678Sdavidxu } 291161678Sdavidxu 292161678Sdavidxu if (*I == '\0') { 293143149Sdavidxu // Detect spurious null characters, which are likely errors. 294143149Sdavidxu H.HandleNullChar(I); 295143149Sdavidxu return true; 296143149Sdavidxu } 297143149Sdavidxu 298201991Sdavidxu // Finally, look for the conversion specifier. 299201991Sdavidxu const char *conversionPosition = I++; 300143149Sdavidxu ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier; 301143149Sdavidxu switch (*conversionPosition) { 302143149Sdavidxu default: 303161678Sdavidxu break; 304139013Sdavidxu // C99: 7.19.6.1 (section 8). 305138224Sdavidxu case '%': k = ConversionSpecifier::PercentArg; break; 306161678Sdavidxu case 'A': k = ConversionSpecifier::AArg; break; 307161678Sdavidxu case 'E': k = ConversionSpecifier::EArg; break; 308138224Sdavidxu case 'F': k = ConversionSpecifier::FArg; break; 309138224Sdavidxu case 'G': k = ConversionSpecifier::GArg; break; 310161678Sdavidxu case 'X': k = ConversionSpecifier::XArg; break; 311161678Sdavidxu case 'a': k = ConversionSpecifier::aArg; break; 312139013Sdavidxu case 'c': k = ConversionSpecifier::cArg; break; 313201886Sdavidxu case 'd': k = ConversionSpecifier::dArg; break; 314179421Sdavidxu case 'e': k = ConversionSpecifier::eArg; break; 315179421Sdavidxu case 'f': k = ConversionSpecifier::fArg; break; 316139013Sdavidxu case 'g': k = ConversionSpecifier::gArg; break; 317139013Sdavidxu case 'i': k = ConversionSpecifier::iArg; break; 318161678Sdavidxu case 'n': 319177848Sdavidxu // Not handled, but reserved in OpenCL. 320161678Sdavidxu if (!LO.OpenCL) 321138224Sdavidxu k = ConversionSpecifier::nArg; 322177848Sdavidxu break; 323139257Sdavidxu case 'o': k = ConversionSpecifier::oArg; break; 324161678Sdavidxu case 'p': k = ConversionSpecifier::pArg; break; 325139257Sdavidxu case 's': k = ConversionSpecifier::sArg; break; 326161678Sdavidxu case 'u': k = ConversionSpecifier::uArg; break; 327177848Sdavidxu case 'x': k = ConversionSpecifier::xArg; break; 328139257Sdavidxu // POSIX specific. 329139257Sdavidxu case 'C': k = ConversionSpecifier::CArg; break; 330161678Sdavidxu case 'S': k = ConversionSpecifier::SArg; break; 331177848Sdavidxu // Apple extension for os_log 332161678Sdavidxu case 'P': 333139257Sdavidxu k = ConversionSpecifier::PArg; 334177848Sdavidxu break; 335139257Sdavidxu // Objective-C. 336161678Sdavidxu case '@': k = ConversionSpecifier::ObjCObjArg; break; 337139257Sdavidxu // Glibc specific. 338161678Sdavidxu case 'm': k = ConversionSpecifier::PrintErrno; break; 339177848Sdavidxu // FreeBSD kernel specific. 340139257Sdavidxu case 'b': 341139257Sdavidxu if (isFreeBSDKPrintf) 342161678Sdavidxu k = ConversionSpecifier::FreeBSDbArg; // int followed by char * 343177848Sdavidxu break; 344177848Sdavidxu case 'r': 345161678Sdavidxu if (isFreeBSDKPrintf) 346139257Sdavidxu k = ConversionSpecifier::FreeBSDrArg; // int 347177848Sdavidxu break; 348138224Sdavidxu case 'y': 349161678Sdavidxu if (isFreeBSDKPrintf) 350161678Sdavidxu k = ConversionSpecifier::FreeBSDyArg; // int 351161678Sdavidxu break; 352177848Sdavidxu // Apple-specific. 353177848Sdavidxu case 'D': 354177880Sdavidxu if (isFreeBSDKPrintf) 355177880Sdavidxu k = ConversionSpecifier::FreeBSDDArg; // void * followed by char * 356177880Sdavidxu else if (Target.getTriple().isOSDarwin()) 357177880Sdavidxu k = ConversionSpecifier::DArg; 358177880Sdavidxu break; 359177880Sdavidxu case 'O': 360177880Sdavidxu if (Target.getTriple().isOSDarwin()) 361177880Sdavidxu k = ConversionSpecifier::OArg; 362177880Sdavidxu break; 363177848Sdavidxu case 'U': 364177880Sdavidxu if (Target.getTriple().isOSDarwin()) 365177880Sdavidxu k = ConversionSpecifier::UArg; 366177848Sdavidxu break; 367177848Sdavidxu // MS specific. 368177848Sdavidxu case 'Z': 369177848Sdavidxu if (Target.getTriple().isOSMSVCRT()) 370177848Sdavidxu k = ConversionSpecifier::ZArg; 371177848Sdavidxu break; 372138224Sdavidxu } 373138224Sdavidxu 374161678Sdavidxu // Check to see if we used the Objective-C modifier flags with 375177848Sdavidxu // a conversion specifier other than '@'. 376161678Sdavidxu if (k != ConversionSpecifier::ObjCObjArg && 377138225Sdavidxu k != ConversionSpecifier::InvalidSpecifier && 378177848Sdavidxu ObjCModifierFlagsStart) { 379138224Sdavidxu H.HandleObjCFlagsWithNonObjCConversion(ObjCModifierFlagsStart, 380161678Sdavidxu ObjCModifierFlagsEnd + 1, 381161678Sdavidxu conversionPosition); 382161678Sdavidxu return true; 383177848Sdavidxu } 384177848Sdavidxu 385177848Sdavidxu PrintfConversionSpecifier CS(conversionPosition, k); 386177848Sdavidxu FS.setConversionSpecifier(CS); 387177848Sdavidxu if (CS.consumesDataArgument() && !FS.usesPositionalArg()) 388138224Sdavidxu FS.setArgIndex(argIndex++); 389138224Sdavidxu // FreeBSD kernel specific. 390201991Sdavidxu if (k == ConversionSpecifier::FreeBSDbArg || 391201991Sdavidxu k == ConversionSpecifier::FreeBSDDArg) 392201991Sdavidxu argIndex++; 393201991Sdavidxu 394201991Sdavidxu if (k == ConversionSpecifier::InvalidSpecifier) { 395201991Sdavidxu unsigned Len = I - Start; 396201991Sdavidxu if (ParseUTF8InvalidSpecifier(Start, E, Len)) { 397201991Sdavidxu CS.setEndScanList(Start + Len); 398201991Sdavidxu FS.setConversionSpecifier(CS); 399201991Sdavidxu } 400201991Sdavidxu // Assume the conversion takes one argument. 401201991Sdavidxu return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, Len); 402201991Sdavidxu } 403201991Sdavidxu return PrintfSpecifierResult(Start, FS); 404201991Sdavidxu} 405201991Sdavidxu 406139013Sdavidxubool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H, 407177848Sdavidxu const char *I, 408115765Sjeff const char *E, 409201991Sdavidxu const LangOptions &LO, 410161678Sdavidxu const TargetInfo &Target, 411139013Sdavidxu bool isFreeBSDKPrintf) { 412161678Sdavidxu 413161678Sdavidxu unsigned argIndex = 0; 414201991Sdavidxu 415203744Sdavidxu // Keep looking for a format specifier until we have exhausted the string. 416201991Sdavidxu while (I != E) { 417201991Sdavidxu const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex, 418201991Sdavidxu LO, Target, true, 419201991Sdavidxu isFreeBSDKPrintf); 420201991Sdavidxu // Did a fail-stop error of any kind occur when parsing the specifier? 421201991Sdavidxu // If so, don't do any more processing. 422201991Sdavidxu if (FSR.shouldStop()) 423201991Sdavidxu return true; 424201991Sdavidxu // Did we exhaust the string or encounter an error that 425201991Sdavidxu // we can recover from? 426201991Sdavidxu if (!FSR.hasValue()) 427233045Sdavide continue; 428233045Sdavide // We have a format specifier. Pass it to the callback. 429233045Sdavide if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(), 430233045Sdavide I - FSR.getStart())) 431233045Sdavide return true; 432233045Sdavide } 433233045Sdavide assert(I == E && "Format string not exhausted"); 434233045Sdavide return false; 435158718Sdavidxu} 436201991Sdavidxu 437201991Sdavidxubool clang::analyze_format_string::ParseFormatStringHasSArg(const char *I, 438139013Sdavidxu const char *E, 439139013Sdavidxu const LangOptions &LO, 440139013Sdavidxu const TargetInfo &Target) { 441177848Sdavidxu 442139013Sdavidxu unsigned argIndex = 0; 443161678Sdavidxu 444201991Sdavidxu // Keep looking for a %s format specifier until we have exhausted the string. 445161678Sdavidxu FormatStringHandler H; 446161678Sdavidxu while (I != E) { 447161678Sdavidxu const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex, 448158718Sdavidxu LO, Target, false, 449201991Sdavidxu false); 450201991Sdavidxu // Did a fail-stop error of any kind occur when parsing the specifier? 451201991Sdavidxu // If so, don't do any more processing. 452233045Sdavide if (FSR.shouldStop()) 453233045Sdavide return false; 454233045Sdavide // Did we exhaust the string or encounter an error that 455158718Sdavidxu // we can recover from? 456201991Sdavidxu if (!FSR.hasValue()) 457201991Sdavidxu continue; 458201991Sdavidxu const analyze_printf::PrintfSpecifier &FS = FSR.getValue(); 459201991Sdavidxu // Return true if this a %s format specifier. 460201991Sdavidxu if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::Kind::sArg) 461201991Sdavidxu return true; 462201991Sdavidxu } 463201991Sdavidxu return false; 464201991Sdavidxu} 465201991Sdavidxu 466201991Sdavidxubool clang::analyze_format_string::parseFormatStringHasFormattingSpecifiers( 467139013Sdavidxu const char *Begin, const char *End, const LangOptions &LO, 468139013Sdavidxu const TargetInfo &Target) { 469139013Sdavidxu unsigned ArgIndex = 0; 470161678Sdavidxu // Keep looking for a formatting specifier until we have exhausted the string. 471161678Sdavidxu FormatStringHandler H; 472161678Sdavidxu while (Begin != End) { 473139013Sdavidxu const PrintfSpecifierResult &FSR = 474139013Sdavidxu ParsePrintfSpecifier(H, Begin, End, ArgIndex, LO, Target, false, false); 475139013Sdavidxu if (FSR.shouldStop()) 476161678Sdavidxu break; 477201991Sdavidxu if (FSR.hasValue()) 478115765Sjeff return true; 479161678Sdavidxu } 480161678Sdavidxu return false; 481201991Sdavidxu} 482201991Sdavidxu 483201991Sdavidxu//===----------------------------------------------------------------------===// 484201991Sdavidxu// Methods on PrintfSpecifier. 485115765Sjeff//===----------------------------------------------------------------------===// 486115765Sjeff 487161678SdavidxuArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx, 488161678Sdavidxu bool IsObjCLiteral) const { 489161678Sdavidxu if (CS.getKind() == ConversionSpecifier::cArg) 490161678Sdavidxu switch (LM.getKind()) { 491139257Sdavidxu case LengthModifier::None: 492161678Sdavidxu return Ctx.IntTy; 493161678Sdavidxu case LengthModifier::AsLong: 494161678Sdavidxu case LengthModifier::AsWide: 495201991Sdavidxu return ArgType(ArgType::WIntTy, "wint_t"); 496161678Sdavidxu case LengthModifier::AsShort: 497161678Sdavidxu if (Ctx.getTargetInfo().getTriple().isOSMSVCRT()) 498161678Sdavidxu return Ctx.IntTy; 499161678Sdavidxu LLVM_FALLTHROUGH; 500201991Sdavidxu default: 501201991Sdavidxu return ArgType::Invalid(); 502201991Sdavidxu } 503201991Sdavidxu 504161678Sdavidxu if (CS.isIntArg()) 505201991Sdavidxu switch (LM.getKind()) { 506161678Sdavidxu case LengthModifier::AsLongDouble: 507161678Sdavidxu // GNU extension. 508161678Sdavidxu return Ctx.LongLongTy; 509161678Sdavidxu case LengthModifier::None: 510161678Sdavidxu case LengthModifier::AsShortLong: 511177848Sdavidxu return Ctx.IntTy; 512161678Sdavidxu case LengthModifier::AsInt32: 513177848Sdavidxu return ArgType(Ctx.IntTy, "__int32"); 514115765Sjeff case LengthModifier::AsChar: 515161678Sdavidxu return ArgType::AnyCharTy; 516201991Sdavidxu case LengthModifier::AsShort: return Ctx.ShortTy; 517201991Sdavidxu case LengthModifier::AsLong: return Ctx.LongTy; 518161678Sdavidxu case LengthModifier::AsLongLong: 519115765Sjeff case LengthModifier::AsQuad: 520139257Sdavidxu return Ctx.LongLongTy; 521161678Sdavidxu case LengthModifier::AsInt64: 522161678Sdavidxu return ArgType(Ctx.LongLongTy, "__int64"); 523201991Sdavidxu case LengthModifier::AsIntMax: 524201991Sdavidxu return ArgType(Ctx.getIntMaxType(), "intmax_t"); 525201991Sdavidxu case LengthModifier::AsSizeT: 526177848Sdavidxu return ArgType::makeSizeT(ArgType(Ctx.getSignedSizeType(), "ssize_t")); 527161678Sdavidxu case LengthModifier::AsInt3264: 528139257Sdavidxu return Ctx.getTargetInfo().getTriple().isArch64Bit() 529201991Sdavidxu ? ArgType(Ctx.LongLongTy, "__int64") 530139013Sdavidxu : ArgType(Ctx.IntTy, "__int32"); 531139013Sdavidxu case LengthModifier::AsPtrDiff: 532139257Sdavidxu return ArgType::makePtrdiffT( 533138224Sdavidxu ArgType(Ctx.getPointerDiffType(), "ptrdiff_t")); 534138224Sdavidxu case LengthModifier::AsAllocate: 535177848Sdavidxu case LengthModifier::AsMAllocate: 536161678Sdavidxu case LengthModifier::AsWide: 537161678Sdavidxu return ArgType::Invalid(); 538161678Sdavidxu } 539161678Sdavidxu 540161678Sdavidxu if (CS.isUIntArg()) 541161678Sdavidxu switch (LM.getKind()) { 542161678Sdavidxu case LengthModifier::AsLongDouble: 543161678Sdavidxu // GNU extension. 544161678Sdavidxu return Ctx.UnsignedLongLongTy; 545161678Sdavidxu case LengthModifier::None: 546161678Sdavidxu case LengthModifier::AsShortLong: 547161678Sdavidxu return Ctx.UnsignedIntTy; 548161678Sdavidxu case LengthModifier::AsInt32: 549161678Sdavidxu return ArgType(Ctx.UnsignedIntTy, "unsigned __int32"); 550161678Sdavidxu case LengthModifier::AsChar: return Ctx.UnsignedCharTy; 551161678Sdavidxu case LengthModifier::AsShort: return Ctx.UnsignedShortTy; 552161678Sdavidxu case LengthModifier::AsLong: return Ctx.UnsignedLongTy; 553161678Sdavidxu case LengthModifier::AsLongLong: 554138224Sdavidxu case LengthModifier::AsQuad: 555161678Sdavidxu return Ctx.UnsignedLongLongTy; 556138224Sdavidxu case LengthModifier::AsInt64: 557161678Sdavidxu return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64"); 558161678Sdavidxu case LengthModifier::AsIntMax: 559161678Sdavidxu return ArgType(Ctx.getUIntMaxType(), "uintmax_t"); 560161678Sdavidxu case LengthModifier::AsSizeT: 561161678Sdavidxu return ArgType::makeSizeT(ArgType(Ctx.getSizeType(), "size_t")); 562161678Sdavidxu case LengthModifier::AsInt3264: 563161678Sdavidxu return Ctx.getTargetInfo().getTriple().isArch64Bit() 564161678Sdavidxu ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64") 565139751Sdavidxu : ArgType(Ctx.UnsignedIntTy, "unsigned __int32"); 566139751Sdavidxu case LengthModifier::AsPtrDiff: 567139751Sdavidxu return ArgType::makePtrdiffT( 568138224Sdavidxu ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t")); 569138224Sdavidxu case LengthModifier::AsAllocate: 570161678Sdavidxu case LengthModifier::AsMAllocate: 571161678Sdavidxu case LengthModifier::AsWide: 572161678Sdavidxu return ArgType::Invalid(); 573218969Sjhb } 574161678Sdavidxu 575139013Sdavidxu if (CS.isDoubleArg()) { 576161678Sdavidxu if (!VectorNumElts.isInvalid()) { 577139013Sdavidxu switch (LM.getKind()) { 578139013Sdavidxu case LengthModifier::AsShort: 579139013Sdavidxu return Ctx.HalfTy; 580139013Sdavidxu case LengthModifier::AsShortLong: 581139013Sdavidxu return Ctx.FloatTy; 582139013Sdavidxu case LengthModifier::AsLong: 583161678Sdavidxu default: 584161678Sdavidxu return Ctx.DoubleTy; 585161678Sdavidxu } 586161678Sdavidxu } 587161678Sdavidxu 588163677Sdavidxu if (LM.getKind() == LengthModifier::AsLongDouble) 589163677Sdavidxu return Ctx.LongDoubleTy; 590161678Sdavidxu return Ctx.DoubleTy; 591161678Sdavidxu } 592161678Sdavidxu 593161678Sdavidxu if (CS.getKind() == ConversionSpecifier::nArg) { 594161678Sdavidxu switch (LM.getKind()) { 595161678Sdavidxu case LengthModifier::None: 596161678Sdavidxu return ArgType::PtrTo(Ctx.IntTy); 597161678Sdavidxu case LengthModifier::AsChar: 598161678Sdavidxu return ArgType::PtrTo(Ctx.SignedCharTy); 599161678Sdavidxu case LengthModifier::AsShort: 600161678Sdavidxu return ArgType::PtrTo(Ctx.ShortTy); 601161678Sdavidxu case LengthModifier::AsLong: 602161678Sdavidxu return ArgType::PtrTo(Ctx.LongTy); 603161678Sdavidxu case LengthModifier::AsLongLong: 604161678Sdavidxu case LengthModifier::AsQuad: 605161678Sdavidxu return ArgType::PtrTo(Ctx.LongLongTy); 606161678Sdavidxu case LengthModifier::AsIntMax: 607161678Sdavidxu return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t")); 608161678Sdavidxu case LengthModifier::AsSizeT: 609161678Sdavidxu return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t")); 610139013Sdavidxu case LengthModifier::AsPtrDiff: 611139013Sdavidxu return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t")); 612161678Sdavidxu case LengthModifier::AsLongDouble: 613139013Sdavidxu return ArgType(); // FIXME: Is this a known extension? 614139013Sdavidxu case LengthModifier::AsAllocate: 615139013Sdavidxu case LengthModifier::AsMAllocate: 616161678Sdavidxu case LengthModifier::AsInt32: 617161678Sdavidxu case LengthModifier::AsInt3264: 618161678Sdavidxu case LengthModifier::AsInt64: 619218969Sjhb case LengthModifier::AsWide: 620139013Sdavidxu return ArgType::Invalid(); 621139013Sdavidxu case LengthModifier::AsShortLong: 622161678Sdavidxu llvm_unreachable("only used for OpenCL which doesn not handle nArg"); 623139013Sdavidxu } 624139013Sdavidxu } 625139013Sdavidxu 626161678Sdavidxu switch (CS.getKind()) { 627161678Sdavidxu case ConversionSpecifier::sArg: 628161678Sdavidxu if (LM.getKind() == LengthModifier::AsWideChar) { 629139013Sdavidxu if (IsObjCLiteral) 630163449Sdavidxu return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()), 631112904Sjeff "const unichar *"); 632143149Sdavidxu return ArgType(ArgType::WCStrTy, "wchar_t *"); 633163449Sdavidxu } 634163449Sdavidxu if (LM.getKind() == LengthModifier::AsWide) 635138224Sdavidxu return ArgType(ArgType::WCStrTy, "wchar_t *"); 636112904Sjeff return ArgType::CStrTy; 637143149Sdavidxu case ConversionSpecifier::SArg: 638161678Sdavidxu if (IsObjCLiteral) 639112904Sjeff return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()), 640161678Sdavidxu "const unichar *"); 641112904Sjeff if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() && 642112904Sjeff LM.getKind() == LengthModifier::AsShort) 643112904Sjeff return ArgType::CStrTy; 644112904Sjeff return ArgType(ArgType::WCStrTy, "wchar_t *"); 645112904Sjeff case ConversionSpecifier::CArg: 646112904Sjeff if (IsObjCLiteral) 647163449Sdavidxu return ArgType(Ctx.UnsignedShortTy, "unichar"); 648112904Sjeff if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() && 649138224Sdavidxu LM.getKind() == LengthModifier::AsShort) 650138224Sdavidxu return Ctx.IntTy; 651138224Sdavidxu return ArgType(Ctx.WideCharTy, "wchar_t"); 652138224Sdavidxu case ConversionSpecifier::pArg: 653115765Sjeff case ConversionSpecifier::PArg: 654115765Sjeff return ArgType::CPointerTy; 655115765Sjeff case ConversionSpecifier::ObjCObjArg: 656115765Sjeff return ArgType::ObjCPointerTy; 657115765Sjeff default: 658115765Sjeff break; 659163449Sdavidxu } 660139013Sdavidxu 661115765Sjeff // FIXME: Handle other cases. 662138224Sdavidxu return ArgType(); 663138224Sdavidxu} 664138224Sdavidxu 665115765Sjeff 666115765SjeffArgType PrintfSpecifier::getArgType(ASTContext &Ctx, 667115765Sjeff bool IsObjCLiteral) const { 668115765Sjeff const PrintfConversionSpecifier &CS = getConversionSpecifier(); 669115765Sjeff 670115765Sjeff if (!CS.consumesDataArgument()) 671112904Sjeff return ArgType::Invalid(); 672112904Sjeff 673138224Sdavidxu ArgType ScalarTy = getScalarArgType(Ctx, IsObjCLiteral); 674138224Sdavidxu if (!ScalarTy.isValid() || VectorNumElts.isInvalid()) 675138224Sdavidxu return ScalarTy; 676138224Sdavidxu 677161678Sdavidxu return ScalarTy.makeVectorType(Ctx, VectorNumElts.getConstantAmount()); 678138224Sdavidxu} 679112904Sjeff 680161678Sdavidxubool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt, 681161678Sdavidxu ASTContext &Ctx, bool IsObjCLiteral) { 682161678Sdavidxu // %n is different from other conversion specifiers; don't try to fix it. 683161678Sdavidxu if (CS.getKind() == ConversionSpecifier::nArg) 684161678Sdavidxu return false; 685161678Sdavidxu 686161678Sdavidxu // Handle Objective-C objects first. Note that while the '%@' specifier will 687161678Sdavidxu // not warn for structure pointer or void pointer arguments (because that's 688161678Sdavidxu // how CoreFoundation objects are implemented), we only show a fixit for '%@' 689161678Sdavidxu // if we know it's an object (block, id, class, or __attribute__((NSObject))). 690112904Sjeff if (QT->isObjCRetainableType()) { 691112904Sjeff if (!IsObjCLiteral) 692112904Sjeff return false; 693112904Sjeff 694112904Sjeff CS.setKind(ConversionSpecifier::ObjCObjArg); 695112904Sjeff 696163449Sdavidxu // Disable irrelevant flags 697112904Sjeff HasThousandsGrouping = false; 698112904Sjeff HasPlusPrefix = false; 699112967Sjake HasSpacePrefix = false; 700143149Sdavidxu HasAlternativeForm = false; 701143149Sdavidxu HasLeadingZeroes = false; 702143149Sdavidxu Precision.setHowSpecified(OptionalAmount::NotSpecified); 703143149Sdavidxu LM.setKind(LengthModifier::None); 704115765Sjeff 705112904Sjeff return true; 706112904Sjeff } 707112904Sjeff 708115765Sjeff // Handle strings next (char *, wchar_t *) 709117685Smtm if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) { 710117685Smtm CS.setKind(ConversionSpecifier::sArg); 711112904Sjeff 712143149Sdavidxu // Disable irrelevant flags 713161678Sdavidxu HasAlternativeForm = 0; 714161678Sdavidxu HasLeadingZeroes = 0; 715143149Sdavidxu 716143149Sdavidxu // Set the long length modifier for wide characters 717143149Sdavidxu if (QT->getPointeeType()->isWideCharType()) 718112904Sjeff LM.setKind(LengthModifier::AsWideChar); 719117743Smtm else 720117743Smtm LM.setKind(LengthModifier::None); 721112904Sjeff 722112904Sjeff return true; 723161678Sdavidxu } 724161678Sdavidxu 725161678Sdavidxu // If it's an enum, get its underlying type. 726139013Sdavidxu if (const EnumType *ETy = QT->getAs<EnumType>()) 727163449Sdavidxu QT = ETy->getDecl()->getIntegerType(); 728140245Sdavidxu 729112904Sjeff const BuiltinType *BT = QT->getAs<BuiltinType>(); 730140245Sdavidxu if (!BT) { 731139013Sdavidxu const VectorType *VT = QT->getAs<VectorType>(); 732140245Sdavidxu if (VT) { 733139013Sdavidxu QT = VT->getElementType(); 734140245Sdavidxu BT = QT->getAs<BuiltinType>(); 735162536Sdavidxu VectorNumElts = OptionalAmount(VT->getNumElements()); 736162030Sdavidxu } 737162030Sdavidxu } 738162030Sdavidxu 739139013Sdavidxu // We can only work with builtin types. 740140245Sdavidxu if (!BT) 741140245Sdavidxu return false; 742140245Sdavidxu 743139013Sdavidxu // Set length modifier 744162536Sdavidxu switch (BT->getKind()) { 745140245Sdavidxu case BuiltinType::Bool: 746140245Sdavidxu case BuiltinType::WChar_U: 747140245Sdavidxu case BuiltinType::WChar_S: 748140245Sdavidxu case BuiltinType::Char8: // FIXME: Treat like 'char'? 749139751Sdavidxu case BuiltinType::Char16: 750139013Sdavidxu case BuiltinType::Char32: 751139013Sdavidxu case BuiltinType::UInt128: 752140245Sdavidxu case BuiltinType::Int128: 753140245Sdavidxu case BuiltinType::Half: 754140245Sdavidxu case BuiltinType::Float16: 755139013Sdavidxu case BuiltinType::Float128: 756162030Sdavidxu case BuiltinType::ShortAccum: 757162030Sdavidxu case BuiltinType::Accum: 758162030Sdavidxu case BuiltinType::LongAccum: 759139013Sdavidxu case BuiltinType::UShortAccum: 760139013Sdavidxu case BuiltinType::UAccum: 761139013Sdavidxu case BuiltinType::ULongAccum: 762139013Sdavidxu case BuiltinType::ShortFract: 763161678Sdavidxu case BuiltinType::Fract: 764161678Sdavidxu case BuiltinType::LongFract: 765161678Sdavidxu case BuiltinType::UShortFract: 766139013Sdavidxu case BuiltinType::UFract: 767163449Sdavidxu case BuiltinType::ULongFract: 768139013Sdavidxu case BuiltinType::SatShortAccum: 769139013Sdavidxu case BuiltinType::SatAccum: 770163449Sdavidxu case BuiltinType::SatLongAccum: 771163449Sdavidxu case BuiltinType::SatUShortAccum: 772139257Sdavidxu case BuiltinType::SatUAccum: 773139257Sdavidxu case BuiltinType::SatULongAccum: 774112904Sjeff case BuiltinType::SatShortFract: 775112904Sjeff case BuiltinType::SatFract: 776112904Sjeff case BuiltinType::SatLongFract: 777112904Sjeff case BuiltinType::SatUShortFract: 778163449Sdavidxu case BuiltinType::SatUFract: 779161678Sdavidxu case BuiltinType::SatULongFract: 780115765Sjeff // Various types which are non-trivial to correct. 781115765Sjeff return false; 782139013Sdavidxu 783115765Sjeff#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ 784112904Sjeff case BuiltinType::Id: 785161678Sdavidxu#include "clang/Basic/OpenCLImageTypes.def" 786161678Sdavidxu#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ 787163449Sdavidxu case BuiltinType::Id: 788161678Sdavidxu#include "clang/Basic/OpenCLExtensionTypes.def" 789161678Sdavidxu#define SVE_TYPE(Name, Id, SingletonId) \ 790161678Sdavidxu case BuiltinType::Id: 791161678Sdavidxu#include "clang/Basic/AArch64SVEACLETypes.def" 792161855Sdavidxu#define SIGNED_TYPE(Id, SingletonId) 793161678Sdavidxu#define UNSIGNED_TYPE(Id, SingletonId) 794161678Sdavidxu#define FLOATING_TYPE(Id, SingletonId) 795117685Smtm#define BUILTIN_TYPE(Id, SingletonId) \ 796161678Sdavidxu case BuiltinType::Id: 797161678Sdavidxu#include "clang/AST/BuiltinTypes.def" 798139257Sdavidxu // Misc other stuff which doesn't make sense here. 799139257Sdavidxu return false; 800139257Sdavidxu 801139257Sdavidxu case BuiltinType::UInt: 802139257Sdavidxu case BuiltinType::Int: 803139257Sdavidxu case BuiltinType::Float: 804139257Sdavidxu LM.setKind(VectorNumElts.isInvalid() ? 805117743Smtm LengthModifier::None : LengthModifier::AsShortLong); 806117743Smtm break; 807117743Smtm case BuiltinType::Double: 808117743Smtm LM.setKind(VectorNumElts.isInvalid() ? 809117743Smtm LengthModifier::None : LengthModifier::AsLong); 810163449Sdavidxu break; 811163449Sdavidxu case BuiltinType::Char_U: 812139257Sdavidxu case BuiltinType::UChar: 813161678Sdavidxu case BuiltinType::Char_S: 814139257Sdavidxu case BuiltinType::SChar: 815139257Sdavidxu LM.setKind(LengthModifier::AsChar); 816139257Sdavidxu break; 817115765Sjeff 818115765Sjeff case BuiltinType::Short: 819138224Sdavidxu case BuiltinType::UShort: 820138224Sdavidxu LM.setKind(LengthModifier::AsShort); 821115765Sjeff break; 822112904Sjeff 823139013Sdavidxu case BuiltinType::Long: 824205014Snwhitehorn case BuiltinType::ULong: 825162536Sdavidxu LM.setKind(LengthModifier::AsLong); 826161678Sdavidxu break; 827162536Sdavidxu 828162536Sdavidxu case BuiltinType::LongLong: 829162536Sdavidxu case BuiltinType::ULongLong: 830162536Sdavidxu LM.setKind(LengthModifier::AsLongLong); 831162536Sdavidxu break; 832162536Sdavidxu 833162536Sdavidxu case BuiltinType::LongDouble: 834162536Sdavidxu LM.setKind(LengthModifier::AsLongDouble); 835162536Sdavidxu break; 836162536Sdavidxu } 837162536Sdavidxu 838162536Sdavidxu // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99. 839162536Sdavidxu if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11)) 840162536Sdavidxu namedTypeToLengthModifier(QT, LM); 841162536Sdavidxu 842162536Sdavidxu // If fixing the length modifier was enough, we might be done. 843162536Sdavidxu if (hasValidLengthModifier(Ctx.getTargetInfo(), LangOpt)) { 844162536Sdavidxu // If we're going to offer a fix anyway, make sure the sign matches. 845162536Sdavidxu switch (CS.getKind()) { 846162536Sdavidxu case ConversionSpecifier::uArg: 847162536Sdavidxu case ConversionSpecifier::UArg: 848162536Sdavidxu if (QT->isSignedIntegerType()) 849162536Sdavidxu CS.setKind(clang::analyze_format_string::ConversionSpecifier::dArg); 850162536Sdavidxu break; 851162536Sdavidxu case ConversionSpecifier::dArg: 852162536Sdavidxu case ConversionSpecifier::DArg: 853162536Sdavidxu case ConversionSpecifier::iArg: 854162536Sdavidxu if (QT->isUnsignedIntegerType() && !HasPlusPrefix) 855162536Sdavidxu CS.setKind(clang::analyze_format_string::ConversionSpecifier::uArg); 856162536Sdavidxu break; 857162536Sdavidxu default: 858162536Sdavidxu // Other specifiers do not have signed/unsigned variants. 859162536Sdavidxu break; 860162536Sdavidxu } 861162536Sdavidxu 862162536Sdavidxu const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral); 863162536Sdavidxu if (ATR.isValid() && ATR.matchesType(Ctx, QT)) 864162536Sdavidxu return true; 865162536Sdavidxu } 866162536Sdavidxu 867162536Sdavidxu // Set conversion specifier and disable any flags which do not apply to it. 868162536Sdavidxu // Let typedefs to char fall through to int, as %c is silly for uint8_t. 869162536Sdavidxu if (!isa<TypedefType>(QT) && QT->isCharType()) { 870162536Sdavidxu CS.setKind(ConversionSpecifier::cArg); 871162536Sdavidxu LM.setKind(LengthModifier::None); 872162536Sdavidxu Precision.setHowSpecified(OptionalAmount::NotSpecified); 873162536Sdavidxu HasAlternativeForm = 0; 874162536Sdavidxu HasLeadingZeroes = 0; 875162536Sdavidxu HasPlusPrefix = 0; 876162536Sdavidxu } 877162536Sdavidxu // Test for Floating type first as LongDouble can pass isUnsignedIntegerType 878162536Sdavidxu else if (QT->isRealFloatingType()) { 879162536Sdavidxu CS.setKind(ConversionSpecifier::fArg); 880162536Sdavidxu } 881162536Sdavidxu else if (QT->isSignedIntegerType()) { 882162536Sdavidxu CS.setKind(ConversionSpecifier::dArg); 883162536Sdavidxu HasAlternativeForm = 0; 884162536Sdavidxu } 885162536Sdavidxu else if (QT->isUnsignedIntegerType()) { 886162536Sdavidxu CS.setKind(ConversionSpecifier::uArg); 887162536Sdavidxu HasAlternativeForm = 0; 888162536Sdavidxu HasPlusPrefix = 0; 889162536Sdavidxu } else { 890162536Sdavidxu llvm_unreachable("Unexpected type"); 891162536Sdavidxu } 892162536Sdavidxu 893162536Sdavidxu return true; 894162536Sdavidxu} 895162536Sdavidxu 896162536Sdavidxuvoid PrintfSpecifier::toString(raw_ostream &os) const { 897162536Sdavidxu // Whilst some features have no defined order, we are using the order 898162536Sdavidxu // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1) 899162536Sdavidxu os << "%"; 900162536Sdavidxu 901162536Sdavidxu // Positional args 902162536Sdavidxu if (usesPositionalArg()) { 903162536Sdavidxu os << getPositionalArgIndex() << "$"; 904162536Sdavidxu } 905162536Sdavidxu 906162536Sdavidxu // Conversion flags 907162536Sdavidxu if (IsLeftJustified) os << "-"; 908162536Sdavidxu if (HasPlusPrefix) os << "+"; 909162536Sdavidxu if (HasSpacePrefix) os << " "; 910162536Sdavidxu if (HasAlternativeForm) os << "#"; 911162536Sdavidxu if (HasLeadingZeroes) os << "0"; 912162536Sdavidxu 913162536Sdavidxu // Minimum field width 914162536Sdavidxu FieldWidth.toString(os); 915162536Sdavidxu // Precision 916162536Sdavidxu Precision.toString(os); 917162536Sdavidxu 918162536Sdavidxu // Vector modifier 919162536Sdavidxu if (!VectorNumElts.isInvalid()) 920162536Sdavidxu os << 'v' << VectorNumElts.getConstantAmount(); 921162536Sdavidxu 922162536Sdavidxu // Length modifier 923162536Sdavidxu os << LM.toString(); 924162536Sdavidxu // Conversion specifier 925162536Sdavidxu os << CS.toString(); 926162536Sdavidxu} 927162536Sdavidxu 928162536Sdavidxubool PrintfSpecifier::hasValidPlusPrefix() const { 929162536Sdavidxu if (!HasPlusPrefix) 930162536Sdavidxu return true; 931162536Sdavidxu 932162536Sdavidxu // The plus prefix only makes sense for signed conversions 933162536Sdavidxu switch (CS.getKind()) { 934162536Sdavidxu case ConversionSpecifier::dArg: 935162536Sdavidxu case ConversionSpecifier::DArg: 936162536Sdavidxu case ConversionSpecifier::iArg: 937162536Sdavidxu case ConversionSpecifier::fArg: 938162536Sdavidxu case ConversionSpecifier::FArg: 939162536Sdavidxu case ConversionSpecifier::eArg: 940162536Sdavidxu case ConversionSpecifier::EArg: 941162536Sdavidxu case ConversionSpecifier::gArg: 942162536Sdavidxu case ConversionSpecifier::GArg: 943162536Sdavidxu case ConversionSpecifier::aArg: 944162536Sdavidxu case ConversionSpecifier::AArg: 945162536Sdavidxu case ConversionSpecifier::FreeBSDrArg: 946162536Sdavidxu case ConversionSpecifier::FreeBSDyArg: 947162536Sdavidxu return true; 948162536Sdavidxu 949162536Sdavidxu default: 950162536Sdavidxu return false; 951162536Sdavidxu } 952162536Sdavidxu} 953162536Sdavidxu 954162536Sdavidxubool PrintfSpecifier::hasValidAlternativeForm() const { 955162536Sdavidxu if (!HasAlternativeForm) 956162536Sdavidxu return true; 957162536Sdavidxu 958162536Sdavidxu // Alternate form flag only valid with the oxXaAeEfFgG conversions 959162536Sdavidxu switch (CS.getKind()) { 960162536Sdavidxu case ConversionSpecifier::oArg: 961162536Sdavidxu case ConversionSpecifier::OArg: 962162536Sdavidxu case ConversionSpecifier::xArg: 963162536Sdavidxu case ConversionSpecifier::XArg: 964162536Sdavidxu case ConversionSpecifier::aArg: 965162536Sdavidxu case ConversionSpecifier::AArg: 966162536Sdavidxu case ConversionSpecifier::eArg: 967162536Sdavidxu case ConversionSpecifier::EArg: 968162536Sdavidxu case ConversionSpecifier::fArg: 969162536Sdavidxu case ConversionSpecifier::FArg: 970162536Sdavidxu case ConversionSpecifier::gArg: 971162536Sdavidxu case ConversionSpecifier::GArg: 972162536Sdavidxu case ConversionSpecifier::FreeBSDrArg: 973162536Sdavidxu case ConversionSpecifier::FreeBSDyArg: 974162536Sdavidxu return true; 975162536Sdavidxu 976162536Sdavidxu default: 977162536Sdavidxu return false; 978162536Sdavidxu } 979162536Sdavidxu} 980162536Sdavidxu 981162536Sdavidxubool PrintfSpecifier::hasValidLeadingZeros() const { 982162536Sdavidxu if (!HasLeadingZeroes) 983162536Sdavidxu return true; 984162536Sdavidxu 985162536Sdavidxu // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions 986162536Sdavidxu switch (CS.getKind()) { 987162536Sdavidxu case ConversionSpecifier::dArg: 988162536Sdavidxu case ConversionSpecifier::DArg: 989162536Sdavidxu case ConversionSpecifier::iArg: 990162536Sdavidxu case ConversionSpecifier::oArg: 991162536Sdavidxu case ConversionSpecifier::OArg: 992162536Sdavidxu case ConversionSpecifier::uArg: 993162536Sdavidxu case ConversionSpecifier::UArg: 994162536Sdavidxu case ConversionSpecifier::xArg: 995162536Sdavidxu case ConversionSpecifier::XArg: 996162536Sdavidxu case ConversionSpecifier::aArg: 997162536Sdavidxu case ConversionSpecifier::AArg: 998162536Sdavidxu case ConversionSpecifier::eArg: 999162536Sdavidxu case ConversionSpecifier::EArg: 1000162536Sdavidxu case ConversionSpecifier::fArg: 1001162536Sdavidxu case ConversionSpecifier::FArg: 1002162536Sdavidxu case ConversionSpecifier::gArg: 1003162536Sdavidxu case ConversionSpecifier::GArg: 1004162536Sdavidxu case ConversionSpecifier::FreeBSDrArg: 1005162536Sdavidxu case ConversionSpecifier::FreeBSDyArg: 1006162536Sdavidxu return true; 1007162536Sdavidxu 1008162536Sdavidxu default: 1009162536Sdavidxu return false; 1010162536Sdavidxu } 1011162536Sdavidxu} 1012162536Sdavidxu 1013162536Sdavidxubool PrintfSpecifier::hasValidSpacePrefix() const { 1014162536Sdavidxu if (!HasSpacePrefix) 1015162536Sdavidxu return true; 1016162536Sdavidxu 1017162536Sdavidxu // The space prefix only makes sense for signed conversions 1018162536Sdavidxu switch (CS.getKind()) { 1019162536Sdavidxu case ConversionSpecifier::dArg: 1020162536Sdavidxu case ConversionSpecifier::DArg: 1021162536Sdavidxu case ConversionSpecifier::iArg: 1022162536Sdavidxu case ConversionSpecifier::fArg: 1023162536Sdavidxu case ConversionSpecifier::FArg: 1024231989Sdavidxu case ConversionSpecifier::eArg: 1025231989Sdavidxu case ConversionSpecifier::EArg: 1026231989Sdavidxu case ConversionSpecifier::gArg: 1027231989Sdavidxu case ConversionSpecifier::GArg: 1028231989Sdavidxu case ConversionSpecifier::aArg: 1029231989Sdavidxu case ConversionSpecifier::AArg: 1030231989Sdavidxu case ConversionSpecifier::FreeBSDrArg: 1031231989Sdavidxu case ConversionSpecifier::FreeBSDyArg: 1032231989Sdavidxu return true; 1033162536Sdavidxu 1034161678Sdavidxu default: 1035161678Sdavidxu return false; 1036139013Sdavidxu } 1037163449Sdavidxu} 1038232144Sdavidxu 1039139013Sdavidxubool PrintfSpecifier::hasValidLeftJustified() const { 1040143149Sdavidxu if (!IsLeftJustified) 1041231989Sdavidxu return true; 1042163449Sdavidxu 1043140245Sdavidxu // The left justified flag is valid for all conversions except n 1044139013Sdavidxu switch (CS.getKind()) { 1045143149Sdavidxu case ConversionSpecifier::nArg: 1046178646Sdavidxu return false; 1047178646Sdavidxu 1048139013Sdavidxu default: 1049161678Sdavidxu return true; 1050161678Sdavidxu } 1051161678Sdavidxu} 1052161678Sdavidxu 1053162536Sdavidxubool PrintfSpecifier::hasValidThousandsGroupingPrefix() const { 1054162536Sdavidxu if (!HasThousandsGrouping) 1055162536Sdavidxu return true; 1056190987Sdavidxu 1057139427Sdavidxu switch (CS.getKind()) { 1058143149Sdavidxu case ConversionSpecifier::dArg: 1059143149Sdavidxu case ConversionSpecifier::DArg: 1060143149Sdavidxu case ConversionSpecifier::iArg: 1061140245Sdavidxu case ConversionSpecifier::uArg: 1062143149Sdavidxu case ConversionSpecifier::UArg: 1063164839Sdavidxu case ConversionSpecifier::fArg: 1064161678Sdavidxu case ConversionSpecifier::FArg: 1065143149Sdavidxu case ConversionSpecifier::gArg: 1066139013Sdavidxu case ConversionSpecifier::GArg: 1067232144Sdavidxu return true; 1068232144Sdavidxu default: 1069231989Sdavidxu return false; 1070232144Sdavidxu } 1071231989Sdavidxu} 1072232144Sdavidxu 1073231989Sdavidxubool PrintfSpecifier::hasValidPrecision() const { 1074161678Sdavidxu if (Precision.getHowSpecified() == OptionalAmount::NotSpecified) 1075139013Sdavidxu return true; 1076231989Sdavidxu 1077231989Sdavidxu // Precision is only valid with the diouxXaAeEfFgGsP conversions 1078231989Sdavidxu switch (CS.getKind()) { 1079231989Sdavidxu case ConversionSpecifier::dArg: 1080231989Sdavidxu case ConversionSpecifier::DArg: 1081231989Sdavidxu case ConversionSpecifier::iArg: 1082231989Sdavidxu case ConversionSpecifier::oArg: 1083211794Sdavidxu case ConversionSpecifier::OArg: 1084211794Sdavidxu case ConversionSpecifier::uArg: 1085161678Sdavidxu case ConversionSpecifier::UArg: 1086211794Sdavidxu case ConversionSpecifier::xArg: 1087140245Sdavidxu case ConversionSpecifier::XArg: 1088140245Sdavidxu case ConversionSpecifier::aArg: 1089161678Sdavidxu case ConversionSpecifier::AArg: 1090232144Sdavidxu case ConversionSpecifier::eArg: 1091161678Sdavidxu case ConversionSpecifier::EArg: 1092139013Sdavidxu case ConversionSpecifier::fArg: 1093143149Sdavidxu case ConversionSpecifier::FArg: 1094143149Sdavidxu case ConversionSpecifier::gArg: 1095139013Sdavidxu case ConversionSpecifier::GArg: 1096143149Sdavidxu case ConversionSpecifier::sArg: 1097139257Sdavidxu case ConversionSpecifier::FreeBSDrArg: 1098139257Sdavidxu case ConversionSpecifier::FreeBSDyArg: 1099139013Sdavidxu case ConversionSpecifier::PArg: 1100139013Sdavidxu return true; 1101139013Sdavidxu 1102161678Sdavidxu default: 1103161678Sdavidxu return false; 1104161678Sdavidxu } 1105151692Sdavidxu} 1106178646Sdavidxubool PrintfSpecifier::hasValidFieldWidth() const { 1107139013Sdavidxu if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified) 1108139013Sdavidxu return true; 1109139257Sdavidxu 1110139013Sdavidxu // The field width is valid for all conversions except n 1111178646Sdavidxu switch (CS.getKind()) { 1112178646Sdavidxu case ConversionSpecifier::nArg: 1113139257Sdavidxu return false; 1114139258Sdavidxu 1115139257Sdavidxu default: 1116139258Sdavidxu return true; 1117139257Sdavidxu } 1118139013Sdavidxu} 1119139013Sdavidxu