1e5dd7070Spatrick // FormatString.cpp - Common stuff for handling printf/scanf formats -*- C++ -*- 2e5dd7070Spatrick // 3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information. 5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e5dd7070Spatrick // 7e5dd7070Spatrick //===----------------------------------------------------------------------===// 8e5dd7070Spatrick // 9e5dd7070Spatrick // Shared details for processing format strings of printf and scanf 10e5dd7070Spatrick // (and friends). 11e5dd7070Spatrick // 12e5dd7070Spatrick //===----------------------------------------------------------------------===// 13e5dd7070Spatrick 14e5dd7070Spatrick #include "FormatStringParsing.h" 15e5dd7070Spatrick #include "clang/Basic/LangOptions.h" 16e5dd7070Spatrick #include "clang/Basic/TargetInfo.h" 17e5dd7070Spatrick #include "llvm/Support/ConvertUTF.h" 18e5dd7070Spatrick 19e5dd7070Spatrick using clang::analyze_format_string::ArgType; 20e5dd7070Spatrick using clang::analyze_format_string::FormatStringHandler; 21e5dd7070Spatrick using clang::analyze_format_string::FormatSpecifier; 22e5dd7070Spatrick using clang::analyze_format_string::LengthModifier; 23e5dd7070Spatrick using clang::analyze_format_string::OptionalAmount; 24e5dd7070Spatrick using clang::analyze_format_string::PositionContext; 25e5dd7070Spatrick using clang::analyze_format_string::ConversionSpecifier; 26e5dd7070Spatrick using namespace clang; 27e5dd7070Spatrick 28e5dd7070Spatrick // Key function to FormatStringHandler. 29e5dd7070Spatrick FormatStringHandler::~FormatStringHandler() {} 30e5dd7070Spatrick 31e5dd7070Spatrick //===----------------------------------------------------------------------===// 32e5dd7070Spatrick // Functions for parsing format strings components in both printf and 33e5dd7070Spatrick // scanf format strings. 34e5dd7070Spatrick //===----------------------------------------------------------------------===// 35e5dd7070Spatrick 36e5dd7070Spatrick OptionalAmount 37e5dd7070Spatrick clang::analyze_format_string::ParseAmount(const char *&Beg, const char *E) { 38e5dd7070Spatrick const char *I = Beg; 39e5dd7070Spatrick UpdateOnReturn <const char*> UpdateBeg(Beg, I); 40e5dd7070Spatrick 41e5dd7070Spatrick unsigned accumulator = 0; 42e5dd7070Spatrick bool hasDigits = false; 43e5dd7070Spatrick 44e5dd7070Spatrick for ( ; I != E; ++I) { 45e5dd7070Spatrick char c = *I; 46e5dd7070Spatrick if (c >= '0' && c <= '9') { 47e5dd7070Spatrick hasDigits = true; 48e5dd7070Spatrick accumulator = (accumulator * 10) + (c - '0'); 49e5dd7070Spatrick continue; 50e5dd7070Spatrick } 51e5dd7070Spatrick 52e5dd7070Spatrick if (hasDigits) 53e5dd7070Spatrick return OptionalAmount(OptionalAmount::Constant, accumulator, Beg, I - Beg, 54e5dd7070Spatrick false); 55e5dd7070Spatrick 56e5dd7070Spatrick break; 57e5dd7070Spatrick } 58e5dd7070Spatrick 59e5dd7070Spatrick return OptionalAmount(); 60e5dd7070Spatrick } 61e5dd7070Spatrick 62e5dd7070Spatrick OptionalAmount 63e5dd7070Spatrick clang::analyze_format_string::ParseNonPositionAmount(const char *&Beg, 64e5dd7070Spatrick const char *E, 65e5dd7070Spatrick unsigned &argIndex) { 66e5dd7070Spatrick if (*Beg == '*') { 67e5dd7070Spatrick ++Beg; 68e5dd7070Spatrick return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg, 0, false); 69e5dd7070Spatrick } 70e5dd7070Spatrick 71e5dd7070Spatrick return ParseAmount(Beg, E); 72e5dd7070Spatrick } 73e5dd7070Spatrick 74e5dd7070Spatrick OptionalAmount 75e5dd7070Spatrick clang::analyze_format_string::ParsePositionAmount(FormatStringHandler &H, 76e5dd7070Spatrick const char *Start, 77e5dd7070Spatrick const char *&Beg, 78e5dd7070Spatrick const char *E, 79e5dd7070Spatrick PositionContext p) { 80e5dd7070Spatrick if (*Beg == '*') { 81e5dd7070Spatrick const char *I = Beg + 1; 82e5dd7070Spatrick const OptionalAmount &Amt = ParseAmount(I, E); 83e5dd7070Spatrick 84e5dd7070Spatrick if (Amt.getHowSpecified() == OptionalAmount::NotSpecified) { 85e5dd7070Spatrick H.HandleInvalidPosition(Beg, I - Beg, p); 86e5dd7070Spatrick return OptionalAmount(false); 87e5dd7070Spatrick } 88e5dd7070Spatrick 89e5dd7070Spatrick if (I == E) { 90e5dd7070Spatrick // No more characters left? 91e5dd7070Spatrick H.HandleIncompleteSpecifier(Start, E - Start); 92e5dd7070Spatrick return OptionalAmount(false); 93e5dd7070Spatrick } 94e5dd7070Spatrick 95e5dd7070Spatrick assert(Amt.getHowSpecified() == OptionalAmount::Constant); 96e5dd7070Spatrick 97e5dd7070Spatrick if (*I == '$') { 98e5dd7070Spatrick // Handle positional arguments 99e5dd7070Spatrick 100e5dd7070Spatrick // Special case: '*0$', since this is an easy mistake. 101e5dd7070Spatrick if (Amt.getConstantAmount() == 0) { 102e5dd7070Spatrick H.HandleZeroPosition(Beg, I - Beg + 1); 103e5dd7070Spatrick return OptionalAmount(false); 104e5dd7070Spatrick } 105e5dd7070Spatrick 106e5dd7070Spatrick const char *Tmp = Beg; 107e5dd7070Spatrick Beg = ++I; 108e5dd7070Spatrick 109e5dd7070Spatrick return OptionalAmount(OptionalAmount::Arg, Amt.getConstantAmount() - 1, 110e5dd7070Spatrick Tmp, 0, true); 111e5dd7070Spatrick } 112e5dd7070Spatrick 113e5dd7070Spatrick H.HandleInvalidPosition(Beg, I - Beg, p); 114e5dd7070Spatrick return OptionalAmount(false); 115e5dd7070Spatrick } 116e5dd7070Spatrick 117e5dd7070Spatrick return ParseAmount(Beg, E); 118e5dd7070Spatrick } 119e5dd7070Spatrick 120e5dd7070Spatrick 121e5dd7070Spatrick bool 122e5dd7070Spatrick clang::analyze_format_string::ParseFieldWidth(FormatStringHandler &H, 123e5dd7070Spatrick FormatSpecifier &CS, 124e5dd7070Spatrick const char *Start, 125e5dd7070Spatrick const char *&Beg, const char *E, 126e5dd7070Spatrick unsigned *argIndex) { 127e5dd7070Spatrick // FIXME: Support negative field widths. 128e5dd7070Spatrick if (argIndex) { 129e5dd7070Spatrick CS.setFieldWidth(ParseNonPositionAmount(Beg, E, *argIndex)); 130e5dd7070Spatrick } 131e5dd7070Spatrick else { 132e5dd7070Spatrick const OptionalAmount Amt = 133e5dd7070Spatrick ParsePositionAmount(H, Start, Beg, E, 134e5dd7070Spatrick analyze_format_string::FieldWidthPos); 135e5dd7070Spatrick 136e5dd7070Spatrick if (Amt.isInvalid()) 137e5dd7070Spatrick return true; 138e5dd7070Spatrick CS.setFieldWidth(Amt); 139e5dd7070Spatrick } 140e5dd7070Spatrick return false; 141e5dd7070Spatrick } 142e5dd7070Spatrick 143e5dd7070Spatrick bool 144e5dd7070Spatrick clang::analyze_format_string::ParseArgPosition(FormatStringHandler &H, 145e5dd7070Spatrick FormatSpecifier &FS, 146e5dd7070Spatrick const char *Start, 147e5dd7070Spatrick const char *&Beg, 148e5dd7070Spatrick const char *E) { 149e5dd7070Spatrick const char *I = Beg; 150e5dd7070Spatrick 151e5dd7070Spatrick const OptionalAmount &Amt = ParseAmount(I, E); 152e5dd7070Spatrick 153e5dd7070Spatrick if (I == E) { 154e5dd7070Spatrick // No more characters left? 155e5dd7070Spatrick H.HandleIncompleteSpecifier(Start, E - Start); 156e5dd7070Spatrick return true; 157e5dd7070Spatrick } 158e5dd7070Spatrick 159e5dd7070Spatrick if (Amt.getHowSpecified() == OptionalAmount::Constant && *(I++) == '$') { 160e5dd7070Spatrick // Warn that positional arguments are non-standard. 161e5dd7070Spatrick H.HandlePosition(Start, I - Start); 162e5dd7070Spatrick 163e5dd7070Spatrick // Special case: '%0$', since this is an easy mistake. 164e5dd7070Spatrick if (Amt.getConstantAmount() == 0) { 165e5dd7070Spatrick H.HandleZeroPosition(Start, I - Start); 166e5dd7070Spatrick return true; 167e5dd7070Spatrick } 168e5dd7070Spatrick 169e5dd7070Spatrick FS.setArgIndex(Amt.getConstantAmount() - 1); 170e5dd7070Spatrick FS.setUsesPositionalArg(); 171e5dd7070Spatrick // Update the caller's pointer if we decided to consume 172e5dd7070Spatrick // these characters. 173e5dd7070Spatrick Beg = I; 174e5dd7070Spatrick return false; 175e5dd7070Spatrick } 176e5dd7070Spatrick 177e5dd7070Spatrick return false; 178e5dd7070Spatrick } 179e5dd7070Spatrick 180e5dd7070Spatrick bool 181e5dd7070Spatrick clang::analyze_format_string::ParseVectorModifier(FormatStringHandler &H, 182e5dd7070Spatrick FormatSpecifier &FS, 183e5dd7070Spatrick const char *&I, 184e5dd7070Spatrick const char *E, 185e5dd7070Spatrick const LangOptions &LO) { 186e5dd7070Spatrick if (!LO.OpenCL) 187e5dd7070Spatrick return false; 188e5dd7070Spatrick 189e5dd7070Spatrick const char *Start = I; 190e5dd7070Spatrick if (*I == 'v') { 191e5dd7070Spatrick ++I; 192e5dd7070Spatrick 193e5dd7070Spatrick if (I == E) { 194e5dd7070Spatrick H.HandleIncompleteSpecifier(Start, E - Start); 195e5dd7070Spatrick return true; 196e5dd7070Spatrick } 197e5dd7070Spatrick 198e5dd7070Spatrick OptionalAmount NumElts = ParseAmount(I, E); 199e5dd7070Spatrick if (NumElts.getHowSpecified() != OptionalAmount::Constant) { 200e5dd7070Spatrick H.HandleIncompleteSpecifier(Start, E - Start); 201e5dd7070Spatrick return true; 202e5dd7070Spatrick } 203e5dd7070Spatrick 204e5dd7070Spatrick FS.setVectorNumElts(NumElts); 205e5dd7070Spatrick } 206e5dd7070Spatrick 207e5dd7070Spatrick return false; 208e5dd7070Spatrick } 209e5dd7070Spatrick 210e5dd7070Spatrick bool 211e5dd7070Spatrick clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS, 212e5dd7070Spatrick const char *&I, 213e5dd7070Spatrick const char *E, 214e5dd7070Spatrick const LangOptions &LO, 215e5dd7070Spatrick bool IsScanf) { 216e5dd7070Spatrick LengthModifier::Kind lmKind = LengthModifier::None; 217e5dd7070Spatrick const char *lmPosition = I; 218e5dd7070Spatrick switch (*I) { 219e5dd7070Spatrick default: 220e5dd7070Spatrick return false; 221e5dd7070Spatrick case 'h': 222e5dd7070Spatrick ++I; 223e5dd7070Spatrick if (I != E && *I == 'h') { 224e5dd7070Spatrick ++I; 225e5dd7070Spatrick lmKind = LengthModifier::AsChar; 226e5dd7070Spatrick } else if (I != E && *I == 'l' && LO.OpenCL) { 227e5dd7070Spatrick ++I; 228e5dd7070Spatrick lmKind = LengthModifier::AsShortLong; 229e5dd7070Spatrick } else { 230e5dd7070Spatrick lmKind = LengthModifier::AsShort; 231e5dd7070Spatrick } 232e5dd7070Spatrick break; 233e5dd7070Spatrick case 'l': 234e5dd7070Spatrick ++I; 235e5dd7070Spatrick if (I != E && *I == 'l') { 236e5dd7070Spatrick ++I; 237e5dd7070Spatrick lmKind = LengthModifier::AsLongLong; 238e5dd7070Spatrick } else { 239e5dd7070Spatrick lmKind = LengthModifier::AsLong; 240e5dd7070Spatrick } 241e5dd7070Spatrick break; 242e5dd7070Spatrick case 'j': lmKind = LengthModifier::AsIntMax; ++I; break; 243e5dd7070Spatrick case 'z': lmKind = LengthModifier::AsSizeT; ++I; break; 244e5dd7070Spatrick case 't': lmKind = LengthModifier::AsPtrDiff; ++I; break; 245e5dd7070Spatrick case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break; 246e5dd7070Spatrick case 'q': lmKind = LengthModifier::AsQuad; ++I; break; 247e5dd7070Spatrick case 'a': 248e5dd7070Spatrick if (IsScanf && !LO.C99 && !LO.CPlusPlus11) { 249e5dd7070Spatrick // For scanf in C90, look at the next character to see if this should 250e5dd7070Spatrick // be parsed as the GNU extension 'a' length modifier. If not, this 251e5dd7070Spatrick // will be parsed as a conversion specifier. 252e5dd7070Spatrick ++I; 253e5dd7070Spatrick if (I != E && (*I == 's' || *I == 'S' || *I == '[')) { 254e5dd7070Spatrick lmKind = LengthModifier::AsAllocate; 255e5dd7070Spatrick break; 256e5dd7070Spatrick } 257e5dd7070Spatrick --I; 258e5dd7070Spatrick } 259e5dd7070Spatrick return false; 260e5dd7070Spatrick case 'm': 261e5dd7070Spatrick if (IsScanf) { 262e5dd7070Spatrick lmKind = LengthModifier::AsMAllocate; 263e5dd7070Spatrick ++I; 264e5dd7070Spatrick break; 265e5dd7070Spatrick } 266e5dd7070Spatrick return false; 267e5dd7070Spatrick // printf: AsInt64, AsInt32, AsInt3264 268e5dd7070Spatrick // scanf: AsInt64 269e5dd7070Spatrick case 'I': 270e5dd7070Spatrick if (I + 1 != E && I + 2 != E) { 271e5dd7070Spatrick if (I[1] == '6' && I[2] == '4') { 272e5dd7070Spatrick I += 3; 273e5dd7070Spatrick lmKind = LengthModifier::AsInt64; 274e5dd7070Spatrick break; 275e5dd7070Spatrick } 276e5dd7070Spatrick if (IsScanf) 277e5dd7070Spatrick return false; 278e5dd7070Spatrick 279e5dd7070Spatrick if (I[1] == '3' && I[2] == '2') { 280e5dd7070Spatrick I += 3; 281e5dd7070Spatrick lmKind = LengthModifier::AsInt32; 282e5dd7070Spatrick break; 283e5dd7070Spatrick } 284e5dd7070Spatrick } 285e5dd7070Spatrick ++I; 286e5dd7070Spatrick lmKind = LengthModifier::AsInt3264; 287e5dd7070Spatrick break; 288e5dd7070Spatrick case 'w': 289e5dd7070Spatrick lmKind = LengthModifier::AsWide; ++I; break; 290e5dd7070Spatrick } 291e5dd7070Spatrick LengthModifier lm(lmPosition, lmKind); 292e5dd7070Spatrick FS.setLengthModifier(lm); 293e5dd7070Spatrick return true; 294e5dd7070Spatrick } 295e5dd7070Spatrick 296e5dd7070Spatrick bool clang::analyze_format_string::ParseUTF8InvalidSpecifier( 297e5dd7070Spatrick const char *SpecifierBegin, const char *FmtStrEnd, unsigned &Len) { 298e5dd7070Spatrick if (SpecifierBegin + 1 >= FmtStrEnd) 299e5dd7070Spatrick return false; 300e5dd7070Spatrick 301e5dd7070Spatrick const llvm::UTF8 *SB = 302e5dd7070Spatrick reinterpret_cast<const llvm::UTF8 *>(SpecifierBegin + 1); 303e5dd7070Spatrick const llvm::UTF8 *SE = reinterpret_cast<const llvm::UTF8 *>(FmtStrEnd); 304e5dd7070Spatrick const char FirstByte = *SB; 305e5dd7070Spatrick 306e5dd7070Spatrick // If the invalid specifier is a multibyte UTF-8 string, return the 307e5dd7070Spatrick // total length accordingly so that the conversion specifier can be 308e5dd7070Spatrick // properly updated to reflect a complete UTF-8 specifier. 309e5dd7070Spatrick unsigned NumBytes = llvm::getNumBytesForUTF8(FirstByte); 310e5dd7070Spatrick if (NumBytes == 1) 311e5dd7070Spatrick return false; 312e5dd7070Spatrick if (SB + NumBytes > SE) 313e5dd7070Spatrick return false; 314e5dd7070Spatrick 315e5dd7070Spatrick Len = NumBytes + 1; 316e5dd7070Spatrick return true; 317e5dd7070Spatrick } 318e5dd7070Spatrick 319e5dd7070Spatrick //===----------------------------------------------------------------------===// 320e5dd7070Spatrick // Methods on ArgType. 321e5dd7070Spatrick //===----------------------------------------------------------------------===// 322e5dd7070Spatrick 323e5dd7070Spatrick clang::analyze_format_string::ArgType::MatchKind 324e5dd7070Spatrick ArgType::matchesType(ASTContext &C, QualType argTy) const { 325e5dd7070Spatrick if (Ptr) { 326e5dd7070Spatrick // It has to be a pointer. 327e5dd7070Spatrick const PointerType *PT = argTy->getAs<PointerType>(); 328e5dd7070Spatrick if (!PT) 329e5dd7070Spatrick return NoMatch; 330e5dd7070Spatrick 331e5dd7070Spatrick // We cannot write through a const qualified pointer. 332e5dd7070Spatrick if (PT->getPointeeType().isConstQualified()) 333e5dd7070Spatrick return NoMatch; 334e5dd7070Spatrick 335e5dd7070Spatrick argTy = PT->getPointeeType(); 336e5dd7070Spatrick } 337e5dd7070Spatrick 338e5dd7070Spatrick switch (K) { 339e5dd7070Spatrick case InvalidTy: 340e5dd7070Spatrick llvm_unreachable("ArgType must be valid"); 341e5dd7070Spatrick 342e5dd7070Spatrick case UnknownTy: 343e5dd7070Spatrick return Match; 344e5dd7070Spatrick 345e5dd7070Spatrick case AnyCharTy: { 346e5dd7070Spatrick if (const EnumType *ETy = argTy->getAs<EnumType>()) { 347e5dd7070Spatrick // If the enum is incomplete we know nothing about the underlying type. 348e5dd7070Spatrick // Assume that it's 'int'. 349e5dd7070Spatrick if (!ETy->getDecl()->isComplete()) 350e5dd7070Spatrick return NoMatch; 351e5dd7070Spatrick argTy = ETy->getDecl()->getIntegerType(); 352e5dd7070Spatrick } 353e5dd7070Spatrick 354e5dd7070Spatrick if (const BuiltinType *BT = argTy->getAs<BuiltinType>()) 355e5dd7070Spatrick switch (BT->getKind()) { 356e5dd7070Spatrick default: 357e5dd7070Spatrick break; 358e5dd7070Spatrick case BuiltinType::Char_S: 359e5dd7070Spatrick case BuiltinType::SChar: 360e5dd7070Spatrick case BuiltinType::UChar: 361e5dd7070Spatrick case BuiltinType::Char_U: 362e5dd7070Spatrick case BuiltinType::Bool: 363e5dd7070Spatrick return Match; 364e5dd7070Spatrick } 365e5dd7070Spatrick return NoMatch; 366e5dd7070Spatrick } 367e5dd7070Spatrick 368e5dd7070Spatrick case SpecificTy: { 369e5dd7070Spatrick if (const EnumType *ETy = argTy->getAs<EnumType>()) { 370e5dd7070Spatrick // If the enum is incomplete we know nothing about the underlying type. 371e5dd7070Spatrick // Assume that it's 'int'. 372e5dd7070Spatrick if (!ETy->getDecl()->isComplete()) 373e5dd7070Spatrick argTy = C.IntTy; 374e5dd7070Spatrick else 375e5dd7070Spatrick argTy = ETy->getDecl()->getIntegerType(); 376e5dd7070Spatrick } 377e5dd7070Spatrick argTy = C.getCanonicalType(argTy).getUnqualifiedType(); 378e5dd7070Spatrick 379e5dd7070Spatrick if (T == argTy) 380e5dd7070Spatrick return Match; 381e5dd7070Spatrick // Check for "compatible types". 382e5dd7070Spatrick if (const BuiltinType *BT = argTy->getAs<BuiltinType>()) 383e5dd7070Spatrick switch (BT->getKind()) { 384e5dd7070Spatrick default: 385e5dd7070Spatrick break; 386e5dd7070Spatrick case BuiltinType::Char_S: 387e5dd7070Spatrick case BuiltinType::SChar: 388e5dd7070Spatrick case BuiltinType::Char_U: 389e5dd7070Spatrick case BuiltinType::UChar: 390e5dd7070Spatrick case BuiltinType::Bool: 391e5dd7070Spatrick if (T == C.UnsignedShortTy || T == C.ShortTy) 392e5dd7070Spatrick return NoMatchTypeConfusion; 393e5dd7070Spatrick return T == C.UnsignedCharTy || T == C.SignedCharTy ? Match 394e5dd7070Spatrick : NoMatch; 395e5dd7070Spatrick case BuiltinType::Short: 396e5dd7070Spatrick return T == C.UnsignedShortTy ? Match : NoMatch; 397e5dd7070Spatrick case BuiltinType::UShort: 398e5dd7070Spatrick return T == C.ShortTy ? Match : NoMatch; 399e5dd7070Spatrick case BuiltinType::Int: 400e5dd7070Spatrick return T == C.UnsignedIntTy ? Match : NoMatch; 401e5dd7070Spatrick case BuiltinType::UInt: 402e5dd7070Spatrick return T == C.IntTy ? Match : NoMatch; 403e5dd7070Spatrick case BuiltinType::Long: 404e5dd7070Spatrick return T == C.UnsignedLongTy ? Match : NoMatch; 405e5dd7070Spatrick case BuiltinType::ULong: 406e5dd7070Spatrick return T == C.LongTy ? Match : NoMatch; 407e5dd7070Spatrick case BuiltinType::LongLong: 408e5dd7070Spatrick return T == C.UnsignedLongLongTy ? Match : NoMatch; 409e5dd7070Spatrick case BuiltinType::ULongLong: 410e5dd7070Spatrick return T == C.LongLongTy ? Match : NoMatch; 411e5dd7070Spatrick } 412e5dd7070Spatrick return NoMatch; 413e5dd7070Spatrick } 414e5dd7070Spatrick 415e5dd7070Spatrick case CStrTy: { 416e5dd7070Spatrick const PointerType *PT = argTy->getAs<PointerType>(); 417e5dd7070Spatrick if (!PT) 418e5dd7070Spatrick return NoMatch; 419e5dd7070Spatrick QualType pointeeTy = PT->getPointeeType(); 420e5dd7070Spatrick if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>()) 421e5dd7070Spatrick switch (BT->getKind()) { 422e5dd7070Spatrick case BuiltinType::Char_U: 423e5dd7070Spatrick case BuiltinType::UChar: 424e5dd7070Spatrick case BuiltinType::Char_S: 425e5dd7070Spatrick case BuiltinType::SChar: 426e5dd7070Spatrick return Match; 427e5dd7070Spatrick default: 428e5dd7070Spatrick break; 429e5dd7070Spatrick } 430e5dd7070Spatrick 431e5dd7070Spatrick return NoMatch; 432e5dd7070Spatrick } 433e5dd7070Spatrick 434e5dd7070Spatrick case WCStrTy: { 435e5dd7070Spatrick const PointerType *PT = argTy->getAs<PointerType>(); 436e5dd7070Spatrick if (!PT) 437e5dd7070Spatrick return NoMatch; 438e5dd7070Spatrick QualType pointeeTy = 439e5dd7070Spatrick C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType(); 440e5dd7070Spatrick return pointeeTy == C.getWideCharType() ? Match : NoMatch; 441e5dd7070Spatrick } 442e5dd7070Spatrick 443e5dd7070Spatrick case WIntTy: { 444e5dd7070Spatrick QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType(); 445e5dd7070Spatrick 446e5dd7070Spatrick if (C.getCanonicalType(argTy).getUnqualifiedType() == WInt) 447e5dd7070Spatrick return Match; 448e5dd7070Spatrick 449e5dd7070Spatrick QualType PromoArg = argTy->isPromotableIntegerType() 450e5dd7070Spatrick ? C.getPromotedIntegerType(argTy) 451e5dd7070Spatrick : argTy; 452e5dd7070Spatrick PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType(); 453e5dd7070Spatrick 454e5dd7070Spatrick // If the promoted argument is the corresponding signed type of the 455e5dd7070Spatrick // wint_t type, then it should match. 456e5dd7070Spatrick if (PromoArg->hasSignedIntegerRepresentation() && 457e5dd7070Spatrick C.getCorrespondingUnsignedType(PromoArg) == WInt) 458e5dd7070Spatrick return Match; 459e5dd7070Spatrick 460e5dd7070Spatrick return WInt == PromoArg ? Match : NoMatch; 461e5dd7070Spatrick } 462e5dd7070Spatrick 463e5dd7070Spatrick case CPointerTy: 464e5dd7070Spatrick if (argTy->isVoidPointerType()) { 465e5dd7070Spatrick return Match; 466e5dd7070Spatrick } if (argTy->isPointerType() || argTy->isObjCObjectPointerType() || 467e5dd7070Spatrick argTy->isBlockPointerType() || argTy->isNullPtrType()) { 468e5dd7070Spatrick return NoMatchPedantic; 469e5dd7070Spatrick } else { 470e5dd7070Spatrick return NoMatch; 471e5dd7070Spatrick } 472e5dd7070Spatrick 473e5dd7070Spatrick case ObjCPointerTy: { 474e5dd7070Spatrick if (argTy->getAs<ObjCObjectPointerType>() || 475e5dd7070Spatrick argTy->getAs<BlockPointerType>()) 476e5dd7070Spatrick return Match; 477e5dd7070Spatrick 478e5dd7070Spatrick // Handle implicit toll-free bridging. 479e5dd7070Spatrick if (const PointerType *PT = argTy->getAs<PointerType>()) { 480e5dd7070Spatrick // Things such as CFTypeRef are really just opaque pointers 481e5dd7070Spatrick // to C structs representing CF types that can often be bridged 482e5dd7070Spatrick // to Objective-C objects. Since the compiler doesn't know which 483e5dd7070Spatrick // structs can be toll-free bridged, we just accept them all. 484e5dd7070Spatrick QualType pointee = PT->getPointeeType(); 485e5dd7070Spatrick if (pointee->getAsStructureType() || pointee->isVoidType()) 486e5dd7070Spatrick return Match; 487e5dd7070Spatrick } 488e5dd7070Spatrick return NoMatch; 489e5dd7070Spatrick } 490e5dd7070Spatrick } 491e5dd7070Spatrick 492e5dd7070Spatrick llvm_unreachable("Invalid ArgType Kind!"); 493e5dd7070Spatrick } 494e5dd7070Spatrick 495e5dd7070Spatrick ArgType ArgType::makeVectorType(ASTContext &C, unsigned NumElts) const { 496e5dd7070Spatrick // Check for valid vector element types. 497e5dd7070Spatrick if (T.isNull()) 498e5dd7070Spatrick return ArgType::Invalid(); 499e5dd7070Spatrick 500e5dd7070Spatrick QualType Vec = C.getExtVectorType(T, NumElts); 501e5dd7070Spatrick return ArgType(Vec, Name); 502e5dd7070Spatrick } 503e5dd7070Spatrick 504e5dd7070Spatrick QualType ArgType::getRepresentativeType(ASTContext &C) const { 505e5dd7070Spatrick QualType Res; 506e5dd7070Spatrick switch (K) { 507e5dd7070Spatrick case InvalidTy: 508e5dd7070Spatrick llvm_unreachable("No representative type for Invalid ArgType"); 509e5dd7070Spatrick case UnknownTy: 510e5dd7070Spatrick llvm_unreachable("No representative type for Unknown ArgType"); 511e5dd7070Spatrick case AnyCharTy: 512e5dd7070Spatrick Res = C.CharTy; 513e5dd7070Spatrick break; 514e5dd7070Spatrick case SpecificTy: 515e5dd7070Spatrick Res = T; 516e5dd7070Spatrick break; 517e5dd7070Spatrick case CStrTy: 518e5dd7070Spatrick Res = C.getPointerType(C.CharTy); 519e5dd7070Spatrick break; 520e5dd7070Spatrick case WCStrTy: 521e5dd7070Spatrick Res = C.getPointerType(C.getWideCharType()); 522e5dd7070Spatrick break; 523e5dd7070Spatrick case ObjCPointerTy: 524e5dd7070Spatrick Res = C.ObjCBuiltinIdTy; 525e5dd7070Spatrick break; 526e5dd7070Spatrick case CPointerTy: 527e5dd7070Spatrick Res = C.VoidPtrTy; 528e5dd7070Spatrick break; 529e5dd7070Spatrick case WIntTy: { 530e5dd7070Spatrick Res = C.getWIntType(); 531e5dd7070Spatrick break; 532e5dd7070Spatrick } 533e5dd7070Spatrick } 534e5dd7070Spatrick 535e5dd7070Spatrick if (Ptr) 536e5dd7070Spatrick Res = C.getPointerType(Res); 537e5dd7070Spatrick return Res; 538e5dd7070Spatrick } 539e5dd7070Spatrick 540e5dd7070Spatrick std::string ArgType::getRepresentativeTypeName(ASTContext &C) const { 541*ec727ea7Spatrick std::string S = getRepresentativeType(C).getAsString(C.getPrintingPolicy()); 542e5dd7070Spatrick 543e5dd7070Spatrick std::string Alias; 544e5dd7070Spatrick if (Name) { 545e5dd7070Spatrick // Use a specific name for this type, e.g. "size_t". 546e5dd7070Spatrick Alias = Name; 547e5dd7070Spatrick if (Ptr) { 548e5dd7070Spatrick // If ArgType is actually a pointer to T, append an asterisk. 549e5dd7070Spatrick Alias += (Alias[Alias.size()-1] == '*') ? "*" : " *"; 550e5dd7070Spatrick } 551e5dd7070Spatrick // If Alias is the same as the underlying type, e.g. wchar_t, then drop it. 552e5dd7070Spatrick if (S == Alias) 553e5dd7070Spatrick Alias.clear(); 554e5dd7070Spatrick } 555e5dd7070Spatrick 556e5dd7070Spatrick if (!Alias.empty()) 557e5dd7070Spatrick return std::string("'") + Alias + "' (aka '" + S + "')"; 558e5dd7070Spatrick return std::string("'") + S + "'"; 559e5dd7070Spatrick } 560e5dd7070Spatrick 561e5dd7070Spatrick 562e5dd7070Spatrick //===----------------------------------------------------------------------===// 563e5dd7070Spatrick // Methods on OptionalAmount. 564e5dd7070Spatrick //===----------------------------------------------------------------------===// 565e5dd7070Spatrick 566e5dd7070Spatrick ArgType 567e5dd7070Spatrick analyze_format_string::OptionalAmount::getArgType(ASTContext &Ctx) const { 568e5dd7070Spatrick return Ctx.IntTy; 569e5dd7070Spatrick } 570e5dd7070Spatrick 571e5dd7070Spatrick //===----------------------------------------------------------------------===// 572e5dd7070Spatrick // Methods on LengthModifier. 573e5dd7070Spatrick //===----------------------------------------------------------------------===// 574e5dd7070Spatrick 575e5dd7070Spatrick const char * 576e5dd7070Spatrick analyze_format_string::LengthModifier::toString() const { 577e5dd7070Spatrick switch (kind) { 578e5dd7070Spatrick case AsChar: 579e5dd7070Spatrick return "hh"; 580e5dd7070Spatrick case AsShort: 581e5dd7070Spatrick return "h"; 582e5dd7070Spatrick case AsShortLong: 583e5dd7070Spatrick return "hl"; 584e5dd7070Spatrick case AsLong: // or AsWideChar 585e5dd7070Spatrick return "l"; 586e5dd7070Spatrick case AsLongLong: 587e5dd7070Spatrick return "ll"; 588e5dd7070Spatrick case AsQuad: 589e5dd7070Spatrick return "q"; 590e5dd7070Spatrick case AsIntMax: 591e5dd7070Spatrick return "j"; 592e5dd7070Spatrick case AsSizeT: 593e5dd7070Spatrick return "z"; 594e5dd7070Spatrick case AsPtrDiff: 595e5dd7070Spatrick return "t"; 596e5dd7070Spatrick case AsInt32: 597e5dd7070Spatrick return "I32"; 598e5dd7070Spatrick case AsInt3264: 599e5dd7070Spatrick return "I"; 600e5dd7070Spatrick case AsInt64: 601e5dd7070Spatrick return "I64"; 602e5dd7070Spatrick case AsLongDouble: 603e5dd7070Spatrick return "L"; 604e5dd7070Spatrick case AsAllocate: 605e5dd7070Spatrick return "a"; 606e5dd7070Spatrick case AsMAllocate: 607e5dd7070Spatrick return "m"; 608e5dd7070Spatrick case AsWide: 609e5dd7070Spatrick return "w"; 610e5dd7070Spatrick case None: 611e5dd7070Spatrick return ""; 612e5dd7070Spatrick } 613e5dd7070Spatrick return nullptr; 614e5dd7070Spatrick } 615e5dd7070Spatrick 616e5dd7070Spatrick //===----------------------------------------------------------------------===// 617e5dd7070Spatrick // Methods on ConversionSpecifier. 618e5dd7070Spatrick //===----------------------------------------------------------------------===// 619e5dd7070Spatrick 620e5dd7070Spatrick const char *ConversionSpecifier::toString() const { 621e5dd7070Spatrick switch (kind) { 622e5dd7070Spatrick case dArg: return "d"; 623e5dd7070Spatrick case DArg: return "D"; 624e5dd7070Spatrick case iArg: return "i"; 625e5dd7070Spatrick case oArg: return "o"; 626e5dd7070Spatrick case OArg: return "O"; 627e5dd7070Spatrick case uArg: return "u"; 628e5dd7070Spatrick case UArg: return "U"; 629e5dd7070Spatrick case xArg: return "x"; 630e5dd7070Spatrick case XArg: return "X"; 631e5dd7070Spatrick case fArg: return "f"; 632e5dd7070Spatrick case FArg: return "F"; 633e5dd7070Spatrick case eArg: return "e"; 634e5dd7070Spatrick case EArg: return "E"; 635e5dd7070Spatrick case gArg: return "g"; 636e5dd7070Spatrick case GArg: return "G"; 637e5dd7070Spatrick case aArg: return "a"; 638e5dd7070Spatrick case AArg: return "A"; 639e5dd7070Spatrick case cArg: return "c"; 640e5dd7070Spatrick case sArg: return "s"; 641e5dd7070Spatrick case pArg: return "p"; 642e5dd7070Spatrick case PArg: 643e5dd7070Spatrick return "P"; 644e5dd7070Spatrick case nArg: return "n"; 645e5dd7070Spatrick case PercentArg: return "%"; 646e5dd7070Spatrick case ScanListArg: return "["; 647e5dd7070Spatrick case InvalidSpecifier: return nullptr; 648e5dd7070Spatrick 649e5dd7070Spatrick // POSIX unicode extensions. 650e5dd7070Spatrick case CArg: return "C"; 651e5dd7070Spatrick case SArg: return "S"; 652e5dd7070Spatrick 653e5dd7070Spatrick // Objective-C specific specifiers. 654e5dd7070Spatrick case ObjCObjArg: return "@"; 655e5dd7070Spatrick 656e5dd7070Spatrick // FreeBSD kernel specific specifiers. 657e5dd7070Spatrick case FreeBSDbArg: return "b"; 658e5dd7070Spatrick case FreeBSDDArg: return "D"; 659e5dd7070Spatrick case FreeBSDrArg: return "r"; 660e5dd7070Spatrick case FreeBSDyArg: return "y"; 661e5dd7070Spatrick 662e5dd7070Spatrick // GlibC specific specifiers. 663e5dd7070Spatrick case PrintErrno: return "m"; 664e5dd7070Spatrick 665e5dd7070Spatrick // MS specific specifiers. 666e5dd7070Spatrick case ZArg: return "Z"; 667e5dd7070Spatrick } 668e5dd7070Spatrick return nullptr; 669e5dd7070Spatrick } 670e5dd7070Spatrick 671e5dd7070Spatrick Optional<ConversionSpecifier> 672e5dd7070Spatrick ConversionSpecifier::getStandardSpecifier() const { 673e5dd7070Spatrick ConversionSpecifier::Kind NewKind; 674e5dd7070Spatrick 675e5dd7070Spatrick switch (getKind()) { 676e5dd7070Spatrick default: 677e5dd7070Spatrick return None; 678e5dd7070Spatrick case DArg: 679e5dd7070Spatrick NewKind = dArg; 680e5dd7070Spatrick break; 681e5dd7070Spatrick case UArg: 682e5dd7070Spatrick NewKind = uArg; 683e5dd7070Spatrick break; 684e5dd7070Spatrick case OArg: 685e5dd7070Spatrick NewKind = oArg; 686e5dd7070Spatrick break; 687e5dd7070Spatrick } 688e5dd7070Spatrick 689e5dd7070Spatrick ConversionSpecifier FixedCS(*this); 690e5dd7070Spatrick FixedCS.setKind(NewKind); 691e5dd7070Spatrick return FixedCS; 692e5dd7070Spatrick } 693e5dd7070Spatrick 694e5dd7070Spatrick //===----------------------------------------------------------------------===// 695e5dd7070Spatrick // Methods on OptionalAmount. 696e5dd7070Spatrick //===----------------------------------------------------------------------===// 697e5dd7070Spatrick 698e5dd7070Spatrick void OptionalAmount::toString(raw_ostream &os) const { 699e5dd7070Spatrick switch (hs) { 700e5dd7070Spatrick case Invalid: 701e5dd7070Spatrick case NotSpecified: 702e5dd7070Spatrick return; 703e5dd7070Spatrick case Arg: 704e5dd7070Spatrick if (UsesDotPrefix) 705e5dd7070Spatrick os << "."; 706e5dd7070Spatrick if (usesPositionalArg()) 707e5dd7070Spatrick os << "*" << getPositionalArgIndex() << "$"; 708e5dd7070Spatrick else 709e5dd7070Spatrick os << "*"; 710e5dd7070Spatrick break; 711e5dd7070Spatrick case Constant: 712e5dd7070Spatrick if (UsesDotPrefix) 713e5dd7070Spatrick os << "."; 714e5dd7070Spatrick os << amt; 715e5dd7070Spatrick break; 716e5dd7070Spatrick } 717e5dd7070Spatrick } 718e5dd7070Spatrick 719e5dd7070Spatrick bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target, 720e5dd7070Spatrick const LangOptions &LO) const { 721e5dd7070Spatrick switch (LM.getKind()) { 722e5dd7070Spatrick case LengthModifier::None: 723e5dd7070Spatrick return true; 724e5dd7070Spatrick 725e5dd7070Spatrick // Handle most integer flags 726e5dd7070Spatrick case LengthModifier::AsShort: 727e5dd7070Spatrick // Length modifier only applies to FP vectors. 728e5dd7070Spatrick if (LO.OpenCL && CS.isDoubleArg()) 729e5dd7070Spatrick return !VectorNumElts.isInvalid(); 730e5dd7070Spatrick 731e5dd7070Spatrick if (Target.getTriple().isOSMSVCRT()) { 732e5dd7070Spatrick switch (CS.getKind()) { 733e5dd7070Spatrick case ConversionSpecifier::cArg: 734e5dd7070Spatrick case ConversionSpecifier::CArg: 735e5dd7070Spatrick case ConversionSpecifier::sArg: 736e5dd7070Spatrick case ConversionSpecifier::SArg: 737e5dd7070Spatrick case ConversionSpecifier::ZArg: 738e5dd7070Spatrick return true; 739e5dd7070Spatrick default: 740e5dd7070Spatrick break; 741e5dd7070Spatrick } 742e5dd7070Spatrick } 743e5dd7070Spatrick LLVM_FALLTHROUGH; 744e5dd7070Spatrick case LengthModifier::AsChar: 745e5dd7070Spatrick case LengthModifier::AsLongLong: 746e5dd7070Spatrick case LengthModifier::AsQuad: 747e5dd7070Spatrick case LengthModifier::AsIntMax: 748e5dd7070Spatrick case LengthModifier::AsSizeT: 749e5dd7070Spatrick case LengthModifier::AsPtrDiff: 750e5dd7070Spatrick switch (CS.getKind()) { 751e5dd7070Spatrick case ConversionSpecifier::dArg: 752e5dd7070Spatrick case ConversionSpecifier::DArg: 753e5dd7070Spatrick case ConversionSpecifier::iArg: 754e5dd7070Spatrick case ConversionSpecifier::oArg: 755e5dd7070Spatrick case ConversionSpecifier::OArg: 756e5dd7070Spatrick case ConversionSpecifier::uArg: 757e5dd7070Spatrick case ConversionSpecifier::UArg: 758e5dd7070Spatrick case ConversionSpecifier::xArg: 759e5dd7070Spatrick case ConversionSpecifier::XArg: 760e5dd7070Spatrick case ConversionSpecifier::nArg: 761e5dd7070Spatrick return true; 762e5dd7070Spatrick case ConversionSpecifier::FreeBSDrArg: 763e5dd7070Spatrick case ConversionSpecifier::FreeBSDyArg: 764e5dd7070Spatrick return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS4(); 765e5dd7070Spatrick default: 766e5dd7070Spatrick return false; 767e5dd7070Spatrick } 768e5dd7070Spatrick 769e5dd7070Spatrick case LengthModifier::AsShortLong: 770e5dd7070Spatrick return LO.OpenCL && !VectorNumElts.isInvalid(); 771e5dd7070Spatrick 772e5dd7070Spatrick // Handle 'l' flag 773e5dd7070Spatrick case LengthModifier::AsLong: // or AsWideChar 774e5dd7070Spatrick if (CS.isDoubleArg()) { 775e5dd7070Spatrick // Invalid for OpenCL FP scalars. 776e5dd7070Spatrick if (LO.OpenCL && VectorNumElts.isInvalid()) 777e5dd7070Spatrick return false; 778e5dd7070Spatrick return true; 779e5dd7070Spatrick } 780e5dd7070Spatrick 781e5dd7070Spatrick switch (CS.getKind()) { 782e5dd7070Spatrick case ConversionSpecifier::dArg: 783e5dd7070Spatrick case ConversionSpecifier::DArg: 784e5dd7070Spatrick case ConversionSpecifier::iArg: 785e5dd7070Spatrick case ConversionSpecifier::oArg: 786e5dd7070Spatrick case ConversionSpecifier::OArg: 787e5dd7070Spatrick case ConversionSpecifier::uArg: 788e5dd7070Spatrick case ConversionSpecifier::UArg: 789e5dd7070Spatrick case ConversionSpecifier::xArg: 790e5dd7070Spatrick case ConversionSpecifier::XArg: 791e5dd7070Spatrick case ConversionSpecifier::nArg: 792e5dd7070Spatrick case ConversionSpecifier::cArg: 793e5dd7070Spatrick case ConversionSpecifier::sArg: 794e5dd7070Spatrick case ConversionSpecifier::ScanListArg: 795e5dd7070Spatrick case ConversionSpecifier::ZArg: 796e5dd7070Spatrick return true; 797e5dd7070Spatrick case ConversionSpecifier::FreeBSDrArg: 798e5dd7070Spatrick case ConversionSpecifier::FreeBSDyArg: 799e5dd7070Spatrick return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS4(); 800e5dd7070Spatrick default: 801e5dd7070Spatrick return false; 802e5dd7070Spatrick } 803e5dd7070Spatrick 804e5dd7070Spatrick case LengthModifier::AsLongDouble: 805e5dd7070Spatrick switch (CS.getKind()) { 806e5dd7070Spatrick case ConversionSpecifier::aArg: 807e5dd7070Spatrick case ConversionSpecifier::AArg: 808e5dd7070Spatrick case ConversionSpecifier::fArg: 809e5dd7070Spatrick case ConversionSpecifier::FArg: 810e5dd7070Spatrick case ConversionSpecifier::eArg: 811e5dd7070Spatrick case ConversionSpecifier::EArg: 812e5dd7070Spatrick case ConversionSpecifier::gArg: 813e5dd7070Spatrick case ConversionSpecifier::GArg: 814e5dd7070Spatrick return true; 815e5dd7070Spatrick // GNU libc extension. 816e5dd7070Spatrick case ConversionSpecifier::dArg: 817e5dd7070Spatrick case ConversionSpecifier::iArg: 818e5dd7070Spatrick case ConversionSpecifier::oArg: 819e5dd7070Spatrick case ConversionSpecifier::uArg: 820e5dd7070Spatrick case ConversionSpecifier::xArg: 821e5dd7070Spatrick case ConversionSpecifier::XArg: 822e5dd7070Spatrick return !Target.getTriple().isOSDarwin() && 823e5dd7070Spatrick !Target.getTriple().isOSWindows(); 824e5dd7070Spatrick default: 825e5dd7070Spatrick return false; 826e5dd7070Spatrick } 827e5dd7070Spatrick 828e5dd7070Spatrick case LengthModifier::AsAllocate: 829e5dd7070Spatrick switch (CS.getKind()) { 830e5dd7070Spatrick case ConversionSpecifier::sArg: 831e5dd7070Spatrick case ConversionSpecifier::SArg: 832e5dd7070Spatrick case ConversionSpecifier::ScanListArg: 833e5dd7070Spatrick return true; 834e5dd7070Spatrick default: 835e5dd7070Spatrick return false; 836e5dd7070Spatrick } 837e5dd7070Spatrick 838e5dd7070Spatrick case LengthModifier::AsMAllocate: 839e5dd7070Spatrick switch (CS.getKind()) { 840e5dd7070Spatrick case ConversionSpecifier::cArg: 841e5dd7070Spatrick case ConversionSpecifier::CArg: 842e5dd7070Spatrick case ConversionSpecifier::sArg: 843e5dd7070Spatrick case ConversionSpecifier::SArg: 844e5dd7070Spatrick case ConversionSpecifier::ScanListArg: 845e5dd7070Spatrick return true; 846e5dd7070Spatrick default: 847e5dd7070Spatrick return false; 848e5dd7070Spatrick } 849e5dd7070Spatrick case LengthModifier::AsInt32: 850e5dd7070Spatrick case LengthModifier::AsInt3264: 851e5dd7070Spatrick case LengthModifier::AsInt64: 852e5dd7070Spatrick switch (CS.getKind()) { 853e5dd7070Spatrick case ConversionSpecifier::dArg: 854e5dd7070Spatrick case ConversionSpecifier::iArg: 855e5dd7070Spatrick case ConversionSpecifier::oArg: 856e5dd7070Spatrick case ConversionSpecifier::uArg: 857e5dd7070Spatrick case ConversionSpecifier::xArg: 858e5dd7070Spatrick case ConversionSpecifier::XArg: 859e5dd7070Spatrick return Target.getTriple().isOSMSVCRT(); 860e5dd7070Spatrick default: 861e5dd7070Spatrick return false; 862e5dd7070Spatrick } 863e5dd7070Spatrick case LengthModifier::AsWide: 864e5dd7070Spatrick switch (CS.getKind()) { 865e5dd7070Spatrick case ConversionSpecifier::cArg: 866e5dd7070Spatrick case ConversionSpecifier::CArg: 867e5dd7070Spatrick case ConversionSpecifier::sArg: 868e5dd7070Spatrick case ConversionSpecifier::SArg: 869e5dd7070Spatrick case ConversionSpecifier::ZArg: 870e5dd7070Spatrick return Target.getTriple().isOSMSVCRT(); 871e5dd7070Spatrick default: 872e5dd7070Spatrick return false; 873e5dd7070Spatrick } 874e5dd7070Spatrick } 875e5dd7070Spatrick llvm_unreachable("Invalid LengthModifier Kind!"); 876e5dd7070Spatrick } 877e5dd7070Spatrick 878e5dd7070Spatrick bool FormatSpecifier::hasStandardLengthModifier() const { 879e5dd7070Spatrick switch (LM.getKind()) { 880e5dd7070Spatrick case LengthModifier::None: 881e5dd7070Spatrick case LengthModifier::AsChar: 882e5dd7070Spatrick case LengthModifier::AsShort: 883e5dd7070Spatrick case LengthModifier::AsLong: 884e5dd7070Spatrick case LengthModifier::AsLongLong: 885e5dd7070Spatrick case LengthModifier::AsIntMax: 886e5dd7070Spatrick case LengthModifier::AsSizeT: 887e5dd7070Spatrick case LengthModifier::AsPtrDiff: 888e5dd7070Spatrick case LengthModifier::AsLongDouble: 889e5dd7070Spatrick return true; 890e5dd7070Spatrick case LengthModifier::AsAllocate: 891e5dd7070Spatrick case LengthModifier::AsMAllocate: 892e5dd7070Spatrick case LengthModifier::AsQuad: 893e5dd7070Spatrick case LengthModifier::AsInt32: 894e5dd7070Spatrick case LengthModifier::AsInt3264: 895e5dd7070Spatrick case LengthModifier::AsInt64: 896e5dd7070Spatrick case LengthModifier::AsWide: 897e5dd7070Spatrick case LengthModifier::AsShortLong: // ??? 898e5dd7070Spatrick return false; 899e5dd7070Spatrick } 900e5dd7070Spatrick llvm_unreachable("Invalid LengthModifier Kind!"); 901e5dd7070Spatrick } 902e5dd7070Spatrick 903e5dd7070Spatrick bool FormatSpecifier::hasStandardConversionSpecifier( 904e5dd7070Spatrick const LangOptions &LangOpt) const { 905e5dd7070Spatrick switch (CS.getKind()) { 906e5dd7070Spatrick case ConversionSpecifier::cArg: 907e5dd7070Spatrick case ConversionSpecifier::dArg: 908e5dd7070Spatrick case ConversionSpecifier::iArg: 909e5dd7070Spatrick case ConversionSpecifier::oArg: 910e5dd7070Spatrick case ConversionSpecifier::uArg: 911e5dd7070Spatrick case ConversionSpecifier::xArg: 912e5dd7070Spatrick case ConversionSpecifier::XArg: 913e5dd7070Spatrick case ConversionSpecifier::fArg: 914e5dd7070Spatrick case ConversionSpecifier::FArg: 915e5dd7070Spatrick case ConversionSpecifier::eArg: 916e5dd7070Spatrick case ConversionSpecifier::EArg: 917e5dd7070Spatrick case ConversionSpecifier::gArg: 918e5dd7070Spatrick case ConversionSpecifier::GArg: 919e5dd7070Spatrick case ConversionSpecifier::aArg: 920e5dd7070Spatrick case ConversionSpecifier::AArg: 921e5dd7070Spatrick case ConversionSpecifier::sArg: 922e5dd7070Spatrick case ConversionSpecifier::pArg: 923e5dd7070Spatrick case ConversionSpecifier::nArg: 924e5dd7070Spatrick case ConversionSpecifier::ObjCObjArg: 925e5dd7070Spatrick case ConversionSpecifier::ScanListArg: 926e5dd7070Spatrick case ConversionSpecifier::PercentArg: 927e5dd7070Spatrick case ConversionSpecifier::PArg: 928e5dd7070Spatrick return true; 929e5dd7070Spatrick case ConversionSpecifier::CArg: 930e5dd7070Spatrick case ConversionSpecifier::SArg: 931e5dd7070Spatrick return LangOpt.ObjC; 932e5dd7070Spatrick case ConversionSpecifier::InvalidSpecifier: 933e5dd7070Spatrick case ConversionSpecifier::FreeBSDbArg: 934e5dd7070Spatrick case ConversionSpecifier::FreeBSDDArg: 935e5dd7070Spatrick case ConversionSpecifier::FreeBSDrArg: 936e5dd7070Spatrick case ConversionSpecifier::FreeBSDyArg: 937e5dd7070Spatrick case ConversionSpecifier::PrintErrno: 938e5dd7070Spatrick case ConversionSpecifier::DArg: 939e5dd7070Spatrick case ConversionSpecifier::OArg: 940e5dd7070Spatrick case ConversionSpecifier::UArg: 941e5dd7070Spatrick case ConversionSpecifier::ZArg: 942e5dd7070Spatrick return false; 943e5dd7070Spatrick } 944e5dd7070Spatrick llvm_unreachable("Invalid ConversionSpecifier Kind!"); 945e5dd7070Spatrick } 946e5dd7070Spatrick 947e5dd7070Spatrick bool FormatSpecifier::hasStandardLengthConversionCombination() const { 948e5dd7070Spatrick if (LM.getKind() == LengthModifier::AsLongDouble) { 949e5dd7070Spatrick switch(CS.getKind()) { 950e5dd7070Spatrick case ConversionSpecifier::dArg: 951e5dd7070Spatrick case ConversionSpecifier::iArg: 952e5dd7070Spatrick case ConversionSpecifier::oArg: 953e5dd7070Spatrick case ConversionSpecifier::uArg: 954e5dd7070Spatrick case ConversionSpecifier::xArg: 955e5dd7070Spatrick case ConversionSpecifier::XArg: 956e5dd7070Spatrick return false; 957e5dd7070Spatrick default: 958e5dd7070Spatrick return true; 959e5dd7070Spatrick } 960e5dd7070Spatrick } 961e5dd7070Spatrick return true; 962e5dd7070Spatrick } 963e5dd7070Spatrick 964e5dd7070Spatrick Optional<LengthModifier> FormatSpecifier::getCorrectedLengthModifier() const { 965e5dd7070Spatrick if (CS.isAnyIntArg() || CS.getKind() == ConversionSpecifier::nArg) { 966e5dd7070Spatrick if (LM.getKind() == LengthModifier::AsLongDouble || 967e5dd7070Spatrick LM.getKind() == LengthModifier::AsQuad) { 968e5dd7070Spatrick LengthModifier FixedLM(LM); 969e5dd7070Spatrick FixedLM.setKind(LengthModifier::AsLongLong); 970e5dd7070Spatrick return FixedLM; 971e5dd7070Spatrick } 972e5dd7070Spatrick } 973e5dd7070Spatrick 974e5dd7070Spatrick return None; 975e5dd7070Spatrick } 976e5dd7070Spatrick 977e5dd7070Spatrick bool FormatSpecifier::namedTypeToLengthModifier(QualType QT, 978e5dd7070Spatrick LengthModifier &LM) { 979e5dd7070Spatrick assert(isa<TypedefType>(QT) && "Expected a TypedefType"); 980e5dd7070Spatrick const TypedefNameDecl *Typedef = cast<TypedefType>(QT)->getDecl(); 981e5dd7070Spatrick 982e5dd7070Spatrick for (;;) { 983e5dd7070Spatrick const IdentifierInfo *Identifier = Typedef->getIdentifier(); 984e5dd7070Spatrick if (Identifier->getName() == "size_t") { 985e5dd7070Spatrick LM.setKind(LengthModifier::AsSizeT); 986e5dd7070Spatrick return true; 987e5dd7070Spatrick } else if (Identifier->getName() == "ssize_t") { 988e5dd7070Spatrick // Not C99, but common in Unix. 989e5dd7070Spatrick LM.setKind(LengthModifier::AsSizeT); 990e5dd7070Spatrick return true; 991e5dd7070Spatrick } else if (Identifier->getName() == "intmax_t") { 992e5dd7070Spatrick LM.setKind(LengthModifier::AsIntMax); 993e5dd7070Spatrick return true; 994e5dd7070Spatrick } else if (Identifier->getName() == "uintmax_t") { 995e5dd7070Spatrick LM.setKind(LengthModifier::AsIntMax); 996e5dd7070Spatrick return true; 997e5dd7070Spatrick } else if (Identifier->getName() == "ptrdiff_t") { 998e5dd7070Spatrick LM.setKind(LengthModifier::AsPtrDiff); 999e5dd7070Spatrick return true; 1000e5dd7070Spatrick } 1001e5dd7070Spatrick 1002e5dd7070Spatrick QualType T = Typedef->getUnderlyingType(); 1003e5dd7070Spatrick if (!isa<TypedefType>(T)) 1004e5dd7070Spatrick break; 1005e5dd7070Spatrick 1006e5dd7070Spatrick Typedef = cast<TypedefType>(T)->getDecl(); 1007e5dd7070Spatrick } 1008e5dd7070Spatrick return false; 1009e5dd7070Spatrick } 1010