diff options
Diffstat (limited to 'lib/Analysis/ScanfFormatString.cpp')
| -rw-r--r-- | lib/Analysis/ScanfFormatString.cpp | 193 | 
1 files changed, 92 insertions, 101 deletions
diff --git a/lib/Analysis/ScanfFormatString.cpp b/lib/Analysis/ScanfFormatString.cpp index 6bc4adb4f3c6..2942400621d1 100644 --- a/lib/Analysis/ScanfFormatString.cpp +++ b/lib/Analysis/ScanfFormatString.cpp @@ -15,12 +15,11 @@  #include "clang/Analysis/Analyses/FormatString.h"  #include "FormatStringParsing.h" -using clang::analyze_format_string::ArgTypeResult; +using clang::analyze_format_string::ArgType;  using clang::analyze_format_string::FormatStringHandler;  using clang::analyze_format_string::LengthModifier;  using clang::analyze_format_string::OptionalAmount;  using clang::analyze_format_string::ConversionSpecifier; -using clang::analyze_scanf::ScanfArgTypeResult;  using clang::analyze_scanf::ScanfConversionSpecifier;  using clang::analyze_scanf::ScanfSpecifier;  using clang::UpdateOnReturn; @@ -194,37 +193,42 @@ static ScanfSpecifierResult ParseScanfSpecifier(FormatStringHandler &H,    return ScanfSpecifierResult(Start, FS);  } -ScanfArgTypeResult ScanfSpecifier::getArgType(ASTContext &Ctx) const { +ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {    const ScanfConversionSpecifier &CS = getConversionSpecifier();    if (!CS.consumesDataArgument()) -    return ScanfArgTypeResult::Invalid(); +    return ArgType::Invalid();    switch(CS.getKind()) {      // Signed int.      case ConversionSpecifier::dArg:      case ConversionSpecifier::iArg:        switch (LM.getKind()) { -        case LengthModifier::None: return ArgTypeResult(Ctx.IntTy); +        case LengthModifier::None: +          return ArgType::PtrTo(Ctx.IntTy);          case LengthModifier::AsChar: -          return ArgTypeResult(ArgTypeResult::AnyCharTy); -        case LengthModifier::AsShort: return ArgTypeResult(Ctx.ShortTy); -        case LengthModifier::AsLong: return ArgTypeResult(Ctx.LongTy); +          return ArgType::PtrTo(ArgType::AnyCharTy); +        case LengthModifier::AsShort: +          return ArgType::PtrTo(Ctx.ShortTy); +        case LengthModifier::AsLong: +          return ArgType::PtrTo(Ctx.LongTy);          case LengthModifier::AsLongLong:          case LengthModifier::AsQuad: -          return ArgTypeResult(Ctx.LongLongTy); +          return ArgType::PtrTo(Ctx.LongLongTy);          case LengthModifier::AsIntMax: -          return ScanfArgTypeResult(Ctx.getIntMaxType(), "intmax_t *"); +          return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));          case LengthModifier::AsSizeT:            // FIXME: ssize_t. -          return ScanfArgTypeResult(); +          return ArgType();          case LengthModifier::AsPtrDiff: -          return ScanfArgTypeResult(Ctx.getPointerDiffType(), "ptrdiff_t *"); +          return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));          case LengthModifier::AsLongDouble:            // GNU extension. -          return ArgTypeResult(Ctx.LongLongTy); -        case LengthModifier::AsAllocate: return ScanfArgTypeResult::Invalid(); -        case LengthModifier::AsMAllocate: return ScanfArgTypeResult::Invalid(); +          return ArgType::PtrTo(Ctx.LongLongTy); +        case LengthModifier::AsAllocate: +          return ArgType::Invalid(); +        case LengthModifier::AsMAllocate: +          return ArgType::Invalid();        }      // Unsigned int. @@ -233,25 +237,31 @@ ScanfArgTypeResult ScanfSpecifier::getArgType(ASTContext &Ctx) const {      case ConversionSpecifier::xArg:      case ConversionSpecifier::XArg:        switch (LM.getKind()) { -        case LengthModifier::None: return ArgTypeResult(Ctx.UnsignedIntTy); -        case LengthModifier::AsChar: return ArgTypeResult(Ctx.UnsignedCharTy); -        case LengthModifier::AsShort: return ArgTypeResult(Ctx.UnsignedShortTy); -        case LengthModifier::AsLong: return ArgTypeResult(Ctx.UnsignedLongTy); +        case LengthModifier::None: +          return ArgType::PtrTo(Ctx.UnsignedIntTy); +        case LengthModifier::AsChar: +          return ArgType::PtrTo(Ctx.UnsignedCharTy); +        case LengthModifier::AsShort: +          return ArgType::PtrTo(Ctx.UnsignedShortTy); +        case LengthModifier::AsLong: +          return ArgType::PtrTo(Ctx.UnsignedLongTy);          case LengthModifier::AsLongLong:          case LengthModifier::AsQuad: -          return ArgTypeResult(Ctx.UnsignedLongLongTy); +          return ArgType::PtrTo(Ctx.UnsignedLongLongTy);          case LengthModifier::AsIntMax: -          return ScanfArgTypeResult(Ctx.getUIntMaxType(), "uintmax_t *"); +          return ArgType::PtrTo(ArgType(Ctx.getUIntMaxType(), "uintmax_t"));          case LengthModifier::AsSizeT: -          return ScanfArgTypeResult(Ctx.getSizeType(), "size_t *"); +          return ArgType::PtrTo(ArgType(Ctx.getSizeType(), "size_t"));          case LengthModifier::AsPtrDiff:            // FIXME: Unsigned version of ptrdiff_t? -          return ScanfArgTypeResult(); +          return ArgType();          case LengthModifier::AsLongDouble:            // GNU extension. -          return ArgTypeResult(Ctx.UnsignedLongLongTy); -        case LengthModifier::AsAllocate: return ScanfArgTypeResult::Invalid(); -        case LengthModifier::AsMAllocate: return ScanfArgTypeResult::Invalid(); +          return ArgType::PtrTo(Ctx.UnsignedLongLongTy); +        case LengthModifier::AsAllocate: +          return ArgType::Invalid(); +        case LengthModifier::AsMAllocate: +          return ArgType::Invalid();        }      // Float. @@ -264,12 +274,14 @@ ScanfArgTypeResult ScanfSpecifier::getArgType(ASTContext &Ctx) const {      case ConversionSpecifier::gArg:      case ConversionSpecifier::GArg:        switch (LM.getKind()) { -        case LengthModifier::None: return ArgTypeResult(Ctx.FloatTy); -        case LengthModifier::AsLong: return ArgTypeResult(Ctx.DoubleTy); +        case LengthModifier::None: +          return ArgType::PtrTo(Ctx.FloatTy); +        case LengthModifier::AsLong: +          return ArgType::PtrTo(Ctx.DoubleTy);          case LengthModifier::AsLongDouble: -          return ArgTypeResult(Ctx.LongDoubleTy); +          return ArgType::PtrTo(Ctx.LongDoubleTy);          default: -          return ScanfArgTypeResult::Invalid(); +          return ArgType::Invalid();        }      // Char, string and scanlist. @@ -277,37 +289,65 @@ ScanfArgTypeResult ScanfSpecifier::getArgType(ASTContext &Ctx) const {      case ConversionSpecifier::sArg:      case ConversionSpecifier::ScanListArg:        switch (LM.getKind()) { -        case LengthModifier::None: return ScanfArgTypeResult::CStrTy; +        case LengthModifier::None: +          return ArgType::PtrTo(ArgType::AnyCharTy);          case LengthModifier::AsLong: -          return ScanfArgTypeResult(ScanfArgTypeResult::WCStrTy, "wchar_t *"); +          return ArgType::PtrTo(ArgType(Ctx.getWCharType(), "wchar_t"));          case LengthModifier::AsAllocate:          case LengthModifier::AsMAllocate: -          return ScanfArgTypeResult(ArgTypeResult::CStrTy); +          return ArgType::PtrTo(ArgType::CStrTy);          default: -          return ScanfArgTypeResult::Invalid(); +          return ArgType::Invalid();        }      case ConversionSpecifier::CArg:      case ConversionSpecifier::SArg:        // FIXME: Mac OS X specific?        switch (LM.getKind()) {          case LengthModifier::None: -          return ScanfArgTypeResult(ScanfArgTypeResult::WCStrTy, "wchar_t *"); +          return ArgType::PtrTo(ArgType(Ctx.getWCharType(), "wchar_t"));          case LengthModifier::AsAllocate:          case LengthModifier::AsMAllocate: -          return ScanfArgTypeResult(ArgTypeResult::WCStrTy, "wchar_t **"); +          return ArgType::PtrTo(ArgType(ArgType::WCStrTy, "wchar_t *"));          default: -          return ScanfArgTypeResult::Invalid(); +          return ArgType::Invalid();        }      // Pointer.      case ConversionSpecifier::pArg: -      return ScanfArgTypeResult(ArgTypeResult(ArgTypeResult::CPointerTy)); +      return ArgType::PtrTo(ArgType::CPointerTy); + +    // Write-back. +    case ConversionSpecifier::nArg: +      switch (LM.getKind()) { +        case LengthModifier::None: +          return ArgType::PtrTo(Ctx.IntTy); +        case LengthModifier::AsChar: +          return ArgType::PtrTo(Ctx.SignedCharTy); +        case LengthModifier::AsShort: +          return ArgType::PtrTo(Ctx.ShortTy); +        case LengthModifier::AsLong: +          return ArgType::PtrTo(Ctx.LongTy); +        case LengthModifier::AsLongLong: +        case LengthModifier::AsQuad: +          return ArgType::PtrTo(Ctx.LongLongTy); +        case LengthModifier::AsIntMax: +          return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t")); +        case LengthModifier::AsSizeT: +          return ArgType(); // FIXME: ssize_t +        case LengthModifier::AsPtrDiff: +          return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t")); +        case LengthModifier::AsLongDouble: +          return ArgType(); // FIXME: Is this a known extension? +        case LengthModifier::AsAllocate: +        case LengthModifier::AsMAllocate: +          return ArgType::Invalid(); +        }      default:        break;    } -  return ScanfArgTypeResult(); +  return ArgType();  }  bool ScanfSpecifier::fixType(QualType QT, const LangOptions &LangOpt, @@ -315,7 +355,16 @@ bool ScanfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,    if (!QT->isPointerType())      return false; +  // %n is different from other conversion specifiers; don't try to fix it. +  if (CS.getKind() == ConversionSpecifier::nArg) +    return false; +    QualType PT = QT->getPointeeType(); + +  // If it's an enum, get its underlying type. +  if (const EnumType *ETy = QT->getAs<EnumType>()) +    QT = ETy->getDecl()->getIntegerType(); +      const BuiltinType *BT = PT->getAs<BuiltinType>();    if (!BT)      return false; @@ -377,25 +426,12 @@ bool ScanfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,    }    // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99. -  if (isa<TypedefType>(PT) && (LangOpt.C99 || LangOpt.CPlusPlus0x)) { -    const IdentifierInfo *Identifier = QT.getBaseTypeIdentifier(); -    if (Identifier->getName() == "size_t") { -      LM.setKind(LengthModifier::AsSizeT); -    } else if (Identifier->getName() == "ssize_t") { -      // Not C99, but common in Unix. -      LM.setKind(LengthModifier::AsSizeT); -    } else if (Identifier->getName() == "intmax_t") { -      LM.setKind(LengthModifier::AsIntMax); -    } else if (Identifier->getName() == "uintmax_t") { -      LM.setKind(LengthModifier::AsIntMax); -    } else if (Identifier->getName() == "ptrdiff_t") { -      LM.setKind(LengthModifier::AsPtrDiff); -    } -  } +  if (isa<TypedefType>(PT) && (LangOpt.C99 || LangOpt.CPlusPlus0x)) +    namedTypeToLengthModifier(PT, LM);    // If fixing the length modifier was enough, we are done. -  const analyze_scanf::ScanfArgTypeResult &ATR = getArgType(Ctx); -  if (hasValidLengthModifier() && ATR.isValid() && ATR.matchesType(Ctx, QT)) +  const analyze_scanf::ArgType &AT = getArgType(Ctx); +  if (hasValidLengthModifier() && AT.isValid() && AT.matchesType(Ctx, QT))      return true;    // Figure out the conversion specifier. @@ -452,48 +488,3 @@ bool clang::analyze_format_string::ParseScanfString(FormatStringHandler &H,    assert(I == E && "Format string not exhausted");    return false;  } - -bool ScanfArgTypeResult::matchesType(ASTContext& C, QualType argTy) const { -  switch (K) { -    case InvalidTy: -      llvm_unreachable("ArgTypeResult must be valid"); -    case UnknownTy: -      return true; -    case CStrTy: -      return ArgTypeResult(ArgTypeResult::CStrTy).matchesType(C, argTy); -    case WCStrTy: -      return ArgTypeResult(ArgTypeResult::WCStrTy).matchesType(C, argTy); -    case PtrToArgTypeResultTy: { -      const PointerType *PT = argTy->getAs<PointerType>(); -      if (!PT) -        return false; -      return A.matchesType(C, PT->getPointeeType()); -    } -  } - -  llvm_unreachable("Invalid ScanfArgTypeResult Kind!"); -} - -QualType ScanfArgTypeResult::getRepresentativeType(ASTContext &C) const { -  switch (K) { -    case InvalidTy: -      llvm_unreachable("No representative type for Invalid ArgTypeResult"); -    case UnknownTy: -      return QualType(); -    case CStrTy: -      return C.getPointerType(C.CharTy); -    case WCStrTy: -      return C.getPointerType(C.getWCharType()); -    case PtrToArgTypeResultTy: -      return C.getPointerType(A.getRepresentativeType(C)); -  } - -  llvm_unreachable("Invalid ScanfArgTypeResult Kind!"); -} - -std::string ScanfArgTypeResult::getRepresentativeTypeName(ASTContext& C) const { -  std::string S = getRepresentativeType(C).getAsString(); -  if (!Name) -    return std::string("'") + S + "'"; -  return std::string("'") + Name + "' (aka '" + S + "')"; -}  | 
