<div dir="ltr">The move of OSLog.h and FormatString.h to AST doesn't look obviously correct.<div>Do these really belong in this layer? I think this patch needs review from someone who knows AST/ better than myself... was there a review?</div><div><br></div><div>(If the do belong here: the namespaces and comments don't seem to have been updated)</div></div><br><div class="gmail_quote"><div dir="ltr">On Fri, Nov 2, 2018 at 2:16 PM Tim Northover via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: tnorthover<br>
Date: Fri Nov  2 06:14:11 2018<br>
New Revision: 345971<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=345971&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=345971&view=rev</a><br>
Log:<br>
Reapply Logging: make os_log buffer size an integer constant expression.<br>
<br>
The size of an os_log buffer is known at any stage of compilation, so making it<br>
a constant expression means that the common idiom of declaring a buffer for it<br>
won't result in a VLA. That allows the compiler to skip saving and restoring<br>
the stack pointer around such buffers.<br>
<br>
This also moves the OSLog and other FormatString helpers from<br>
libclangAnalysis to libclangAST to avoid a circular dependency.<br>
<br>
Added:<br>
    cfe/trunk/include/clang/AST/FormatString.h<br>
    cfe/trunk/include/clang/AST/OSLog.h<br>
    cfe/trunk/lib/AST/FormatString.cpp<br>
    cfe/trunk/lib/AST/FormatStringParsing.h<br>
    cfe/trunk/lib/AST/OSLog.cpp<br>
    cfe/trunk/lib/AST/PrintfFormatString.cpp<br>
    cfe/trunk/lib/AST/ScanfFormatString.cpp<br>
Removed:<br>
    cfe/trunk/include/clang/Analysis/Analyses/FormatString.h<br>
    cfe/trunk/include/clang/Analysis/Analyses/OSLog.h<br>
    cfe/trunk/lib/Analysis/FormatString.cpp<br>
    cfe/trunk/lib/Analysis/FormatStringParsing.h<br>
    cfe/trunk/lib/Analysis/OSLog.cpp<br>
    cfe/trunk/lib/Analysis/PrintfFormatString.cpp<br>
    cfe/trunk/lib/Analysis/ScanfFormatString.cpp<br>
Modified:<br>
    cfe/trunk/lib/AST/CMakeLists.txt<br>
    cfe/trunk/lib/AST/ExprConstant.cpp<br>
    cfe/trunk/lib/Analysis/CMakeLists.txt<br>
    cfe/trunk/lib/CodeGen/CGBuiltin.cpp<br>
    cfe/trunk/lib/Sema/SemaChecking.cpp<br>
    cfe/trunk/test/CodeGen/builtins.c<br>
<br>
Added: cfe/trunk/include/clang/AST/FormatString.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/FormatString.h?rev=345971&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/FormatString.h?rev=345971&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/FormatString.h (added)<br>
+++ cfe/trunk/include/clang/AST/FormatString.h Fri Nov  2 06:14:11 2018<br>
@@ -0,0 +1,719 @@<br>
+//= FormatString.h - Analysis of printf/fprintf format strings --*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// This file defines APIs for analyzing the format strings of printf, fscanf,<br>
+// and friends.<br>
+//<br>
+// The structure of format strings for fprintf are described in C99 7.19.6.1.<br>
+//<br>
+// The structure of format strings for fscanf are described in C99 7.19.6.2.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_FORMATSTRING_H<br>
+#define LLVM_CLANG_ANALYSIS_ANALYSES_FORMATSTRING_H<br>
+<br>
+#include "clang/AST/CanonicalType.h"<br>
+<br>
+namespace clang {<br>
+<br>
+class TargetInfo;<br>
+<br>
+//===----------------------------------------------------------------------===//<br>
+/// Common components of both fprintf and fscanf format strings.<br>
+namespace analyze_format_string {<br>
+<br>
+/// Class representing optional flags with location and representation<br>
+/// information.<br>
+class OptionalFlag {<br>
+public:<br>
+  OptionalFlag(const char *Representation)<br>
+      : representation(Representation), flag(false) {}<br>
+  bool isSet() const { return flag; }<br>
+  void set() { flag = true; }<br>
+  void clear() { flag = false; }<br>
+  void setPosition(const char *position) {<br>
+    assert(position);<br>
+    flag = true;<br>
+    this->position = position;<br>
+  }<br>
+  const char *getPosition() const {<br>
+    assert(position);<br>
+    return position;<br>
+  }<br>
+  const char *toString() const { return representation; }<br>
+<br>
+  // Overloaded operators for bool like qualities<br>
+  explicit operator bool() const { return flag; }<br>
+  OptionalFlag& operator=(const bool &rhs) {<br>
+    flag = rhs;<br>
+    return *this;  // Return a reference to myself.<br>
+  }<br>
+private:<br>
+  const char *representation;<br>
+  const char *position;<br>
+  bool flag;<br>
+};<br>
+<br>
+/// Represents the length modifier in a format string in scanf/printf.<br>
+class LengthModifier {<br>
+public:<br>
+  enum Kind {<br>
+    None,<br>
+    AsChar,       // 'hh'<br>
+    AsShort,      // 'h'<br>
+    AsLong,       // 'l'<br>
+    AsLongLong,   // 'll'<br>
+    AsQuad,       // 'q' (BSD, deprecated, for 64-bit integer types)<br>
+    AsIntMax,     // 'j'<br>
+    AsSizeT,      // 'z'<br>
+    AsPtrDiff,    // 't'<br>
+    AsInt32,      // 'I32' (MSVCRT, like __int32)<br>
+    AsInt3264,    // 'I'   (MSVCRT, like __int3264 from MIDL)<br>
+    AsInt64,      // 'I64' (MSVCRT, like __int64)<br>
+    AsLongDouble, // 'L'<br>
+    AsAllocate,   // for '%as', GNU extension to C90 scanf<br>
+    AsMAllocate,  // for '%ms', GNU extension to scanf<br>
+    AsWide,       // 'w' (MSVCRT, like l but only for c, C, s, S, or Z<br>
+    AsWideChar = AsLong // for '%ls', only makes sense for printf<br>
+  };<br>
+<br>
+  LengthModifier()<br>
+    : Position(nullptr), kind(None) {}<br>
+  LengthModifier(const char *pos, Kind k)<br>
+    : Position(pos), kind(k) {}<br>
+<br>
+  const char *getStart() const {<br>
+    return Position;<br>
+  }<br>
+<br>
+  unsigned getLength() const {<br>
+    switch (kind) {<br>
+      default:<br>
+        return 1;<br>
+      case AsLongLong:<br>
+      case AsChar:<br>
+        return 2;<br>
+      case AsInt32:<br>
+      case AsInt64:<br>
+        return 3;<br>
+      case None:<br>
+        return 0;<br>
+    }<br>
+  }<br>
+<br>
+  Kind getKind() const { return kind; }<br>
+  void setKind(Kind k) { kind = k; }<br>
+<br>
+  const char *toString() const;<br>
+<br>
+private:<br>
+  const char *Position;<br>
+  Kind kind;<br>
+};<br>
+<br>
+class ConversionSpecifier {<br>
+public:<br>
+  enum Kind {<br>
+    InvalidSpecifier = 0,<br>
+    // C99 conversion specifiers.<br>
+    cArg,<br>
+    dArg,<br>
+    DArg, // Apple extension<br>
+    iArg,<br>
+    IntArgBeg = dArg,<br>
+    IntArgEnd = iArg,<br>
+<br>
+    oArg,<br>
+    OArg, // Apple extension<br>
+    uArg,<br>
+    UArg, // Apple extension<br>
+    xArg,<br>
+    XArg,<br>
+    UIntArgBeg = oArg,<br>
+    UIntArgEnd = XArg,<br>
+<br>
+    fArg,<br>
+    FArg,<br>
+    eArg,<br>
+    EArg,<br>
+    gArg,<br>
+    GArg,<br>
+    aArg,<br>
+    AArg,<br>
+    DoubleArgBeg = fArg,<br>
+    DoubleArgEnd = AArg,<br>
+<br>
+    sArg,<br>
+    pArg,<br>
+    nArg,<br>
+    PercentArg,<br>
+    CArg,<br>
+    SArg,<br>
+<br>
+    // Apple extension: P specifies to os_log that the data being pointed to is<br>
+    // to be copied by os_log. The precision indicates the number of bytes to<br>
+    // copy.<br>
+    PArg,<br>
+<br>
+    // ** Printf-specific **<br>
+<br>
+    ZArg, // MS extension<br>
+<br>
+    // Objective-C specific specifiers.<br>
+    ObjCObjArg, // '@'<br>
+    ObjCBeg = ObjCObjArg,<br>
+    ObjCEnd = ObjCObjArg,<br>
+<br>
+    // FreeBSD kernel specific specifiers.<br>
+    FreeBSDbArg,<br>
+    FreeBSDDArg,<br>
+    FreeBSDrArg,<br>
+    FreeBSDyArg,<br>
+<br>
+    // GlibC specific specifiers.<br>
+    PrintErrno, // 'm'<br>
+<br>
+    PrintfConvBeg = ObjCObjArg,<br>
+    PrintfConvEnd = PrintErrno,<br>
+<br>
+    // ** Scanf-specific **<br>
+    ScanListArg, // '['<br>
+    ScanfConvBeg = ScanListArg,<br>
+    ScanfConvEnd = ScanListArg<br>
+  };<br>
+<br>
+  ConversionSpecifier(bool isPrintf = true)<br>
+    : IsPrintf(isPrintf), Position(nullptr), EndScanList(nullptr),<br>
+      kind(InvalidSpecifier) {}<br>
+<br>
+  ConversionSpecifier(bool isPrintf, const char *pos, Kind k)<br>
+    : IsPrintf(isPrintf), Position(pos), EndScanList(nullptr), kind(k) {}<br>
+<br>
+  const char *getStart() const {<br>
+    return Position;<br>
+  }<br>
+<br>
+  StringRef getCharacters() const {<br>
+    return StringRef(getStart(), getLength());<br>
+  }<br>
+<br>
+  bool consumesDataArgument() const {<br>
+    switch (kind) {<br>
+      case PrintErrno:<br>
+        assert(IsPrintf);<br>
+        return false;<br>
+      case PercentArg:<br>
+        return false;<br>
+      case InvalidSpecifier:<br>
+        return false;<br>
+      default:<br>
+        return true;<br>
+    }<br>
+  }<br>
+<br>
+  Kind getKind() const { return kind; }<br>
+  void setKind(Kind k) { kind = k; }<br>
+  unsigned getLength() const {<br>
+    return EndScanList ? EndScanList - Position : 1;<br>
+  }<br>
+  void setEndScanList(const char *pos) { EndScanList = pos; }<br>
+<br>
+  bool isIntArg() const { return (kind >= IntArgBeg && kind <= IntArgEnd) ||<br>
+    kind == FreeBSDrArg || kind == FreeBSDyArg; }<br>
+  bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; }<br>
+  bool isAnyIntArg() const { return kind >= IntArgBeg && kind <= UIntArgEnd; }<br>
+  bool isDoubleArg() const {<br>
+    return kind >= DoubleArgBeg && kind <= DoubleArgEnd;<br>
+  }<br>
+<br>
+  const char *toString() const;<br>
+<br>
+  bool isPrintfKind() const { return IsPrintf; }<br>
+<br>
+  Optional<ConversionSpecifier> getStandardSpecifier() const;<br>
+<br>
+protected:<br>
+  bool IsPrintf;<br>
+  const char *Position;<br>
+  const char *EndScanList;<br>
+  Kind kind;<br>
+};<br>
+<br>
+class ArgType {<br>
+public:<br>
+  enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy,<br>
+              AnyCharTy, CStrTy, WCStrTy, WIntTy };<br>
+<br>
+  enum MatchKind { NoMatch = 0, Match = 1, NoMatchPedantic };<br>
+<br>
+private:<br>
+  const Kind K;<br>
+  QualType T;<br>
+  const char *Name = nullptr;<br>
+  bool Ptr = false;<br>
+<br>
+  /// The TypeKind identifies certain well-known types like size_t and<br>
+  /// ptrdiff_t.<br>
+  enum class TypeKind { DontCare, SizeT, PtrdiffT };<br>
+  TypeKind TK = TypeKind::DontCare;<br>
+<br>
+public:<br>
+  ArgType(Kind K = UnknownTy, const char *N = nullptr) : K(K), Name(N) {}<br>
+  ArgType(QualType T, const char *N = nullptr) : K(SpecificTy), T(T), Name(N) {}<br>
+  ArgType(CanQualType T) : K(SpecificTy), T(T) {}<br>
+<br>
+  static ArgType Invalid() { return ArgType(InvalidTy); }<br>
+  bool isValid() const { return K != InvalidTy; }<br>
+<br>
+  bool isSizeT() const { return TK == TypeKind::SizeT; }<br>
+<br>
+  bool isPtrdiffT() const { return TK == TypeKind::PtrdiffT; }<br>
+<br>
+  /// Create an ArgType which corresponds to the type pointer to A.<br>
+  static ArgType PtrTo(const ArgType& A) {<br>
+    assert(A.K >= InvalidTy && "ArgType cannot be pointer to invalid/unknown");<br>
+    ArgType Res = A;<br>
+    Res.Ptr = true;<br>
+    return Res;<br>
+  }<br>
+<br>
+  /// Create an ArgType which corresponds to the size_t/ssize_t type.<br>
+  static ArgType makeSizeT(const ArgType &A) {<br>
+    ArgType Res = A;<br>
+    Res.TK = TypeKind::SizeT;<br>
+    return Res;<br>
+  }<br>
+<br>
+  /// Create an ArgType which corresponds to the ptrdiff_t/unsigned ptrdiff_t<br>
+  /// type.<br>
+  static ArgType makePtrdiffT(const ArgType &A) {<br>
+    ArgType Res = A;<br>
+    Res.TK = TypeKind::PtrdiffT;<br>
+    return Res;<br>
+  }<br>
+<br>
+  MatchKind matchesType(ASTContext &C, QualType argTy) const;<br>
+<br>
+  QualType getRepresentativeType(ASTContext &C) const;<br>
+<br>
+  std::string getRepresentativeTypeName(ASTContext &C) const;<br>
+};<br>
+<br>
+class OptionalAmount {<br>
+public:<br>
+  enum HowSpecified { NotSpecified, Constant, Arg, Invalid };<br>
+<br>
+  OptionalAmount(HowSpecified howSpecified,<br>
+                 unsigned amount,<br>
+                 const char *amountStart,<br>
+                 unsigned amountLength,<br>
+                 bool usesPositionalArg)<br>
+  : start(amountStart), length(amountLength), hs(howSpecified), amt(amount),<br>
+  UsesPositionalArg(usesPositionalArg), UsesDotPrefix(0) {}<br>
+<br>
+  OptionalAmount(bool valid = true)<br>
+  : start(nullptr),length(0), hs(valid ? NotSpecified : Invalid), amt(0),<br>
+  UsesPositionalArg(0), UsesDotPrefix(0) {}<br>
+<br>
+  bool isInvalid() const {<br>
+    return hs == Invalid;<br>
+  }<br>
+<br>
+  HowSpecified getHowSpecified() const { return hs; }<br>
+  void setHowSpecified(HowSpecified h) { hs = h; }<br>
+<br>
+  bool hasDataArgument() const { return hs == Arg; }<br>
+<br>
+  unsigned getArgIndex() const {<br>
+    assert(hasDataArgument());<br>
+    return amt;<br>
+  }<br>
+<br>
+  unsigned getConstantAmount() const {<br>
+    assert(hs == Constant);<br>
+    return amt;<br>
+  }<br>
+<br>
+  const char *getStart() const {<br>
+      // We include the . character if it is given.<br>
+    return start - UsesDotPrefix;<br>
+  }<br>
+<br>
+  unsigned getConstantLength() const {<br>
+    assert(hs == Constant);<br>
+    return length + UsesDotPrefix;<br>
+  }<br>
+<br>
+  ArgType getArgType(ASTContext &Ctx) const;<br>
+<br>
+  void toString(raw_ostream &os) const;<br>
+<br>
+  bool usesPositionalArg() const { return (bool) UsesPositionalArg; }<br>
+  unsigned getPositionalArgIndex() const {<br>
+    assert(hasDataArgument());<br>
+    return amt + 1;<br>
+  }<br>
+<br>
+  bool usesDotPrefix() const { return UsesDotPrefix; }<br>
+  void setUsesDotPrefix() { UsesDotPrefix = true; }<br>
+<br>
+private:<br>
+  const char *start;<br>
+  unsigned length;<br>
+  HowSpecified hs;<br>
+  unsigned amt;<br>
+  bool UsesPositionalArg : 1;<br>
+  bool UsesDotPrefix;<br>
+};<br>
+<br>
+<br>
+class FormatSpecifier {<br>
+protected:<br>
+  LengthModifier LM;<br>
+  OptionalAmount FieldWidth;<br>
+  ConversionSpecifier CS;<br>
+  /// Positional arguments, an IEEE extension:<br>
+  ///  IEEE Std 1003.1, 2004 Edition<br>
+  ///  <a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html" rel="noreferrer" target="_blank">http://www.opengroup.org/onlinepubs/009695399/functions/printf.html</a><br>
+  bool UsesPositionalArg;<br>
+  unsigned argIndex;<br>
+public:<br>
+  FormatSpecifier(bool isPrintf)<br>
+    : CS(isPrintf), UsesPositionalArg(false), argIndex(0) {}<br>
+<br>
+  void setLengthModifier(LengthModifier lm) {<br>
+    LM = lm;<br>
+  }<br>
+<br>
+  void setUsesPositionalArg() { UsesPositionalArg = true; }<br>
+<br>
+  void setArgIndex(unsigned i) {<br>
+    argIndex = i;<br>
+  }<br>
+<br>
+  unsigned getArgIndex() const {<br>
+    return argIndex;<br>
+  }<br>
+<br>
+  unsigned getPositionalArgIndex() const {<br>
+    return argIndex + 1;<br>
+  }<br>
+<br>
+  const LengthModifier &getLengthModifier() const {<br>
+    return LM;<br>
+  }<br>
+<br>
+  const OptionalAmount &getFieldWidth() const {<br>
+    return FieldWidth;<br>
+  }<br>
+<br>
+  void setFieldWidth(const OptionalAmount &Amt) {<br>
+    FieldWidth = Amt;<br>
+  }<br>
+<br>
+  bool usesPositionalArg() const { return UsesPositionalArg; }<br>
+<br>
+  bool hasValidLengthModifier(const TargetInfo &Target) const;<br>
+<br>
+  bool hasStandardLengthModifier() const;<br>
+<br>
+  Optional<LengthModifier> getCorrectedLengthModifier() const;<br>
+<br>
+  bool hasStandardConversionSpecifier(const LangOptions &LangOpt) const;<br>
+<br>
+  bool hasStandardLengthConversionCombination() const;<br>
+<br>
+  /// For a TypedefType QT, if it is a named integer type such as size_t,<br>
+  /// assign the appropriate value to LM and return true.<br>
+  static bool namedTypeToLengthModifier(QualType QT, LengthModifier &LM);<br>
+};<br>
+<br>
+} // end analyze_format_string namespace<br>
+<br>
+//===----------------------------------------------------------------------===//<br>
+/// Pieces specific to fprintf format strings.<br>
+<br>
+namespace analyze_printf {<br>
+<br>
+class PrintfConversionSpecifier :<br>
+  public analyze_format_string::ConversionSpecifier  {<br>
+public:<br>
+  PrintfConversionSpecifier()<br>
+    : ConversionSpecifier(true, nullptr, InvalidSpecifier) {}<br>
+<br>
+  PrintfConversionSpecifier(const char *pos, Kind k)<br>
+    : ConversionSpecifier(true, pos, k) {}<br>
+<br>
+  bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; }<br>
+  bool isDoubleArg() const { return kind >= DoubleArgBeg &&<br>
+                                    kind <= DoubleArgEnd; }<br>
+<br>
+  static bool classof(const analyze_format_string::ConversionSpecifier *CS) {<br>
+    return CS->isPrintfKind();<br>
+  }<br>
+};<br>
+<br>
+using analyze_format_string::ArgType;<br>
+using analyze_format_string::LengthModifier;<br>
+using analyze_format_string::OptionalAmount;<br>
+using analyze_format_string::OptionalFlag;<br>
+<br>
+class PrintfSpecifier : public analyze_format_string::FormatSpecifier {<br>
+  OptionalFlag HasThousandsGrouping; // ''', POSIX extension.<br>
+  OptionalFlag IsLeftJustified; // '-'<br>
+  OptionalFlag HasPlusPrefix; // '+'<br>
+  OptionalFlag HasSpacePrefix; // ' '<br>
+  OptionalFlag HasAlternativeForm; // '#'<br>
+  OptionalFlag HasLeadingZeroes; // '0'<br>
+  OptionalFlag HasObjCTechnicalTerm; // '[tt]'<br>
+  OptionalFlag IsPrivate;            // '{private}'<br>
+  OptionalFlag IsPublic;             // '{public}'<br>
+  OptionalAmount Precision;<br>
+public:<br>
+  PrintfSpecifier()<br>
+      : FormatSpecifier(/* isPrintf = */ true), HasThousandsGrouping("'"),<br>
+        IsLeftJustified("-"), HasPlusPrefix("+"), HasSpacePrefix(" "),<br>
+        HasAlternativeForm("#"), HasLeadingZeroes("0"),<br>
+        HasObjCTechnicalTerm("tt"), IsPrivate("private"), IsPublic("public") {}<br>
+<br>
+  static PrintfSpecifier Parse(const char *beg, const char *end);<br>
+<br>
+    // Methods for incrementally constructing the PrintfSpecifier.<br>
+  void setConversionSpecifier(const PrintfConversionSpecifier &cs) {<br>
+    CS = cs;<br>
+  }<br>
+  void setHasThousandsGrouping(const char *position) {<br>
+    HasThousandsGrouping.setPosition(position);<br>
+  }<br>
+  void setIsLeftJustified(const char *position) {<br>
+    IsLeftJustified.setPosition(position);<br>
+  }<br>
+  void setHasPlusPrefix(const char *position) {<br>
+    HasPlusPrefix.setPosition(position);<br>
+  }<br>
+  void setHasSpacePrefix(const char *position) {<br>
+    HasSpacePrefix.setPosition(position);<br>
+  }<br>
+  void setHasAlternativeForm(const char *position) {<br>
+    HasAlternativeForm.setPosition(position);<br>
+  }<br>
+  void setHasLeadingZeros(const char *position) {<br>
+    HasLeadingZeroes.setPosition(position);<br>
+  }<br>
+  void setHasObjCTechnicalTerm(const char *position) {<br>
+    HasObjCTechnicalTerm.setPosition(position);<br>
+  }<br>
+  void setIsPrivate(const char *position) { IsPrivate.setPosition(position); }<br>
+  void setIsPublic(const char *position) { IsPublic.setPosition(position); }<br>
+  void setUsesPositionalArg() { UsesPositionalArg = true; }<br>
+<br>
+    // Methods for querying the format specifier.<br>
+<br>
+  const PrintfConversionSpecifier &getConversionSpecifier() const {<br>
+    return cast<PrintfConversionSpecifier>(CS);<br>
+  }<br>
+<br>
+  void setPrecision(const OptionalAmount &Amt) {<br>
+    Precision = Amt;<br>
+    Precision.setUsesDotPrefix();<br>
+  }<br>
+<br>
+  const OptionalAmount &getPrecision() const {<br>
+    return Precision;<br>
+  }<br>
+<br>
+  bool consumesDataArgument() const {<br>
+    return getConversionSpecifier().consumesDataArgument();<br>
+  }<br>
+<br>
+  /// Returns the builtin type that a data argument<br>
+  /// paired with this format specifier should have.  This method<br>
+  /// will return null if the format specifier does not have<br>
+  /// a matching data argument or the matching argument matches<br>
+  /// more than one type.<br>
+  ArgType getArgType(ASTContext &Ctx, bool IsObjCLiteral) const;<br>
+<br>
+  const OptionalFlag &hasThousandsGrouping() const {<br>
+      return HasThousandsGrouping;<br>
+  }<br>
+  const OptionalFlag &isLeftJustified() const { return IsLeftJustified; }<br>
+  const OptionalFlag &hasPlusPrefix() const { return HasPlusPrefix; }<br>
+  const OptionalFlag &hasAlternativeForm() const { return HasAlternativeForm; }<br>
+  const OptionalFlag &hasLeadingZeros() const { return HasLeadingZeroes; }<br>
+  const OptionalFlag &hasSpacePrefix() const { return HasSpacePrefix; }<br>
+  const OptionalFlag &hasObjCTechnicalTerm() const { return HasObjCTechnicalTerm; }<br>
+  const OptionalFlag &isPrivate() const { return IsPrivate; }<br>
+  const OptionalFlag &isPublic() const { return IsPublic; }<br>
+  bool usesPositionalArg() const { return UsesPositionalArg; }<br>
+<br>
+  /// Changes the specifier and length according to a QualType, retaining any<br>
+  /// flags or options. Returns true on success, or false when a conversion<br>
+  /// was not successful.<br>
+  bool fixType(QualType QT, const LangOptions &LangOpt, ASTContext &Ctx,<br>
+               bool IsObjCLiteral);<br>
+<br>
+  void toString(raw_ostream &os) const;<br>
+<br>
+  // Validation methods - to check if any element results in undefined behavior<br>
+  bool hasValidPlusPrefix() const;<br>
+  bool hasValidAlternativeForm() const;<br>
+  bool hasValidLeadingZeros() const;<br>
+  bool hasValidSpacePrefix() const;<br>
+  bool hasValidLeftJustified() const;<br>
+  bool hasValidThousandsGroupingPrefix() const;<br>
+<br>
+  bool hasValidPrecision() const;<br>
+  bool hasValidFieldWidth() const;<br>
+};<br>
+}  // end analyze_printf namespace<br>
+<br>
+//===----------------------------------------------------------------------===//<br>
+/// Pieces specific to fscanf format strings.<br>
+<br>
+namespace analyze_scanf {<br>
+<br>
+class ScanfConversionSpecifier :<br>
+    public analyze_format_string::ConversionSpecifier  {<br>
+public:<br>
+  ScanfConversionSpecifier()<br>
+    : ConversionSpecifier(false, nullptr, InvalidSpecifier) {}<br>
+<br>
+  ScanfConversionSpecifier(const char *pos, Kind k)<br>
+    : ConversionSpecifier(false, pos, k) {}<br>
+<br>
+  static bool classof(const analyze_format_string::ConversionSpecifier *CS) {<br>
+    return !CS->isPrintfKind();<br>
+  }<br>
+};<br>
+<br>
+using analyze_format_string::ArgType;<br>
+using analyze_format_string::LengthModifier;<br>
+using analyze_format_string::OptionalAmount;<br>
+using analyze_format_string::OptionalFlag;<br>
+<br>
+class ScanfSpecifier : public analyze_format_string::FormatSpecifier {<br>
+  OptionalFlag SuppressAssignment; // '*'<br>
+public:<br>
+  ScanfSpecifier() :<br>
+    FormatSpecifier(/* isPrintf = */ false),<br>
+    SuppressAssignment("*") {}<br>
+<br>
+  void setSuppressAssignment(const char *position) {<br>
+    SuppressAssignment.setPosition(position);<br>
+  }<br>
+<br>
+  const OptionalFlag &getSuppressAssignment() const {<br>
+    return SuppressAssignment;<br>
+  }<br>
+<br>
+  void setConversionSpecifier(const ScanfConversionSpecifier &cs) {<br>
+    CS = cs;<br>
+  }<br>
+<br>
+  const ScanfConversionSpecifier &getConversionSpecifier() const {<br>
+    return cast<ScanfConversionSpecifier>(CS);<br>
+  }<br>
+<br>
+  bool consumesDataArgument() const {<br>
+    return CS.consumesDataArgument() && !SuppressAssignment;<br>
+  }<br>
+<br>
+  ArgType getArgType(ASTContext &Ctx) const;<br>
+<br>
+  bool fixType(QualType QT, QualType RawQT, const LangOptions &LangOpt,<br>
+               ASTContext &Ctx);<br>
+<br>
+  void toString(raw_ostream &os) const;<br>
+<br>
+  static ScanfSpecifier Parse(const char *beg, const char *end);<br>
+};<br>
+<br>
+} // end analyze_scanf namespace<br>
+<br>
+//===----------------------------------------------------------------------===//<br>
+// Parsing and processing of format strings (both fprintf and fscanf).<br>
+<br>
+namespace analyze_format_string {<br>
+<br>
+enum PositionContext { FieldWidthPos = 0, PrecisionPos = 1 };<br>
+<br>
+class FormatStringHandler {<br>
+public:<br>
+  FormatStringHandler() {}<br>
+  virtual ~FormatStringHandler();<br>
+<br>
+  virtual void HandleNullChar(const char *nullCharacter) {}<br>
+<br>
+  virtual void HandlePosition(const char *startPos, unsigned posLen) {}<br>
+<br>
+  virtual void HandleInvalidPosition(const char *startPos, unsigned posLen,<br>
+                                     PositionContext p) {}<br>
+<br>
+  virtual void HandleZeroPosition(const char *startPos, unsigned posLen) {}<br>
+<br>
+  virtual void HandleIncompleteSpecifier(const char *startSpecifier,<br>
+                                         unsigned specifierLen) {}<br>
+<br>
+  virtual void HandleEmptyObjCModifierFlag(const char *startFlags,<br>
+                                           unsigned flagsLen) {}<br>
+<br>
+  virtual void HandleInvalidObjCModifierFlag(const char *startFlag,<br>
+                                             unsigned flagLen) {}<br>
+<br>
+  virtual void HandleObjCFlagsWithNonObjCConversion(const char *flagsStart,<br>
+                                            const char *flagsEnd,<br>
+                                            const char *conversionPosition) {}<br>
+  // Printf-specific handlers.<br>
+<br>
+  virtual bool HandleInvalidPrintfConversionSpecifier(<br>
+                                      const analyze_printf::PrintfSpecifier &FS,<br>
+                                      const char *startSpecifier,<br>
+                                      unsigned specifierLen) {<br>
+    return true;<br>
+  }<br>
+<br>
+  virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,<br>
+                                     const char *startSpecifier,<br>
+                                     unsigned specifierLen) {<br>
+    return true;<br>
+  }<br>
+<br>
+    // Scanf-specific handlers.<br>
+<br>
+  virtual bool HandleInvalidScanfConversionSpecifier(<br>
+                                        const analyze_scanf::ScanfSpecifier &FS,<br>
+                                        const char *startSpecifier,<br>
+                                        unsigned specifierLen) {<br>
+    return true;<br>
+  }<br>
+<br>
+  virtual bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,<br>
+                                    const char *startSpecifier,<br>
+                                    unsigned specifierLen) {<br>
+    return true;<br>
+  }<br>
+<br>
+  virtual void HandleIncompleteScanList(const char *start, const char *end) {}<br>
+};<br>
+<br>
+bool ParsePrintfString(FormatStringHandler &H,<br>
+                       const char *beg, const char *end, const LangOptions &LO,<br>
+                       const TargetInfo &Target, bool isFreeBSDKPrintf);<br>
+<br>
+bool ParseFormatStringHasSArg(const char *beg, const char *end,<br>
+                              const LangOptions &LO, const TargetInfo &Target);<br>
+<br>
+bool ParseScanfString(FormatStringHandler &H,<br>
+                      const char *beg, const char *end, const LangOptions &LO,<br>
+                      const TargetInfo &Target);<br>
+<br>
+} // end analyze_format_string namespace<br>
+} // end clang namespace<br>
+#endif<br>
<br>
Added: cfe/trunk/include/clang/AST/OSLog.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/OSLog.h?rev=345971&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/OSLog.h?rev=345971&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/OSLog.h (added)<br>
+++ cfe/trunk/include/clang/AST/OSLog.h Fri Nov  2 06:14:11 2018<br>
@@ -0,0 +1,155 @@<br>
+//= OSLog.h - Analysis of calls to os_log builtins --*- C++ -*-===============//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// This file defines APIs for determining the layout of the data buffer for<br>
+// os_log() and os_trace().<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_OSLOG_H<br>
+#define LLVM_CLANG_ANALYSIS_ANALYSES_OSLOG_H<br>
+<br>
+#include "clang/AST/ASTContext.h"<br>
+#include "clang/AST/Expr.h"<br>
+<br>
+namespace clang {<br>
+namespace analyze_os_log {<br>
+<br>
+/// An OSLogBufferItem represents a single item in the data written by a call<br>
+/// to os_log() or os_trace().<br>
+class OSLogBufferItem {<br>
+public:<br>
+  enum Kind {<br>
+    // The item is a scalar (int, float, raw pointer, etc.). No further copying<br>
+    // is required. This is the only kind allowed by os_trace().<br>
+    ScalarKind = 0,<br>
+<br>
+    // The item is a count, which describes the length of the following item to<br>
+    // be copied. A count may only be followed by an item of kind StringKind,<br>
+    // WideStringKind, or PointerKind.<br>
+    CountKind,<br>
+<br>
+    // The item is a pointer to a C string. If preceded by a count 'n',<br>
+    // os_log() will copy at most 'n' bytes from the pointer.<br>
+    StringKind,<br>
+<br>
+    // The item is a pointer to a block of raw data. This item must be preceded<br>
+    // by a count 'n'. os_log() will copy exactly 'n' bytes from the pointer.<br>
+    PointerKind,<br>
+<br>
+    // The item is a pointer to an Objective-C object. os_log() may retain the<br>
+    // object for later processing.<br>
+    ObjCObjKind,<br>
+<br>
+    // The item is a pointer to wide-char string.<br>
+    WideStringKind,<br>
+<br>
+    // The item is corresponding to the '%m' format specifier, no value is<br>
+    // populated in the buffer and the runtime is loading the errno value.<br>
+    ErrnoKind<br>
+  };<br>
+<br>
+  enum {<br>
+    // The item is marked "private" in the format string.<br>
+    IsPrivate = 0x1,<br>
+<br>
+    // The item is marked "public" in the format string.<br>
+    IsPublic = 0x2<br>
+  };<br>
+<br>
+private:<br>
+  Kind TheKind = ScalarKind;<br>
+  const Expr *TheExpr = nullptr;<br>
+  CharUnits ConstValue;<br>
+  CharUnits Size; // size of the data, not including the header bytes<br>
+  unsigned Flags = 0;<br>
+<br>
+public:<br>
+  OSLogBufferItem(Kind kind, const Expr *expr, CharUnits size, unsigned flags)<br>
+      : TheKind(kind), TheExpr(expr), Size(size), Flags(flags) {}<br>
+<br>
+  OSLogBufferItem(ASTContext &Ctx, CharUnits value, unsigned flags)<br>
+      : TheKind(CountKind), ConstValue(value),<br>
+        Size(Ctx.getTypeSizeInChars(Ctx.IntTy)), Flags(flags) {}<br>
+<br>
+  unsigned char getDescriptorByte() const {<br>
+    unsigned char result = 0;<br>
+    if (getIsPrivate())<br>
+      result |= IsPrivate;<br>
+    if (getIsPublic())<br>
+      result |= IsPublic;<br>
+    result |= ((unsigned)getKind()) << 4;<br>
+    return result;<br>
+  }<br>
+<br>
+  unsigned char getSizeByte() const { return size().getQuantity(); }<br>
+<br>
+  Kind getKind() const { return TheKind; }<br>
+  bool getIsPrivate() const { return (Flags & IsPrivate) != 0; }<br>
+  bool getIsPublic() const { return (Flags & IsPublic) != 0; }<br>
+<br>
+  const Expr *getExpr() const { return TheExpr; }<br>
+  CharUnits getConstValue() const { return ConstValue; }<br>
+  CharUnits size() const { return Size; }<br>
+};<br>
+<br>
+class OSLogBufferLayout {<br>
+public:<br>
+  SmallVector<OSLogBufferItem, 4> Items;<br>
+<br>
+  enum Flags { HasPrivateItems = 1, HasNonScalarItems = 1 << 1 };<br>
+<br>
+  CharUnits size() const {<br>
+    CharUnits result;<br>
+    result += CharUnits::fromQuantity(2); // summary byte, num-args byte<br>
+    for (auto &item : Items) {<br>
+      // descriptor byte, size byte<br>
+      result += item.size() + CharUnits::fromQuantity(2);<br>
+    }<br>
+    return result;<br>
+  }<br>
+<br>
+  bool hasPrivateItems() const {<br>
+    return llvm::any_of(<br>
+        Items, [](const OSLogBufferItem &Item) { return Item.getIsPrivate(); });<br>
+  }<br>
+<br>
+  bool hasPublicItems() const {<br>
+    return llvm::any_of(<br>
+        Items, [](const OSLogBufferItem &Item) { return Item.getIsPublic(); });<br>
+  }<br>
+<br>
+  bool hasNonScalar() const {<br>
+    return llvm::any_of(Items, [](const OSLogBufferItem &Item) {<br>
+      return Item.getKind() != OSLogBufferItem::ScalarKind;<br>
+    });<br>
+  }<br>
+<br>
+  unsigned char getSummaryByte() const {<br>
+    unsigned char result = 0;<br>
+    if (hasPrivateItems())<br>
+      result |= HasPrivateItems;<br>
+    if (hasNonScalar())<br>
+      result |= HasNonScalarItems;<br>
+    return result;<br>
+  }<br>
+<br>
+  unsigned char getNumArgsByte() const { return Items.size(); }<br>
+};<br>
+<br>
+// Given a call 'E' to one of the builtins __builtin_os_log_format() or<br>
+// __builtin_os_log_format_buffer_size(), compute the layout of the buffer that<br>
+// the call will write into and store it in 'layout'. Returns 'false' if there<br>
+// was some error encountered while computing the layout, and 'true' otherwise.<br>
+bool computeOSLogBufferLayout(clang::ASTContext &Ctx, const clang::CallExpr *E,<br>
+                              OSLogBufferLayout &layout);<br>
+<br>
+} // namespace analyze_os_log<br>
+} // namespace clang<br>
+#endif<br>
<br>
Removed: cfe/trunk/include/clang/Analysis/Analyses/FormatString.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/FormatString.h?rev=345970&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/FormatString.h?rev=345970&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Analysis/Analyses/FormatString.h (original)<br>
+++ cfe/trunk/include/clang/Analysis/Analyses/FormatString.h (removed)<br>
@@ -1,719 +0,0 @@<br>
-//= FormatString.h - Analysis of printf/fprintf format strings --*- C++ -*-===//<br>
-//<br>
-//                     The LLVM Compiler Infrastructure<br>
-//<br>
-// This file is distributed under the University of Illinois Open Source<br>
-// License. See LICENSE.TXT for details.<br>
-//<br>
-//===----------------------------------------------------------------------===//<br>
-//<br>
-// This file defines APIs for analyzing the format strings of printf, fscanf,<br>
-// and friends.<br>
-//<br>
-// The structure of format strings for fprintf are described in C99 7.19.6.1.<br>
-//<br>
-// The structure of format strings for fscanf are described in C99 7.19.6.2.<br>
-//<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_FORMATSTRING_H<br>
-#define LLVM_CLANG_ANALYSIS_ANALYSES_FORMATSTRING_H<br>
-<br>
-#include "clang/AST/CanonicalType.h"<br>
-<br>
-namespace clang {<br>
-<br>
-class TargetInfo;<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-/// Common components of both fprintf and fscanf format strings.<br>
-namespace analyze_format_string {<br>
-<br>
-/// Class representing optional flags with location and representation<br>
-/// information.<br>
-class OptionalFlag {<br>
-public:<br>
-  OptionalFlag(const char *Representation)<br>
-      : representation(Representation), flag(false) {}<br>
-  bool isSet() const { return flag; }<br>
-  void set() { flag = true; }<br>
-  void clear() { flag = false; }<br>
-  void setPosition(const char *position) {<br>
-    assert(position);<br>
-    flag = true;<br>
-    this->position = position;<br>
-  }<br>
-  const char *getPosition() const {<br>
-    assert(position);<br>
-    return position;<br>
-  }<br>
-  const char *toString() const { return representation; }<br>
-<br>
-  // Overloaded operators for bool like qualities<br>
-  explicit operator bool() const { return flag; }<br>
-  OptionalFlag& operator=(const bool &rhs) {<br>
-    flag = rhs;<br>
-    return *this;  // Return a reference to myself.<br>
-  }<br>
-private:<br>
-  const char *representation;<br>
-  const char *position;<br>
-  bool flag;<br>
-};<br>
-<br>
-/// Represents the length modifier in a format string in scanf/printf.<br>
-class LengthModifier {<br>
-public:<br>
-  enum Kind {<br>
-    None,<br>
-    AsChar,       // 'hh'<br>
-    AsShort,      // 'h'<br>
-    AsLong,       // 'l'<br>
-    AsLongLong,   // 'll'<br>
-    AsQuad,       // 'q' (BSD, deprecated, for 64-bit integer types)<br>
-    AsIntMax,     // 'j'<br>
-    AsSizeT,      // 'z'<br>
-    AsPtrDiff,    // 't'<br>
-    AsInt32,      // 'I32' (MSVCRT, like __int32)<br>
-    AsInt3264,    // 'I'   (MSVCRT, like __int3264 from MIDL)<br>
-    AsInt64,      // 'I64' (MSVCRT, like __int64)<br>
-    AsLongDouble, // 'L'<br>
-    AsAllocate,   // for '%as', GNU extension to C90 scanf<br>
-    AsMAllocate,  // for '%ms', GNU extension to scanf<br>
-    AsWide,       // 'w' (MSVCRT, like l but only for c, C, s, S, or Z<br>
-    AsWideChar = AsLong // for '%ls', only makes sense for printf<br>
-  };<br>
-<br>
-  LengthModifier()<br>
-    : Position(nullptr), kind(None) {}<br>
-  LengthModifier(const char *pos, Kind k)<br>
-    : Position(pos), kind(k) {}<br>
-<br>
-  const char *getStart() const {<br>
-    return Position;<br>
-  }<br>
-<br>
-  unsigned getLength() const {<br>
-    switch (kind) {<br>
-      default:<br>
-        return 1;<br>
-      case AsLongLong:<br>
-      case AsChar:<br>
-        return 2;<br>
-      case AsInt32:<br>
-      case AsInt64:<br>
-        return 3;<br>
-      case None:<br>
-        return 0;<br>
-    }<br>
-  }<br>
-<br>
-  Kind getKind() const { return kind; }<br>
-  void setKind(Kind k) { kind = k; }<br>
-<br>
-  const char *toString() const;<br>
-<br>
-private:<br>
-  const char *Position;<br>
-  Kind kind;<br>
-};<br>
-<br>
-class ConversionSpecifier {<br>
-public:<br>
-  enum Kind {<br>
-    InvalidSpecifier = 0,<br>
-    // C99 conversion specifiers.<br>
-    cArg,<br>
-    dArg,<br>
-    DArg, // Apple extension<br>
-    iArg,<br>
-    IntArgBeg = dArg,<br>
-    IntArgEnd = iArg,<br>
-<br>
-    oArg,<br>
-    OArg, // Apple extension<br>
-    uArg,<br>
-    UArg, // Apple extension<br>
-    xArg,<br>
-    XArg,<br>
-    UIntArgBeg = oArg,<br>
-    UIntArgEnd = XArg,<br>
-<br>
-    fArg,<br>
-    FArg,<br>
-    eArg,<br>
-    EArg,<br>
-    gArg,<br>
-    GArg,<br>
-    aArg,<br>
-    AArg,<br>
-    DoubleArgBeg = fArg,<br>
-    DoubleArgEnd = AArg,<br>
-<br>
-    sArg,<br>
-    pArg,<br>
-    nArg,<br>
-    PercentArg,<br>
-    CArg,<br>
-    SArg,<br>
-<br>
-    // Apple extension: P specifies to os_log that the data being pointed to is<br>
-    // to be copied by os_log. The precision indicates the number of bytes to<br>
-    // copy.<br>
-    PArg,<br>
-<br>
-    // ** Printf-specific **<br>
-<br>
-    ZArg, // MS extension<br>
-<br>
-    // Objective-C specific specifiers.<br>
-    ObjCObjArg, // '@'<br>
-    ObjCBeg = ObjCObjArg,<br>
-    ObjCEnd = ObjCObjArg,<br>
-<br>
-    // FreeBSD kernel specific specifiers.<br>
-    FreeBSDbArg,<br>
-    FreeBSDDArg,<br>
-    FreeBSDrArg,<br>
-    FreeBSDyArg,<br>
-<br>
-    // GlibC specific specifiers.<br>
-    PrintErrno, // 'm'<br>
-<br>
-    PrintfConvBeg = ObjCObjArg,<br>
-    PrintfConvEnd = PrintErrno,<br>
-<br>
-    // ** Scanf-specific **<br>
-    ScanListArg, // '['<br>
-    ScanfConvBeg = ScanListArg,<br>
-    ScanfConvEnd = ScanListArg<br>
-  };<br>
-<br>
-  ConversionSpecifier(bool isPrintf = true)<br>
-    : IsPrintf(isPrintf), Position(nullptr), EndScanList(nullptr),<br>
-      kind(InvalidSpecifier) {}<br>
-<br>
-  ConversionSpecifier(bool isPrintf, const char *pos, Kind k)<br>
-    : IsPrintf(isPrintf), Position(pos), EndScanList(nullptr), kind(k) {}<br>
-<br>
-  const char *getStart() const {<br>
-    return Position;<br>
-  }<br>
-<br>
-  StringRef getCharacters() const {<br>
-    return StringRef(getStart(), getLength());<br>
-  }<br>
-<br>
-  bool consumesDataArgument() const {<br>
-    switch (kind) {<br>
-      case PrintErrno:<br>
-        assert(IsPrintf);<br>
-        return false;<br>
-      case PercentArg:<br>
-        return false;<br>
-      case InvalidSpecifier:<br>
-        return false;<br>
-      default:<br>
-        return true;<br>
-    }<br>
-  }<br>
-<br>
-  Kind getKind() const { return kind; }<br>
-  void setKind(Kind k) { kind = k; }<br>
-  unsigned getLength() const {<br>
-    return EndScanList ? EndScanList - Position : 1;<br>
-  }<br>
-  void setEndScanList(const char *pos) { EndScanList = pos; }<br>
-<br>
-  bool isIntArg() const { return (kind >= IntArgBeg && kind <= IntArgEnd) ||<br>
-    kind == FreeBSDrArg || kind == FreeBSDyArg; }<br>
-  bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; }<br>
-  bool isAnyIntArg() const { return kind >= IntArgBeg && kind <= UIntArgEnd; }<br>
-  bool isDoubleArg() const {<br>
-    return kind >= DoubleArgBeg && kind <= DoubleArgEnd;<br>
-  }<br>
-<br>
-  const char *toString() const;<br>
-<br>
-  bool isPrintfKind() const { return IsPrintf; }<br>
-<br>
-  Optional<ConversionSpecifier> getStandardSpecifier() const;<br>
-<br>
-protected:<br>
-  bool IsPrintf;<br>
-  const char *Position;<br>
-  const char *EndScanList;<br>
-  Kind kind;<br>
-};<br>
-<br>
-class ArgType {<br>
-public:<br>
-  enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy,<br>
-              AnyCharTy, CStrTy, WCStrTy, WIntTy };<br>
-<br>
-  enum MatchKind { NoMatch = 0, Match = 1, NoMatchPedantic };<br>
-<br>
-private:<br>
-  const Kind K;<br>
-  QualType T;<br>
-  const char *Name = nullptr;<br>
-  bool Ptr = false;<br>
-<br>
-  /// The TypeKind identifies certain well-known types like size_t and<br>
-  /// ptrdiff_t.<br>
-  enum class TypeKind { DontCare, SizeT, PtrdiffT };<br>
-  TypeKind TK = TypeKind::DontCare;<br>
-<br>
-public:<br>
-  ArgType(Kind K = UnknownTy, const char *N = nullptr) : K(K), Name(N) {}<br>
-  ArgType(QualType T, const char *N = nullptr) : K(SpecificTy), T(T), Name(N) {}<br>
-  ArgType(CanQualType T) : K(SpecificTy), T(T) {}<br>
-<br>
-  static ArgType Invalid() { return ArgType(InvalidTy); }<br>
-  bool isValid() const { return K != InvalidTy; }<br>
-<br>
-  bool isSizeT() const { return TK == TypeKind::SizeT; }<br>
-<br>
-  bool isPtrdiffT() const { return TK == TypeKind::PtrdiffT; }<br>
-<br>
-  /// Create an ArgType which corresponds to the type pointer to A.<br>
-  static ArgType PtrTo(const ArgType& A) {<br>
-    assert(A.K >= InvalidTy && "ArgType cannot be pointer to invalid/unknown");<br>
-    ArgType Res = A;<br>
-    Res.Ptr = true;<br>
-    return Res;<br>
-  }<br>
-<br>
-  /// Create an ArgType which corresponds to the size_t/ssize_t type.<br>
-  static ArgType makeSizeT(const ArgType &A) {<br>
-    ArgType Res = A;<br>
-    Res.TK = TypeKind::SizeT;<br>
-    return Res;<br>
-  }<br>
-<br>
-  /// Create an ArgType which corresponds to the ptrdiff_t/unsigned ptrdiff_t<br>
-  /// type.<br>
-  static ArgType makePtrdiffT(const ArgType &A) {<br>
-    ArgType Res = A;<br>
-    Res.TK = TypeKind::PtrdiffT;<br>
-    return Res;<br>
-  }<br>
-<br>
-  MatchKind matchesType(ASTContext &C, QualType argTy) const;<br>
-<br>
-  QualType getRepresentativeType(ASTContext &C) const;<br>
-<br>
-  std::string getRepresentativeTypeName(ASTContext &C) const;<br>
-};<br>
-<br>
-class OptionalAmount {<br>
-public:<br>
-  enum HowSpecified { NotSpecified, Constant, Arg, Invalid };<br>
-<br>
-  OptionalAmount(HowSpecified howSpecified,<br>
-                 unsigned amount,<br>
-                 const char *amountStart,<br>
-                 unsigned amountLength,<br>
-                 bool usesPositionalArg)<br>
-  : start(amountStart), length(amountLength), hs(howSpecified), amt(amount),<br>
-  UsesPositionalArg(usesPositionalArg), UsesDotPrefix(0) {}<br>
-<br>
-  OptionalAmount(bool valid = true)<br>
-  : start(nullptr),length(0), hs(valid ? NotSpecified : Invalid), amt(0),<br>
-  UsesPositionalArg(0), UsesDotPrefix(0) {}<br>
-<br>
-  bool isInvalid() const {<br>
-    return hs == Invalid;<br>
-  }<br>
-<br>
-  HowSpecified getHowSpecified() const { return hs; }<br>
-  void setHowSpecified(HowSpecified h) { hs = h; }<br>
-<br>
-  bool hasDataArgument() const { return hs == Arg; }<br>
-<br>
-  unsigned getArgIndex() const {<br>
-    assert(hasDataArgument());<br>
-    return amt;<br>
-  }<br>
-<br>
-  unsigned getConstantAmount() const {<br>
-    assert(hs == Constant);<br>
-    return amt;<br>
-  }<br>
-<br>
-  const char *getStart() const {<br>
-      // We include the . character if it is given.<br>
-    return start - UsesDotPrefix;<br>
-  }<br>
-<br>
-  unsigned getConstantLength() const {<br>
-    assert(hs == Constant);<br>
-    return length + UsesDotPrefix;<br>
-  }<br>
-<br>
-  ArgType getArgType(ASTContext &Ctx) const;<br>
-<br>
-  void toString(raw_ostream &os) const;<br>
-<br>
-  bool usesPositionalArg() const { return (bool) UsesPositionalArg; }<br>
-  unsigned getPositionalArgIndex() const {<br>
-    assert(hasDataArgument());<br>
-    return amt + 1;<br>
-  }<br>
-<br>
-  bool usesDotPrefix() const { return UsesDotPrefix; }<br>
-  void setUsesDotPrefix() { UsesDotPrefix = true; }<br>
-<br>
-private:<br>
-  const char *start;<br>
-  unsigned length;<br>
-  HowSpecified hs;<br>
-  unsigned amt;<br>
-  bool UsesPositionalArg : 1;<br>
-  bool UsesDotPrefix;<br>
-};<br>
-<br>
-<br>
-class FormatSpecifier {<br>
-protected:<br>
-  LengthModifier LM;<br>
-  OptionalAmount FieldWidth;<br>
-  ConversionSpecifier CS;<br>
-  /// Positional arguments, an IEEE extension:<br>
-  ///  IEEE Std 1003.1, 2004 Edition<br>
-  ///  <a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html" rel="noreferrer" target="_blank">http://www.opengroup.org/onlinepubs/009695399/functions/printf.html</a><br>
-  bool UsesPositionalArg;<br>
-  unsigned argIndex;<br>
-public:<br>
-  FormatSpecifier(bool isPrintf)<br>
-    : CS(isPrintf), UsesPositionalArg(false), argIndex(0) {}<br>
-<br>
-  void setLengthModifier(LengthModifier lm) {<br>
-    LM = lm;<br>
-  }<br>
-<br>
-  void setUsesPositionalArg() { UsesPositionalArg = true; }<br>
-<br>
-  void setArgIndex(unsigned i) {<br>
-    argIndex = i;<br>
-  }<br>
-<br>
-  unsigned getArgIndex() const {<br>
-    return argIndex;<br>
-  }<br>
-<br>
-  unsigned getPositionalArgIndex() const {<br>
-    return argIndex + 1;<br>
-  }<br>
-<br>
-  const LengthModifier &getLengthModifier() const {<br>
-    return LM;<br>
-  }<br>
-<br>
-  const OptionalAmount &getFieldWidth() const {<br>
-    return FieldWidth;<br>
-  }<br>
-<br>
-  void setFieldWidth(const OptionalAmount &Amt) {<br>
-    FieldWidth = Amt;<br>
-  }<br>
-<br>
-  bool usesPositionalArg() const { return UsesPositionalArg; }<br>
-<br>
-  bool hasValidLengthModifier(const TargetInfo &Target) const;<br>
-<br>
-  bool hasStandardLengthModifier() const;<br>
-<br>
-  Optional<LengthModifier> getCorrectedLengthModifier() const;<br>
-<br>
-  bool hasStandardConversionSpecifier(const LangOptions &LangOpt) const;<br>
-<br>
-  bool hasStandardLengthConversionCombination() const;<br>
-<br>
-  /// For a TypedefType QT, if it is a named integer type such as size_t,<br>
-  /// assign the appropriate value to LM and return true.<br>
-  static bool namedTypeToLengthModifier(QualType QT, LengthModifier &LM);<br>
-};<br>
-<br>
-} // end analyze_format_string namespace<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-/// Pieces specific to fprintf format strings.<br>
-<br>
-namespace analyze_printf {<br>
-<br>
-class PrintfConversionSpecifier :<br>
-  public analyze_format_string::ConversionSpecifier  {<br>
-public:<br>
-  PrintfConversionSpecifier()<br>
-    : ConversionSpecifier(true, nullptr, InvalidSpecifier) {}<br>
-<br>
-  PrintfConversionSpecifier(const char *pos, Kind k)<br>
-    : ConversionSpecifier(true, pos, k) {}<br>
-<br>
-  bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; }<br>
-  bool isDoubleArg() const { return kind >= DoubleArgBeg &&<br>
-                                    kind <= DoubleArgEnd; }<br>
-<br>
-  static bool classof(const analyze_format_string::ConversionSpecifier *CS) {<br>
-    return CS->isPrintfKind();<br>
-  }<br>
-};<br>
-<br>
-using analyze_format_string::ArgType;<br>
-using analyze_format_string::LengthModifier;<br>
-using analyze_format_string::OptionalAmount;<br>
-using analyze_format_string::OptionalFlag;<br>
-<br>
-class PrintfSpecifier : public analyze_format_string::FormatSpecifier {<br>
-  OptionalFlag HasThousandsGrouping; // ''', POSIX extension.<br>
-  OptionalFlag IsLeftJustified; // '-'<br>
-  OptionalFlag HasPlusPrefix; // '+'<br>
-  OptionalFlag HasSpacePrefix; // ' '<br>
-  OptionalFlag HasAlternativeForm; // '#'<br>
-  OptionalFlag HasLeadingZeroes; // '0'<br>
-  OptionalFlag HasObjCTechnicalTerm; // '[tt]'<br>
-  OptionalFlag IsPrivate;            // '{private}'<br>
-  OptionalFlag IsPublic;             // '{public}'<br>
-  OptionalAmount Precision;<br>
-public:<br>
-  PrintfSpecifier()<br>
-      : FormatSpecifier(/* isPrintf = */ true), HasThousandsGrouping("'"),<br>
-        IsLeftJustified("-"), HasPlusPrefix("+"), HasSpacePrefix(" "),<br>
-        HasAlternativeForm("#"), HasLeadingZeroes("0"),<br>
-        HasObjCTechnicalTerm("tt"), IsPrivate("private"), IsPublic("public") {}<br>
-<br>
-  static PrintfSpecifier Parse(const char *beg, const char *end);<br>
-<br>
-    // Methods for incrementally constructing the PrintfSpecifier.<br>
-  void setConversionSpecifier(const PrintfConversionSpecifier &cs) {<br>
-    CS = cs;<br>
-  }<br>
-  void setHasThousandsGrouping(const char *position) {<br>
-    HasThousandsGrouping.setPosition(position);<br>
-  }<br>
-  void setIsLeftJustified(const char *position) {<br>
-    IsLeftJustified.setPosition(position);<br>
-  }<br>
-  void setHasPlusPrefix(const char *position) {<br>
-    HasPlusPrefix.setPosition(position);<br>
-  }<br>
-  void setHasSpacePrefix(const char *position) {<br>
-    HasSpacePrefix.setPosition(position);<br>
-  }<br>
-  void setHasAlternativeForm(const char *position) {<br>
-    HasAlternativeForm.setPosition(position);<br>
-  }<br>
-  void setHasLeadingZeros(const char *position) {<br>
-    HasLeadingZeroes.setPosition(position);<br>
-  }<br>
-  void setHasObjCTechnicalTerm(const char *position) {<br>
-    HasObjCTechnicalTerm.setPosition(position);<br>
-  }<br>
-  void setIsPrivate(const char *position) { IsPrivate.setPosition(position); }<br>
-  void setIsPublic(const char *position) { IsPublic.setPosition(position); }<br>
-  void setUsesPositionalArg() { UsesPositionalArg = true; }<br>
-<br>
-    // Methods for querying the format specifier.<br>
-<br>
-  const PrintfConversionSpecifier &getConversionSpecifier() const {<br>
-    return cast<PrintfConversionSpecifier>(CS);<br>
-  }<br>
-<br>
-  void setPrecision(const OptionalAmount &Amt) {<br>
-    Precision = Amt;<br>
-    Precision.setUsesDotPrefix();<br>
-  }<br>
-<br>
-  const OptionalAmount &getPrecision() const {<br>
-    return Precision;<br>
-  }<br>
-<br>
-  bool consumesDataArgument() const {<br>
-    return getConversionSpecifier().consumesDataArgument();<br>
-  }<br>
-<br>
-  /// Returns the builtin type that a data argument<br>
-  /// paired with this format specifier should have.  This method<br>
-  /// will return null if the format specifier does not have<br>
-  /// a matching data argument or the matching argument matches<br>
-  /// more than one type.<br>
-  ArgType getArgType(ASTContext &Ctx, bool IsObjCLiteral) const;<br>
-<br>
-  const OptionalFlag &hasThousandsGrouping() const {<br>
-      return HasThousandsGrouping;<br>
-  }<br>
-  const OptionalFlag &isLeftJustified() const { return IsLeftJustified; }<br>
-  const OptionalFlag &hasPlusPrefix() const { return HasPlusPrefix; }<br>
-  const OptionalFlag &hasAlternativeForm() const { return HasAlternativeForm; }<br>
-  const OptionalFlag &hasLeadingZeros() const { return HasLeadingZeroes; }<br>
-  const OptionalFlag &hasSpacePrefix() const { return HasSpacePrefix; }<br>
-  const OptionalFlag &hasObjCTechnicalTerm() const { return HasObjCTechnicalTerm; }<br>
-  const OptionalFlag &isPrivate() const { return IsPrivate; }<br>
-  const OptionalFlag &isPublic() const { return IsPublic; }<br>
-  bool usesPositionalArg() const { return UsesPositionalArg; }<br>
-<br>
-  /// Changes the specifier and length according to a QualType, retaining any<br>
-  /// flags or options. Returns true on success, or false when a conversion<br>
-  /// was not successful.<br>
-  bool fixType(QualType QT, const LangOptions &LangOpt, ASTContext &Ctx,<br>
-               bool IsObjCLiteral);<br>
-<br>
-  void toString(raw_ostream &os) const;<br>
-<br>
-  // Validation methods - to check if any element results in undefined behavior<br>
-  bool hasValidPlusPrefix() const;<br>
-  bool hasValidAlternativeForm() const;<br>
-  bool hasValidLeadingZeros() const;<br>
-  bool hasValidSpacePrefix() const;<br>
-  bool hasValidLeftJustified() const;<br>
-  bool hasValidThousandsGroupingPrefix() const;<br>
-<br>
-  bool hasValidPrecision() const;<br>
-  bool hasValidFieldWidth() const;<br>
-};<br>
-}  // end analyze_printf namespace<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-/// Pieces specific to fscanf format strings.<br>
-<br>
-namespace analyze_scanf {<br>
-<br>
-class ScanfConversionSpecifier :<br>
-    public analyze_format_string::ConversionSpecifier  {<br>
-public:<br>
-  ScanfConversionSpecifier()<br>
-    : ConversionSpecifier(false, nullptr, InvalidSpecifier) {}<br>
-<br>
-  ScanfConversionSpecifier(const char *pos, Kind k)<br>
-    : ConversionSpecifier(false, pos, k) {}<br>
-<br>
-  static bool classof(const analyze_format_string::ConversionSpecifier *CS) {<br>
-    return !CS->isPrintfKind();<br>
-  }<br>
-};<br>
-<br>
-using analyze_format_string::ArgType;<br>
-using analyze_format_string::LengthModifier;<br>
-using analyze_format_string::OptionalAmount;<br>
-using analyze_format_string::OptionalFlag;<br>
-<br>
-class ScanfSpecifier : public analyze_format_string::FormatSpecifier {<br>
-  OptionalFlag SuppressAssignment; // '*'<br>
-public:<br>
-  ScanfSpecifier() :<br>
-    FormatSpecifier(/* isPrintf = */ false),<br>
-    SuppressAssignment("*") {}<br>
-<br>
-  void setSuppressAssignment(const char *position) {<br>
-    SuppressAssignment.setPosition(position);<br>
-  }<br>
-<br>
-  const OptionalFlag &getSuppressAssignment() const {<br>
-    return SuppressAssignment;<br>
-  }<br>
-<br>
-  void setConversionSpecifier(const ScanfConversionSpecifier &cs) {<br>
-    CS = cs;<br>
-  }<br>
-<br>
-  const ScanfConversionSpecifier &getConversionSpecifier() const {<br>
-    return cast<ScanfConversionSpecifier>(CS);<br>
-  }<br>
-<br>
-  bool consumesDataArgument() const {<br>
-    return CS.consumesDataArgument() && !SuppressAssignment;<br>
-  }<br>
-<br>
-  ArgType getArgType(ASTContext &Ctx) const;<br>
-<br>
-  bool fixType(QualType QT, QualType RawQT, const LangOptions &LangOpt,<br>
-               ASTContext &Ctx);<br>
-<br>
-  void toString(raw_ostream &os) const;<br>
-<br>
-  static ScanfSpecifier Parse(const char *beg, const char *end);<br>
-};<br>
-<br>
-} // end analyze_scanf namespace<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Parsing and processing of format strings (both fprintf and fscanf).<br>
-<br>
-namespace analyze_format_string {<br>
-<br>
-enum PositionContext { FieldWidthPos = 0, PrecisionPos = 1 };<br>
-<br>
-class FormatStringHandler {<br>
-public:<br>
-  FormatStringHandler() {}<br>
-  virtual ~FormatStringHandler();<br>
-<br>
-  virtual void HandleNullChar(const char *nullCharacter) {}<br>
-<br>
-  virtual void HandlePosition(const char *startPos, unsigned posLen) {}<br>
-<br>
-  virtual void HandleInvalidPosition(const char *startPos, unsigned posLen,<br>
-                                     PositionContext p) {}<br>
-<br>
-  virtual void HandleZeroPosition(const char *startPos, unsigned posLen) {}<br>
-<br>
-  virtual void HandleIncompleteSpecifier(const char *startSpecifier,<br>
-                                         unsigned specifierLen) {}<br>
-<br>
-  virtual void HandleEmptyObjCModifierFlag(const char *startFlags,<br>
-                                           unsigned flagsLen) {}<br>
-<br>
-  virtual void HandleInvalidObjCModifierFlag(const char *startFlag,<br>
-                                             unsigned flagLen) {}<br>
-<br>
-  virtual void HandleObjCFlagsWithNonObjCConversion(const char *flagsStart,<br>
-                                            const char *flagsEnd,<br>
-                                            const char *conversionPosition) {}<br>
-  // Printf-specific handlers.<br>
-<br>
-  virtual bool HandleInvalidPrintfConversionSpecifier(<br>
-                                      const analyze_printf::PrintfSpecifier &FS,<br>
-                                      const char *startSpecifier,<br>
-                                      unsigned specifierLen) {<br>
-    return true;<br>
-  }<br>
-<br>
-  virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,<br>
-                                     const char *startSpecifier,<br>
-                                     unsigned specifierLen) {<br>
-    return true;<br>
-  }<br>
-<br>
-    // Scanf-specific handlers.<br>
-<br>
-  virtual bool HandleInvalidScanfConversionSpecifier(<br>
-                                        const analyze_scanf::ScanfSpecifier &FS,<br>
-                                        const char *startSpecifier,<br>
-                                        unsigned specifierLen) {<br>
-    return true;<br>
-  }<br>
-<br>
-  virtual bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,<br>
-                                    const char *startSpecifier,<br>
-                                    unsigned specifierLen) {<br>
-    return true;<br>
-  }<br>
-<br>
-  virtual void HandleIncompleteScanList(const char *start, const char *end) {}<br>
-};<br>
-<br>
-bool ParsePrintfString(FormatStringHandler &H,<br>
-                       const char *beg, const char *end, const LangOptions &LO,<br>
-                       const TargetInfo &Target, bool isFreeBSDKPrintf);<br>
-<br>
-bool ParseFormatStringHasSArg(const char *beg, const char *end,<br>
-                              const LangOptions &LO, const TargetInfo &Target);<br>
-<br>
-bool ParseScanfString(FormatStringHandler &H,<br>
-                      const char *beg, const char *end, const LangOptions &LO,<br>
-                      const TargetInfo &Target);<br>
-<br>
-} // end analyze_format_string namespace<br>
-} // end clang namespace<br>
-#endif<br>
<br>
Removed: cfe/trunk/include/clang/Analysis/Analyses/OSLog.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/OSLog.h?rev=345970&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/OSLog.h?rev=345970&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Analysis/Analyses/OSLog.h (original)<br>
+++ cfe/trunk/include/clang/Analysis/Analyses/OSLog.h (removed)<br>
@@ -1,155 +0,0 @@<br>
-//= OSLog.h - Analysis of calls to os_log builtins --*- C++ -*-===============//<br>
-//<br>
-//                     The LLVM Compiler Infrastructure<br>
-//<br>
-// This file is distributed under the University of Illinois Open Source<br>
-// License. See LICENSE.TXT for details.<br>
-//<br>
-//===----------------------------------------------------------------------===//<br>
-//<br>
-// This file defines APIs for determining the layout of the data buffer for<br>
-// os_log() and os_trace().<br>
-//<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_OSLOG_H<br>
-#define LLVM_CLANG_ANALYSIS_ANALYSES_OSLOG_H<br>
-<br>
-#include "clang/AST/ASTContext.h"<br>
-#include "clang/AST/Expr.h"<br>
-<br>
-namespace clang {<br>
-namespace analyze_os_log {<br>
-<br>
-/// An OSLogBufferItem represents a single item in the data written by a call<br>
-/// to os_log() or os_trace().<br>
-class OSLogBufferItem {<br>
-public:<br>
-  enum Kind {<br>
-    // The item is a scalar (int, float, raw pointer, etc.). No further copying<br>
-    // is required. This is the only kind allowed by os_trace().<br>
-    ScalarKind = 0,<br>
-<br>
-    // The item is a count, which describes the length of the following item to<br>
-    // be copied. A count may only be followed by an item of kind StringKind,<br>
-    // WideStringKind, or PointerKind.<br>
-    CountKind,<br>
-<br>
-    // The item is a pointer to a C string. If preceded by a count 'n',<br>
-    // os_log() will copy at most 'n' bytes from the pointer.<br>
-    StringKind,<br>
-<br>
-    // The item is a pointer to a block of raw data. This item must be preceded<br>
-    // by a count 'n'. os_log() will copy exactly 'n' bytes from the pointer.<br>
-    PointerKind,<br>
-<br>
-    // The item is a pointer to an Objective-C object. os_log() may retain the<br>
-    // object for later processing.<br>
-    ObjCObjKind,<br>
-<br>
-    // The item is a pointer to wide-char string.<br>
-    WideStringKind,<br>
-<br>
-    // The item is corresponding to the '%m' format specifier, no value is<br>
-    // populated in the buffer and the runtime is loading the errno value.<br>
-    ErrnoKind<br>
-  };<br>
-<br>
-  enum {<br>
-    // The item is marked "private" in the format string.<br>
-    IsPrivate = 0x1,<br>
-<br>
-    // The item is marked "public" in the format string.<br>
-    IsPublic = 0x2<br>
-  };<br>
-<br>
-private:<br>
-  Kind TheKind = ScalarKind;<br>
-  const Expr *TheExpr = nullptr;<br>
-  CharUnits ConstValue;<br>
-  CharUnits Size; // size of the data, not including the header bytes<br>
-  unsigned Flags = 0;<br>
-<br>
-public:<br>
-  OSLogBufferItem(Kind kind, const Expr *expr, CharUnits size, unsigned flags)<br>
-      : TheKind(kind), TheExpr(expr), Size(size), Flags(flags) {}<br>
-<br>
-  OSLogBufferItem(ASTContext &Ctx, CharUnits value, unsigned flags)<br>
-      : TheKind(CountKind), ConstValue(value),<br>
-        Size(Ctx.getTypeSizeInChars(Ctx.IntTy)), Flags(flags) {}<br>
-<br>
-  unsigned char getDescriptorByte() const {<br>
-    unsigned char result = 0;<br>
-    if (getIsPrivate())<br>
-      result |= IsPrivate;<br>
-    if (getIsPublic())<br>
-      result |= IsPublic;<br>
-    result |= ((unsigned)getKind()) << 4;<br>
-    return result;<br>
-  }<br>
-<br>
-  unsigned char getSizeByte() const { return size().getQuantity(); }<br>
-<br>
-  Kind getKind() const { return TheKind; }<br>
-  bool getIsPrivate() const { return (Flags & IsPrivate) != 0; }<br>
-  bool getIsPublic() const { return (Flags & IsPublic) != 0; }<br>
-<br>
-  const Expr *getExpr() const { return TheExpr; }<br>
-  CharUnits getConstValue() const { return ConstValue; }<br>
-  CharUnits size() const { return Size; }<br>
-};<br>
-<br>
-class OSLogBufferLayout {<br>
-public:<br>
-  SmallVector<OSLogBufferItem, 4> Items;<br>
-<br>
-  enum Flags { HasPrivateItems = 1, HasNonScalarItems = 1 << 1 };<br>
-<br>
-  CharUnits size() const {<br>
-    CharUnits result;<br>
-    result += CharUnits::fromQuantity(2); // summary byte, num-args byte<br>
-    for (auto &item : Items) {<br>
-      // descriptor byte, size byte<br>
-      result += item.size() + CharUnits::fromQuantity(2);<br>
-    }<br>
-    return result;<br>
-  }<br>
-<br>
-  bool hasPrivateItems() const {<br>
-    return llvm::any_of(<br>
-        Items, [](const OSLogBufferItem &Item) { return Item.getIsPrivate(); });<br>
-  }<br>
-<br>
-  bool hasPublicItems() const {<br>
-    return llvm::any_of(<br>
-        Items, [](const OSLogBufferItem &Item) { return Item.getIsPublic(); });<br>
-  }<br>
-<br>
-  bool hasNonScalar() const {<br>
-    return llvm::any_of(Items, [](const OSLogBufferItem &Item) {<br>
-      return Item.getKind() != OSLogBufferItem::ScalarKind;<br>
-    });<br>
-  }<br>
-<br>
-  unsigned char getSummaryByte() const {<br>
-    unsigned char result = 0;<br>
-    if (hasPrivateItems())<br>
-      result |= HasPrivateItems;<br>
-    if (hasNonScalar())<br>
-      result |= HasNonScalarItems;<br>
-    return result;<br>
-  }<br>
-<br>
-  unsigned char getNumArgsByte() const { return Items.size(); }<br>
-};<br>
-<br>
-// Given a call 'E' to one of the builtins __builtin_os_log_format() or<br>
-// __builtin_os_log_format_buffer_size(), compute the layout of the buffer that<br>
-// the call will write into and store it in 'layout'. Returns 'false' if there<br>
-// was some error encountered while computing the layout, and 'true' otherwise.<br>
-bool computeOSLogBufferLayout(clang::ASTContext &Ctx, const clang::CallExpr *E,<br>
-                              OSLogBufferLayout &layout);<br>
-<br>
-} // namespace analyze_os_log<br>
-} // namespace clang<br>
-#endif<br>
<br>
Modified: cfe/trunk/lib/AST/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CMakeLists.txt?rev=345971&r1=345970&r2=345971&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CMakeLists.txt?rev=345971&r1=345970&r2=345971&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/CMakeLists.txt (original)<br>
+++ cfe/trunk/lib/AST/CMakeLists.txt Fri Nov  2 06:14:11 2018<br>
@@ -39,6 +39,7 @@ add_clang_library(clangAST<br>
   ExprObjC.cpp<br>
   ExternalASTMerger.cpp<br>
   ExternalASTSource.cpp<br>
+  FormatString.cpp<br>
   InheritViz.cpp<br>
   ItaniumCXXABI.cpp<br>
   ItaniumMangle.cpp<br>
@@ -48,12 +49,15 @@ add_clang_library(clangAST<br>
   NestedNameSpecifier.cpp<br>
   NSAPI.cpp<br>
   ODRHash.cpp<br>
+  OSLog.cpp<br>
   OpenMPClause.cpp<br>
   ParentMap.cpp<br>
+  PrintfFormatString.cpp<br>
   QualTypeNames.cpp<br>
   RawCommentList.cpp<br>
   RecordLayout.cpp<br>
   RecordLayoutBuilder.cpp<br>
+  ScanfFormatString.cpp<br>
   SelectorLocationsKind.cpp<br>
   Stmt.cpp<br>
   StmtCXX.cpp<br>
<br>
Modified: cfe/trunk/lib/AST/ExprConstant.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=345971&r1=345970&r2=345971&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=345971&r1=345970&r2=345971&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)<br>
+++ cfe/trunk/lib/AST/ExprConstant.cpp Fri Nov  2 06:14:11 2018<br>
@@ -39,6 +39,7 @@<br>
 #include "clang/AST/ASTLambda.h"<br>
 #include "clang/AST/CharUnits.h"<br>
 #include "clang/AST/Expr.h"<br>
+#include "clang/AST/OSLog.h"<br>
 #include "clang/AST/RecordLayout.h"<br>
 #include "clang/AST/StmtVisitor.h"<br>
 #include "clang/AST/TypeLoc.h"<br>
@@ -8126,6 +8127,12 @@ bool IntExprEvaluator::VisitBuiltinCallE<br>
     llvm_unreachable("unexpected EvalMode");<br>
   }<br>
<br>
+  case Builtin::BI__builtin_os_log_format_buffer_size: {<br>
+    analyze_os_log::OSLogBufferLayout Layout;<br>
+    analyze_os_log::computeOSLogBufferLayout(Info.Ctx, E, Layout);<br>
+    return Success(Layout.size().getQuantity(), E);<br>
+  }<br>
+<br>
   case Builtin::BI__builtin_bswap16:<br>
   case Builtin::BI__builtin_bswap32:<br>
   case Builtin::BI__builtin_bswap64: {<br>
<br>
Added: cfe/trunk/lib/AST/FormatString.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/FormatString.cpp?rev=345971&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/FormatString.cpp?rev=345971&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/FormatString.cpp (added)<br>
+++ cfe/trunk/lib/AST/FormatString.cpp Fri Nov  2 06:14:11 2018<br>
@@ -0,0 +1,955 @@<br>
+// FormatString.cpp - Common stuff for handling printf/scanf formats -*- C++ -*-<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// Shared details for processing format strings of printf and scanf<br>
+// (and friends).<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "FormatStringParsing.h"<br>
+#include "clang/Basic/LangOptions.h"<br>
+#include "clang/Basic/TargetInfo.h"<br>
+#include "llvm/Support/ConvertUTF.h"<br>
+<br>
+using clang::analyze_format_string::ArgType;<br>
+using clang::analyze_format_string::FormatStringHandler;<br>
+using clang::analyze_format_string::FormatSpecifier;<br>
+using clang::analyze_format_string::LengthModifier;<br>
+using clang::analyze_format_string::OptionalAmount;<br>
+using clang::analyze_format_string::PositionContext;<br>
+using clang::analyze_format_string::ConversionSpecifier;<br>
+using namespace clang;<br>
+<br>
+// Key function to FormatStringHandler.<br>
+FormatStringHandler::~FormatStringHandler() {}<br>
+<br>
+//===----------------------------------------------------------------------===//<br>
+// Functions for parsing format strings components in both printf and<br>
+// scanf format strings.<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+OptionalAmount<br>
+clang::analyze_format_string::ParseAmount(const char *&Beg, const char *E) {<br>
+  const char *I = Beg;<br>
+  UpdateOnReturn <const char*> UpdateBeg(Beg, I);<br>
+<br>
+  unsigned accumulator = 0;<br>
+  bool hasDigits = false;<br>
+<br>
+  for ( ; I != E; ++I) {<br>
+    char c = *I;<br>
+    if (c >= '0' && c <= '9') {<br>
+      hasDigits = true;<br>
+      accumulator = (accumulator * 10) + (c - '0');<br>
+      continue;<br>
+    }<br>
+<br>
+    if (hasDigits)<br>
+      return OptionalAmount(OptionalAmount::Constant, accumulator, Beg, I - Beg,<br>
+          false);<br>
+<br>
+    break;<br>
+  }<br>
+<br>
+  return OptionalAmount();<br>
+}<br>
+<br>
+OptionalAmount<br>
+clang::analyze_format_string::ParseNonPositionAmount(const char *&Beg,<br>
+                                                     const char *E,<br>
+                                                     unsigned &argIndex) {<br>
+  if (*Beg == '*') {<br>
+    ++Beg;<br>
+    return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg, 0, false);<br>
+  }<br>
+<br>
+  return ParseAmount(Beg, E);<br>
+}<br>
+<br>
+OptionalAmount<br>
+clang::analyze_format_string::ParsePositionAmount(FormatStringHandler &H,<br>
+                                                  const char *Start,<br>
+                                                  const char *&Beg,<br>
+                                                  const char *E,<br>
+                                                  PositionContext p) {<br>
+  if (*Beg == '*') {<br>
+    const char *I = Beg + 1;<br>
+    const OptionalAmount &Amt = ParseAmount(I, E);<br>
+<br>
+    if (Amt.getHowSpecified() == OptionalAmount::NotSpecified) {<br>
+      H.HandleInvalidPosition(Beg, I - Beg, p);<br>
+      return OptionalAmount(false);<br>
+    }<br>
+<br>
+    if (I == E) {<br>
+      // No more characters left?<br>
+      H.HandleIncompleteSpecifier(Start, E - Start);<br>
+      return OptionalAmount(false);<br>
+    }<br>
+<br>
+    assert(Amt.getHowSpecified() == OptionalAmount::Constant);<br>
+<br>
+    if (*I == '$') {<br>
+      // Handle positional arguments<br>
+<br>
+      // Special case: '*0$', since this is an easy mistake.<br>
+      if (Amt.getConstantAmount() == 0) {<br>
+        H.HandleZeroPosition(Beg, I - Beg + 1);<br>
+        return OptionalAmount(false);<br>
+      }<br>
+<br>
+      const char *Tmp = Beg;<br>
+      Beg = ++I;<br>
+<br>
+      return OptionalAmount(OptionalAmount::Arg, Amt.getConstantAmount() - 1,<br>
+                            Tmp, 0, true);<br>
+    }<br>
+<br>
+    H.HandleInvalidPosition(Beg, I - Beg, p);<br>
+    return OptionalAmount(false);<br>
+  }<br>
+<br>
+  return ParseAmount(Beg, E);<br>
+}<br>
+<br>
+<br>
+bool<br>
+clang::analyze_format_string::ParseFieldWidth(FormatStringHandler &H,<br>
+                                              FormatSpecifier &CS,<br>
+                                              const char *Start,<br>
+                                              const char *&Beg, const char *E,<br>
+                                              unsigned *argIndex) {<br>
+  // FIXME: Support negative field widths.<br>
+  if (argIndex) {<br>
+    CS.setFieldWidth(ParseNonPositionAmount(Beg, E, *argIndex));<br>
+  }<br>
+  else {<br>
+    const OptionalAmount Amt =<br>
+      ParsePositionAmount(H, Start, Beg, E,<br>
+                          analyze_format_string::FieldWidthPos);<br>
+<br>
+    if (Amt.isInvalid())<br>
+      return true;<br>
+    CS.setFieldWidth(Amt);<br>
+  }<br>
+  return false;<br>
+}<br>
+<br>
+bool<br>
+clang::analyze_format_string::ParseArgPosition(FormatStringHandler &H,<br>
+                                               FormatSpecifier &FS,<br>
+                                               const char *Start,<br>
+                                               const char *&Beg,<br>
+                                               const char *E) {<br>
+  const char *I = Beg;<br>
+<br>
+  const OptionalAmount &Amt = ParseAmount(I, E);<br>
+<br>
+  if (I == E) {<br>
+    // No more characters left?<br>
+    H.HandleIncompleteSpecifier(Start, E - Start);<br>
+    return true;<br>
+  }<br>
+<br>
+  if (Amt.getHowSpecified() == OptionalAmount::Constant && *(I++) == '$') {<br>
+    // Warn that positional arguments are non-standard.<br>
+    H.HandlePosition(Start, I - Start);<br>
+<br>
+    // Special case: '%0$', since this is an easy mistake.<br>
+    if (Amt.getConstantAmount() == 0) {<br>
+      H.HandleZeroPosition(Start, I - Start);<br>
+      return true;<br>
+    }<br>
+<br>
+    FS.setArgIndex(Amt.getConstantAmount() - 1);<br>
+    FS.setUsesPositionalArg();<br>
+    // Update the caller's pointer if we decided to consume<br>
+    // these characters.<br>
+    Beg = I;<br>
+    return false;<br>
+  }<br>
+<br>
+  return false;<br>
+}<br>
+<br>
+bool<br>
+clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS,<br>
+                                                  const char *&I,<br>
+                                                  const char *E,<br>
+                                                  const LangOptions &LO,<br>
+                                                  bool IsScanf) {<br>
+  LengthModifier::Kind lmKind = LengthModifier::None;<br>
+  const char *lmPosition = I;<br>
+  switch (*I) {<br>
+    default:<br>
+      return false;<br>
+    case 'h':<br>
+      ++I;<br>
+      if (I != E && *I == 'h') {<br>
+        ++I;<br>
+        lmKind = LengthModifier::AsChar;<br>
+      } else {<br>
+        lmKind = LengthModifier::AsShort;<br>
+      }<br>
+      break;<br>
+    case 'l':<br>
+      ++I;<br>
+      if (I != E && *I == 'l') {<br>
+        ++I;<br>
+        lmKind = LengthModifier::AsLongLong;<br>
+      } else {<br>
+        lmKind = LengthModifier::AsLong;<br>
+      }<br>
+      break;<br>
+    case 'j': lmKind = LengthModifier::AsIntMax;     ++I; break;<br>
+    case 'z': lmKind = LengthModifier::AsSizeT;      ++I; break;<br>
+    case 't': lmKind = LengthModifier::AsPtrDiff;    ++I; break;<br>
+    case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break;<br>
+    case 'q': lmKind = LengthModifier::AsQuad;       ++I; break;<br>
+    case 'a':<br>
+      if (IsScanf && !LO.C99 && !LO.CPlusPlus11) {<br>
+        // For scanf in C90, look at the next character to see if this should<br>
+        // be parsed as the GNU extension 'a' length modifier. If not, this<br>
+        // will be parsed as a conversion specifier.<br>
+        ++I;<br>
+        if (I != E && (*I == 's' || *I == 'S' || *I == '[')) {<br>
+          lmKind = LengthModifier::AsAllocate;<br>
+          break;<br>
+        }<br>
+        --I;<br>
+      }<br>
+      return false;<br>
+    case 'm':<br>
+      if (IsScanf) {<br>
+        lmKind = LengthModifier::AsMAllocate;<br>
+        ++I;<br>
+        break;<br>
+      }<br>
+      return false;<br>
+    // printf: AsInt64, AsInt32, AsInt3264<br>
+    // scanf:  AsInt64<br>
+    case 'I':<br>
+      if (I + 1 != E && I + 2 != E) {<br>
+        if (I[1] == '6' && I[2] == '4') {<br>
+          I += 3;<br>
+          lmKind = LengthModifier::AsInt64;<br>
+          break;<br>
+        }<br>
+        if (IsScanf)<br>
+          return false;<br>
+<br>
+        if (I[1] == '3' && I[2] == '2') {<br>
+          I += 3;<br>
+          lmKind = LengthModifier::AsInt32;<br>
+          break;<br>
+        }<br>
+      }<br>
+      ++I;<br>
+      lmKind = LengthModifier::AsInt3264;<br>
+      break;<br>
+    case 'w':<br>
+      lmKind = LengthModifier::AsWide; ++I; break;<br>
+  }<br>
+  LengthModifier lm(lmPosition, lmKind);<br>
+  FS.setLengthModifier(lm);<br>
+  return true;<br>
+}<br>
+<br>
+bool clang::analyze_format_string::ParseUTF8InvalidSpecifier(<br>
+    const char *SpecifierBegin, const char *FmtStrEnd, unsigned &Len) {<br>
+  if (SpecifierBegin + 1 >= FmtStrEnd)<br>
+    return false;<br>
+<br>
+  const llvm::UTF8 *SB =<br>
+      reinterpret_cast<const llvm::UTF8 *>(SpecifierBegin + 1);<br>
+  const llvm::UTF8 *SE = reinterpret_cast<const llvm::UTF8 *>(FmtStrEnd);<br>
+  const char FirstByte = *SB;<br>
+<br>
+  // If the invalid specifier is a multibyte UTF-8 string, return the<br>
+  // total length accordingly so that the conversion specifier can be<br>
+  // properly updated to reflect a complete UTF-8 specifier.<br>
+  unsigned NumBytes = llvm::getNumBytesForUTF8(FirstByte);<br>
+  if (NumBytes == 1)<br>
+    return false;<br>
+  if (SB + NumBytes > SE)<br>
+    return false;<br>
+<br>
+  Len = NumBytes + 1;<br>
+  return true;<br>
+}<br>
+<br>
+//===----------------------------------------------------------------------===//<br>
+// Methods on ArgType.<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+clang::analyze_format_string::ArgType::MatchKind<br>
+ArgType::matchesType(ASTContext &C, QualType argTy) const {<br>
+  if (Ptr) {<br>
+    // It has to be a pointer.<br>
+    const PointerType *PT = argTy->getAs<PointerType>();<br>
+    if (!PT)<br>
+      return NoMatch;<br>
+<br>
+    // We cannot write through a const qualified pointer.<br>
+    if (PT->getPointeeType().isConstQualified())<br>
+      return NoMatch;<br>
+<br>
+    argTy = PT->getPointeeType();<br>
+  }<br>
+<br>
+  switch (K) {<br>
+    case InvalidTy:<br>
+      llvm_unreachable("ArgType must be valid");<br>
+<br>
+    case UnknownTy:<br>
+      return Match;<br>
+<br>
+    case AnyCharTy: {<br>
+      if (const EnumType *ETy = argTy->getAs<EnumType>()) {<br>
+        // If the enum is incomplete we know nothing about the underlying type.<br>
+        // Assume that it's 'int'.<br>
+        if (!ETy->getDecl()->isComplete())<br>
+          return NoMatch;<br>
+        argTy = ETy->getDecl()->getIntegerType();<br>
+      }<br>
+<br>
+      if (const BuiltinType *BT = argTy->getAs<BuiltinType>())<br>
+        switch (BT->getKind()) {<br>
+          default:<br>
+            break;<br>
+          case BuiltinType::Char_S:<br>
+          case BuiltinType::SChar:<br>
+          case BuiltinType::UChar:<br>
+          case BuiltinType::Char_U:<br>
+            return Match;<br>
+        }<br>
+      return NoMatch;<br>
+    }<br>
+<br>
+    case SpecificTy: {<br>
+      if (const EnumType *ETy = argTy->getAs<EnumType>()) {<br>
+        // If the enum is incomplete we know nothing about the underlying type.<br>
+        // Assume that it's 'int'.<br>
+        if (!ETy->getDecl()->isComplete())<br>
+          argTy = C.IntTy;<br>
+        else<br>
+          argTy = ETy->getDecl()->getIntegerType();<br>
+      }<br>
+      argTy = C.getCanonicalType(argTy).getUnqualifiedType();<br>
+<br>
+      if (T == argTy)<br>
+        return Match;<br>
+      // Check for "compatible types".<br>
+      if (const BuiltinType *BT = argTy->getAs<BuiltinType>())<br>
+        switch (BT->getKind()) {<br>
+          default:<br>
+            break;<br>
+          case BuiltinType::Char_S:<br>
+          case BuiltinType::SChar:<br>
+          case BuiltinType::Char_U:<br>
+          case BuiltinType::UChar:<br>
+            return T == C.UnsignedCharTy || T == C.SignedCharTy ? Match<br>
+                                                                : NoMatch;<br>
+          case BuiltinType::Short:<br>
+            return T == C.UnsignedShortTy ? Match : NoMatch;<br>
+          case BuiltinType::UShort:<br>
+            return T == C.ShortTy ? Match : NoMatch;<br>
+          case BuiltinType::Int:<br>
+            return T == C.UnsignedIntTy ? Match : NoMatch;<br>
+          case BuiltinType::UInt:<br>
+            return T == C.IntTy ? Match : NoMatch;<br>
+          case BuiltinType::Long:<br>
+            return T == C.UnsignedLongTy ? Match : NoMatch;<br>
+          case BuiltinType::ULong:<br>
+            return T == C.LongTy ? Match : NoMatch;<br>
+          case BuiltinType::LongLong:<br>
+            return T == C.UnsignedLongLongTy ? Match : NoMatch;<br>
+          case BuiltinType::ULongLong:<br>
+            return T == C.LongLongTy ? Match : NoMatch;<br>
+        }<br>
+      return NoMatch;<br>
+    }<br>
+<br>
+    case CStrTy: {<br>
+      const PointerType *PT = argTy->getAs<PointerType>();<br>
+      if (!PT)<br>
+        return NoMatch;<br>
+      QualType pointeeTy = PT->getPointeeType();<br>
+      if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>())<br>
+        switch (BT->getKind()) {<br>
+          case BuiltinType::Void:<br>
+          case BuiltinType::Char_U:<br>
+          case BuiltinType::UChar:<br>
+          case BuiltinType::Char_S:<br>
+          case BuiltinType::SChar:<br>
+            return Match;<br>
+          default:<br>
+            break;<br>
+        }<br>
+<br>
+      return NoMatch;<br>
+    }<br>
+<br>
+    case WCStrTy: {<br>
+      const PointerType *PT = argTy->getAs<PointerType>();<br>
+      if (!PT)<br>
+        return NoMatch;<br>
+      QualType pointeeTy =<br>
+        C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType();<br>
+      return pointeeTy == C.getWideCharType() ? Match : NoMatch;<br>
+    }<br>
+<br>
+    case WIntTy: {<br>
+      QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType();<br>
+<br>
+      if (C.getCanonicalType(argTy).getUnqualifiedType() == WInt)<br>
+        return Match;<br>
+<br>
+      QualType PromoArg = argTy->isPromotableIntegerType()<br>
+                              ? C.getPromotedIntegerType(argTy)<br>
+                              : argTy;<br>
+      PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType();<br>
+<br>
+      // If the promoted argument is the corresponding signed type of the<br>
+      // wint_t type, then it should match.<br>
+      if (PromoArg->hasSignedIntegerRepresentation() &&<br>
+          C.getCorrespondingUnsignedType(PromoArg) == WInt)<br>
+        return Match;<br>
+<br>
+      return WInt == PromoArg ? Match : NoMatch;<br>
+    }<br>
+<br>
+    case CPointerTy:<br>
+      if (argTy->isVoidPointerType()) {<br>
+        return Match;<br>
+      } if (argTy->isPointerType() || argTy->isObjCObjectPointerType() ||<br>
+            argTy->isBlockPointerType() || argTy->isNullPtrType()) {<br>
+        return NoMatchPedantic;<br>
+      } else {<br>
+        return NoMatch;<br>
+      }<br>
+<br>
+    case ObjCPointerTy: {<br>
+      if (argTy->getAs<ObjCObjectPointerType>() ||<br>
+          argTy->getAs<BlockPointerType>())<br>
+        return Match;<br>
+<br>
+      // Handle implicit toll-free bridging.<br>
+      if (const PointerType *PT = argTy->getAs<PointerType>()) {<br>
+        // Things such as CFTypeRef are really just opaque pointers<br>
+        // to C structs representing CF types that can often be bridged<br>
+        // to Objective-C objects.  Since the compiler doesn't know which<br>
+        // structs can be toll-free bridged, we just accept them all.<br>
+        QualType pointee = PT->getPointeeType();<br>
+        if (pointee->getAsStructureType() || pointee->isVoidType())<br>
+          return Match;<br>
+      }<br>
+      return NoMatch;<br>
+    }<br>
+  }<br>
+<br>
+  llvm_unreachable("Invalid ArgType Kind!");<br>
+}<br>
+<br>
+QualType ArgType::getRepresentativeType(ASTContext &C) const {<br>
+  QualType Res;<br>
+  switch (K) {<br>
+    case InvalidTy:<br>
+      llvm_unreachable("No representative type for Invalid ArgType");<br>
+    case UnknownTy:<br>
+      llvm_unreachable("No representative type for Unknown ArgType");<br>
+    case AnyCharTy:<br>
+      Res = C.CharTy;<br>
+      break;<br>
+    case SpecificTy:<br>
+      Res = T;<br>
+      break;<br>
+    case CStrTy:<br>
+      Res = C.getPointerType(C.CharTy);<br>
+      break;<br>
+    case WCStrTy:<br>
+      Res = C.getPointerType(C.getWideCharType());<br>
+      break;<br>
+    case ObjCPointerTy:<br>
+      Res = C.ObjCBuiltinIdTy;<br>
+      break;<br>
+    case CPointerTy:<br>
+      Res = C.VoidPtrTy;<br>
+      break;<br>
+    case WIntTy: {<br>
+      Res = C.getWIntType();<br>
+      break;<br>
+    }<br>
+  }<br>
+<br>
+  if (Ptr)<br>
+    Res = C.getPointerType(Res);<br>
+  return Res;<br>
+}<br>
+<br>
+std::string ArgType::getRepresentativeTypeName(ASTContext &C) const {<br>
+  std::string S = getRepresentativeType(C).getAsString();<br>
+<br>
+  std::string Alias;<br>
+  if (Name) {<br>
+    // Use a specific name for this type, e.g. "size_t".<br>
+    Alias = Name;<br>
+    if (Ptr) {<br>
+      // If ArgType is actually a pointer to T, append an asterisk.<br>
+      Alias += (Alias[Alias.size()-1] == '*') ? "*" : " *";<br>
+    }<br>
+    // If Alias is the same as the underlying type, e.g. wchar_t, then drop it.<br>
+    if (S == Alias)<br>
+      Alias.clear();<br>
+  }<br>
+<br>
+  if (!Alias.empty())<br>
+    return std::string("'") + Alias + "' (aka '" + S + "')";<br>
+  return std::string("'") + S + "'";<br>
+}<br>
+<br>
+<br>
+//===----------------------------------------------------------------------===//<br>
+// Methods on OptionalAmount.<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+ArgType<br>
+analyze_format_string::OptionalAmount::getArgType(ASTContext &Ctx) const {<br>
+  return Ctx.IntTy;<br>
+}<br>
+<br>
+//===----------------------------------------------------------------------===//<br>
+// Methods on LengthModifier.<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+const char *<br>
+analyze_format_string::LengthModifier::toString() const {<br>
+  switch (kind) {<br>
+  case AsChar:<br>
+    return "hh";<br>
+  case AsShort:<br>
+    return "h";<br>
+  case AsLong: // or AsWideChar<br>
+    return "l";<br>
+  case AsLongLong:<br>
+    return "ll";<br>
+  case AsQuad:<br>
+    return "q";<br>
+  case AsIntMax:<br>
+    return "j";<br>
+  case AsSizeT:<br>
+    return "z";<br>
+  case AsPtrDiff:<br>
+    return "t";<br>
+  case AsInt32:<br>
+    return "I32";<br>
+  case AsInt3264:<br>
+    return "I";<br>
+  case AsInt64:<br>
+    return "I64";<br>
+  case AsLongDouble:<br>
+    return "L";<br>
+  case AsAllocate:<br>
+    return "a";<br>
+  case AsMAllocate:<br>
+    return "m";<br>
+  case AsWide:<br>
+    return "w";<br>
+  case None:<br>
+    return "";<br>
+  }<br>
+  return nullptr;<br>
+}<br>
+<br>
+//===----------------------------------------------------------------------===//<br>
+// Methods on ConversionSpecifier.<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+const char *ConversionSpecifier::toString() const {<br>
+  switch (kind) {<br>
+  case dArg: return "d";<br>
+  case DArg: return "D";<br>
+  case iArg: return "i";<br>
+  case oArg: return "o";<br>
+  case OArg: return "O";<br>
+  case uArg: return "u";<br>
+  case UArg: return "U";<br>
+  case xArg: return "x";<br>
+  case XArg: return "X";<br>
+  case fArg: return "f";<br>
+  case FArg: return "F";<br>
+  case eArg: return "e";<br>
+  case EArg: return "E";<br>
+  case gArg: return "g";<br>
+  case GArg: return "G";<br>
+  case aArg: return "a";<br>
+  case AArg: return "A";<br>
+  case cArg: return "c";<br>
+  case sArg: return "s";<br>
+  case pArg: return "p";<br>
+  case PArg:<br>
+    return "P";<br>
+  case nArg: return "n";<br>
+  case PercentArg:  return "%";<br>
+  case ScanListArg: return "[";<br>
+  case InvalidSpecifier: return nullptr;<br>
+<br>
+  // POSIX unicode extensions.<br>
+  case CArg: return "C";<br>
+  case SArg: return "S";<br>
+<br>
+  // Objective-C specific specifiers.<br>
+  case ObjCObjArg: return "@";<br>
+<br>
+  // FreeBSD kernel specific specifiers.<br>
+  case FreeBSDbArg: return "b";<br>
+  case FreeBSDDArg: return "D";<br>
+  case FreeBSDrArg: return "r";<br>
+  case FreeBSDyArg: return "y";<br>
+<br>
+  // GlibC specific specifiers.<br>
+  case PrintErrno: return "m";<br>
+<br>
+  // MS specific specifiers.<br>
+  case ZArg: return "Z";<br>
+  }<br>
+  return nullptr;<br>
+}<br>
+<br>
+Optional<ConversionSpecifier><br>
+ConversionSpecifier::getStandardSpecifier() const {<br>
+  ConversionSpecifier::Kind NewKind;<br>
+<br>
+  switch (getKind()) {<br>
+  default:<br>
+    return None;<br>
+  case DArg:<br>
+    NewKind = dArg;<br>
+    break;<br>
+  case UArg:<br>
+    NewKind = uArg;<br>
+    break;<br>
+  case OArg:<br>
+    NewKind = oArg;<br>
+    break;<br>
+  }<br>
+<br>
+  ConversionSpecifier FixedCS(*this);<br>
+  FixedCS.setKind(NewKind);<br>
+  return FixedCS;<br>
+}<br>
+<br>
+//===----------------------------------------------------------------------===//<br>
+// Methods on OptionalAmount.<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+void OptionalAmount::toString(raw_ostream &os) const {<br>
+  switch (hs) {<br>
+  case Invalid:<br>
+  case NotSpecified:<br>
+    return;<br>
+  case Arg:<br>
+    if (UsesDotPrefix)<br>
+        os << ".";<br>
+    if (usesPositionalArg())<br>
+      os << "*" << getPositionalArgIndex() << "$";<br>
+    else<br>
+      os << "*";<br>
+    break;<br>
+  case Constant:<br>
+    if (UsesDotPrefix)<br>
+        os << ".";<br>
+    os << amt;<br>
+    break;<br>
+  }<br>
+}<br>
+<br>
+bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target) const {<br>
+  switch (LM.getKind()) {<br>
+    case LengthModifier::None:<br>
+      return true;<br>
+<br>
+    // Handle most integer flags<br>
+    case LengthModifier::AsShort:<br>
+      if (Target.getTriple().isOSMSVCRT()) {<br>
+        switch (CS.getKind()) {<br>
+          case ConversionSpecifier::cArg:<br>
+          case ConversionSpecifier::CArg:<br>
+          case ConversionSpecifier::sArg:<br>
+          case ConversionSpecifier::SArg:<br>
+          case ConversionSpecifier::ZArg:<br>
+            return true;<br>
+          default:<br>
+            break;<br>
+        }<br>
+      }<br>
+      LLVM_FALLTHROUGH;<br>
+    case LengthModifier::AsChar:<br>
+    case LengthModifier::AsLongLong:<br>
+    case LengthModifier::AsQuad:<br>
+    case LengthModifier::AsIntMax:<br>
+    case LengthModifier::AsSizeT:<br>
+    case LengthModifier::AsPtrDiff:<br>
+      switch (CS.getKind()) {<br>
+        case ConversionSpecifier::dArg:<br>
+        case ConversionSpecifier::DArg:<br>
+        case ConversionSpecifier::iArg:<br>
+        case ConversionSpecifier::oArg:<br>
+        case ConversionSpecifier::OArg:<br>
+        case ConversionSpecifier::uArg:<br>
+        case ConversionSpecifier::UArg:<br>
+        case ConversionSpecifier::xArg:<br>
+        case ConversionSpecifier::XArg:<br>
+        case ConversionSpecifier::nArg:<br>
+          return true;<br>
+        case ConversionSpecifier::FreeBSDrArg:<br>
+        case ConversionSpecifier::FreeBSDyArg:<br>
+          return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS4();<br>
+        default:<br>
+          return false;<br>
+      }<br>
+<br>
+    // Handle 'l' flag<br>
+    case LengthModifier::AsLong: // or AsWideChar<br>
+      switch (CS.getKind()) {<br>
+        case ConversionSpecifier::dArg:<br>
+        case ConversionSpecifier::DArg:<br>
+        case ConversionSpecifier::iArg:<br>
+        case ConversionSpecifier::oArg:<br>
+        case ConversionSpecifier::OArg:<br>
+        case ConversionSpecifier::uArg:<br>
+        case ConversionSpecifier::UArg:<br>
+        case ConversionSpecifier::xArg:<br>
+        case ConversionSpecifier::XArg:<br>
+        case ConversionSpecifier::aArg:<br>
+        case ConversionSpecifier::AArg:<br>
+        case ConversionSpecifier::fArg:<br>
+        case ConversionSpecifier::FArg:<br>
+        case ConversionSpecifier::eArg:<br>
+        case ConversionSpecifier::EArg:<br>
+        case ConversionSpecifier::gArg:<br>
+        case ConversionSpecifier::GArg:<br>
+        case ConversionSpecifier::nArg:<br>
+        case ConversionSpecifier::cArg:<br>
+        case ConversionSpecifier::sArg:<br>
+        case ConversionSpecifier::ScanListArg:<br>
+        case ConversionSpecifier::ZArg:<br>
+          return true;<br>
+        case ConversionSpecifier::FreeBSDrArg:<br>
+        case ConversionSpecifier::FreeBSDyArg:<br>
+          return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS4();<br>
+        default:<br>
+          return false;<br>
+      }<br>
+<br>
+    case LengthModifier::AsLongDouble:<br>
+      switch (CS.getKind()) {<br>
+        case ConversionSpecifier::aArg:<br>
+        case ConversionSpecifier::AArg:<br>
+        case ConversionSpecifier::fArg:<br>
+        case ConversionSpecifier::FArg:<br>
+        case ConversionSpecifier::eArg:<br>
+        case ConversionSpecifier::EArg:<br>
+        case ConversionSpecifier::gArg:<br>
+        case ConversionSpecifier::GArg:<br>
+          return true;<br>
+        // GNU libc extension.<br>
+        case ConversionSpecifier::dArg:<br>
+        case ConversionSpecifier::iArg:<br>
+        case ConversionSpecifier::oArg:<br>
+        case ConversionSpecifier::uArg:<br>
+        case ConversionSpecifier::xArg:<br>
+        case ConversionSpecifier::XArg:<br>
+          return !Target.getTriple().isOSDarwin() &&<br>
+                 !Target.getTriple().isOSWindows();<br>
+        default:<br>
+          return false;<br>
+      }<br>
+<br>
+    case LengthModifier::AsAllocate:<br>
+      switch (CS.getKind()) {<br>
+        case ConversionSpecifier::sArg:<br>
+        case ConversionSpecifier::SArg:<br>
+        case ConversionSpecifier::ScanListArg:<br>
+          return true;<br>
+        default:<br>
+          return false;<br>
+      }<br>
+<br>
+    case LengthModifier::AsMAllocate:<br>
+      switch (CS.getKind()) {<br>
+        case ConversionSpecifier::cArg:<br>
+        case ConversionSpecifier::CArg:<br>
+        case ConversionSpecifier::sArg:<br>
+        case ConversionSpecifier::SArg:<br>
+        case ConversionSpecifier::ScanListArg:<br>
+          return true;<br>
+        default:<br>
+          return false;<br>
+      }<br>
+    case LengthModifier::AsInt32:<br>
+    case LengthModifier::AsInt3264:<br>
+    case LengthModifier::AsInt64:<br>
+      switch (CS.getKind()) {<br>
+        case ConversionSpecifier::dArg:<br>
+        case ConversionSpecifier::iArg:<br>
+        case ConversionSpecifier::oArg:<br>
+        case ConversionSpecifier::uArg:<br>
+        case ConversionSpecifier::xArg:<br>
+        case ConversionSpecifier::XArg:<br>
+          return Target.getTriple().isOSMSVCRT();<br>
+        default:<br>
+          return false;<br>
+      }<br>
+    case LengthModifier::AsWide:<br>
+      switch (CS.getKind()) {<br>
+        case ConversionSpecifier::cArg:<br>
+        case ConversionSpecifier::CArg:<br>
+        case ConversionSpecifier::sArg:<br>
+        case ConversionSpecifier::SArg:<br>
+        case ConversionSpecifier::ZArg:<br>
+          return Target.getTriple().isOSMSVCRT();<br>
+        default:<br>
+          return false;<br>
+      }<br>
+  }<br>
+  llvm_unreachable("Invalid LengthModifier Kind!");<br>
+}<br>
+<br>
+bool FormatSpecifier::hasStandardLengthModifier() const {<br>
+  switch (LM.getKind()) {<br>
+    case LengthModifier::None:<br>
+    case LengthModifier::AsChar:<br>
+    case LengthModifier::AsShort:<br>
+    case LengthModifier::AsLong:<br>
+    case LengthModifier::AsLongLong:<br>
+    case LengthModifier::AsIntMax:<br>
+    case LengthModifier::AsSizeT:<br>
+    case LengthModifier::AsPtrDiff:<br>
+    case LengthModifier::AsLongDouble:<br>
+      return true;<br>
+    case LengthModifier::AsAllocate:<br>
+    case LengthModifier::AsMAllocate:<br>
+    case LengthModifier::AsQuad:<br>
+    case LengthModifier::AsInt32:<br>
+    case LengthModifier::AsInt3264:<br>
+    case LengthModifier::AsInt64:<br>
+    case LengthModifier::AsWide:<br>
+      return false;<br>
+  }<br>
+  llvm_unreachable("Invalid LengthModifier Kind!");<br>
+}<br>
+<br>
+bool FormatSpecifier::hasStandardConversionSpecifier(<br>
+    const LangOptions &LangOpt) const {<br>
+  switch (CS.getKind()) {<br>
+    case ConversionSpecifier::cArg:<br>
+    case ConversionSpecifier::dArg:<br>
+    case ConversionSpecifier::iArg:<br>
+    case ConversionSpecifier::oArg:<br>
+    case ConversionSpecifier::uArg:<br>
+    case ConversionSpecifier::xArg:<br>
+    case ConversionSpecifier::XArg:<br>
+    case ConversionSpecifier::fArg:<br>
+    case ConversionSpecifier::FArg:<br>
+    case ConversionSpecifier::eArg:<br>
+    case ConversionSpecifier::EArg:<br>
+    case ConversionSpecifier::gArg:<br>
+    case ConversionSpecifier::GArg:<br>
+    case ConversionSpecifier::aArg:<br>
+    case ConversionSpecifier::AArg:<br>
+    case ConversionSpecifier::sArg:<br>
+    case ConversionSpecifier::pArg:<br>
+    case ConversionSpecifier::nArg:<br>
+    case ConversionSpecifier::ObjCObjArg:<br>
+    case ConversionSpecifier::ScanListArg:<br>
+    case ConversionSpecifier::PercentArg:<br>
+    case ConversionSpecifier::PArg:<br>
+      return true;<br>
+    case ConversionSpecifier::CArg:<br>
+    case ConversionSpecifier::SArg:<br>
+      return LangOpt.ObjC;<br>
+    case ConversionSpecifier::InvalidSpecifier:<br>
+    case ConversionSpecifier::FreeBSDbArg:<br>
+    case ConversionSpecifier::FreeBSDDArg:<br>
+    case ConversionSpecifier::FreeBSDrArg:<br>
+    case ConversionSpecifier::FreeBSDyArg:<br>
+    case ConversionSpecifier::PrintErrno:<br>
+    case ConversionSpecifier::DArg:<br>
+    case ConversionSpecifier::OArg:<br>
+    case ConversionSpecifier::UArg:<br>
+    case ConversionSpecifier::ZArg:<br>
+      return false;<br>
+  }<br>
+  llvm_unreachable("Invalid ConversionSpecifier Kind!");<br>
+}<br>
+<br>
+bool FormatSpecifier::hasStandardLengthConversionCombination() const {<br>
+  if (LM.getKind() == LengthModifier::AsLongDouble) {<br>
+    switch(CS.getKind()) {<br>
+        case ConversionSpecifier::dArg:<br>
+        case ConversionSpecifier::iArg:<br>
+        case ConversionSpecifier::oArg:<br>
+        case ConversionSpecifier::uArg:<br>
+        case ConversionSpecifier::xArg:<br>
+        case ConversionSpecifier::XArg:<br>
+          return false;<br>
+        default:<br>
+          return true;<br>
+    }<br>
+  }<br>
+  return true;<br>
+}<br>
+<br>
+Optional<LengthModifier> FormatSpecifier::getCorrectedLengthModifier() const {<br>
+  if (CS.isAnyIntArg() || CS.getKind() == ConversionSpecifier::nArg) {<br>
+    if (LM.getKind() == LengthModifier::AsLongDouble ||<br>
+        LM.getKind() == LengthModifier::AsQuad) {<br>
+      LengthModifier FixedLM(LM);<br>
+      FixedLM.setKind(LengthModifier::AsLongLong);<br>
+      return FixedLM;<br>
+    }<br>
+  }<br>
+<br>
+  return None;<br>
+}<br>
+<br>
+bool FormatSpecifier::namedTypeToLengthModifier(QualType QT,<br>
+                                                LengthModifier &LM) {<br>
+  assert(isa<TypedefType>(QT) && "Expected a TypedefType");<br>
+  const TypedefNameDecl *Typedef = cast<TypedefType>(QT)->getDecl();<br>
+<br>
+  for (;;) {<br>
+    const IdentifierInfo *Identifier = Typedef->getIdentifier();<br>
+    if (Identifier->getName() == "size_t") {<br>
+      LM.setKind(LengthModifier::AsSizeT);<br>
+      return true;<br>
+    } else if (Identifier->getName() == "ssize_t") {<br>
+      // Not C99, but common in Unix.<br>
+      LM.setKind(LengthModifier::AsSizeT);<br>
+      return true;<br>
+    } else if (Identifier->getName() == "intmax_t") {<br>
+      LM.setKind(LengthModifier::AsIntMax);<br>
+      return true;<br>
+    } else if (Identifier->getName() == "uintmax_t") {<br>
+      LM.setKind(LengthModifier::AsIntMax);<br>
+      return true;<br>
+    } else if (Identifier->getName() == "ptrdiff_t") {<br>
+      LM.setKind(LengthModifier::AsPtrDiff);<br>
+      return true;<br>
+    }<br>
+<br>
+    QualType T = Typedef->getUnderlyingType();<br>
+    if (!isa<TypedefType>(T))<br>
+      break;<br>
+<br>
+    Typedef = cast<TypedefType>(T)->getDecl();<br>
+  }<br>
+  return false;<br>
+}<br>
<br>
Added: cfe/trunk/lib/AST/FormatStringParsing.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/FormatStringParsing.h?rev=345971&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/FormatStringParsing.h?rev=345971&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/FormatStringParsing.h (added)<br>
+++ cfe/trunk/lib/AST/FormatStringParsing.h Fri Nov  2 06:14:11 2018<br>
@@ -0,0 +1,79 @@<br>
+#ifndef LLVM_CLANG_LIB_ANALYSIS_FORMATSTRINGPARSING_H<br>
+#define LLVM_CLANG_LIB_ANALYSIS_FORMATSTRINGPARSING_H<br>
+<br>
+#include "clang/AST/ASTContext.h"<br>
+#include "clang/AST/Type.h"<br>
+#include "clang/AST/FormatString.h"<br>
+<br>
+namespace clang {<br>
+<br>
+class LangOptions;<br>
+<br>
+template <typename T><br>
+class UpdateOnReturn {<br>
+  T &ValueToUpdate;<br>
+  const T &ValueToCopy;<br>
+public:<br>
+  UpdateOnReturn(T &valueToUpdate, const T &valueToCopy)<br>
+    : ValueToUpdate(valueToUpdate), ValueToCopy(valueToCopy) {}<br>
+<br>
+  ~UpdateOnReturn() {<br>
+    ValueToUpdate = ValueToCopy;<br>
+  }<br>
+};<br>
+<br>
+namespace analyze_format_string {<br>
+<br>
+OptionalAmount ParseAmount(const char *&Beg, const char *E);<br>
+OptionalAmount ParseNonPositionAmount(const char *&Beg, const char *E,<br>
+                                      unsigned &argIndex);<br>
+<br>
+OptionalAmount ParsePositionAmount(FormatStringHandler &H,<br>
+                                   const char *Start, const char *&Beg,<br>
+                                   const char *E, PositionContext p);<br>
+<br>
+bool ParseFieldWidth(FormatStringHandler &H,<br>
+                     FormatSpecifier &CS,<br>
+                     const char *Start, const char *&Beg, const char *E,<br>
+                     unsigned *argIndex);<br>
+<br>
+bool ParseArgPosition(FormatStringHandler &H,<br>
+                      FormatSpecifier &CS, const char *Start,<br>
+                      const char *&Beg, const char *E);<br>
+<br>
+/// Returns true if a LengthModifier was parsed and installed in the<br>
+/// FormatSpecifier& argument, and false otherwise.<br>
+bool ParseLengthModifier(FormatSpecifier &FS, const char *&Beg, const char *E,<br>
+                         const LangOptions &LO, bool IsScanf = false);<br>
+<br>
+/// Returns true if the invalid specifier in \p SpecifierBegin is a UTF-8<br>
+/// string; check that it won't go further than \p FmtStrEnd and write<br>
+/// up the total size in \p Len.<br>
+bool ParseUTF8InvalidSpecifier(const char *SpecifierBegin,<br>
+                               const char *FmtStrEnd, unsigned &Len);<br>
+<br>
+template <typename T> class SpecifierResult {<br>
+  T FS;<br>
+  const char *Start;<br>
+  bool Stop;<br>
+public:<br>
+  SpecifierResult(bool stop = false)<br>
+  : Start(nullptr), Stop(stop) {}<br>
+  SpecifierResult(const char *start,<br>
+                  const T &fs)<br>
+  : FS(fs), Start(start), Stop(false) {}<br>
+<br>
+  const char *getStart() const { return Start; }<br>
+  bool shouldStop() const { return Stop; }<br>
+  bool hasValue() const { return Start != nullptr; }<br>
+  const T &getValue() const {<br>
+    assert(hasValue());<br>
+    return FS;<br>
+  }<br>
+  const T &getValue() { return FS; }<br>
+};<br>
+<br>
+} // end analyze_format_string namespace<br>
+} // end clang namespace<br>
+<br>
+#endif<br>
<br>
Added: cfe/trunk/lib/AST/OSLog.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/OSLog.cpp?rev=345971&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/OSLog.cpp?rev=345971&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/OSLog.cpp (added)<br>
+++ cfe/trunk/lib/AST/OSLog.cpp Fri Nov  2 06:14:11 2018<br>
@@ -0,0 +1,203 @@<br>
+// TODO: header template<br>
+<br>
+#include "clang/AST/OSLog.h"<br>
+#include "clang/AST/Attr.h"<br>
+#include "clang/AST/Decl.h"<br>
+#include "clang/AST/DeclCXX.h"<br>
+#include "clang/AST/ExprObjC.h"<br>
+#include "clang/AST/FormatString.h"<br>
+#include "clang/Basic/Builtins.h"<br>
+#include "llvm/ADT/SmallBitVector.h"<br>
+<br>
+using namespace clang;<br>
+<br>
+using clang::analyze_os_log::OSLogBufferItem;<br>
+using clang::analyze_os_log::OSLogBufferLayout;<br>
+<br>
+namespace {<br>
+class OSLogFormatStringHandler<br>
+    : public analyze_format_string::FormatStringHandler {<br>
+private:<br>
+  struct ArgData {<br>
+    const Expr *E = nullptr;<br>
+    Optional<OSLogBufferItem::Kind> Kind;<br>
+    Optional<unsigned> Size;<br>
+    Optional<const Expr *> Count;<br>
+    Optional<const Expr *> Precision;<br>
+    Optional<const Expr *> FieldWidth;<br>
+    unsigned char Flags = 0;<br>
+  };<br>
+  SmallVector<ArgData, 4> ArgsData;<br>
+  ArrayRef<const Expr *> Args;<br>
+<br>
+  OSLogBufferItem::Kind<br>
+  getKind(analyze_format_string::ConversionSpecifier::Kind K) {<br>
+    switch (K) {<br>
+    case clang::analyze_format_string::ConversionSpecifier::sArg: // "%s"<br>
+      return OSLogBufferItem::StringKind;<br>
+    case clang::analyze_format_string::ConversionSpecifier::SArg: // "%S"<br>
+      return OSLogBufferItem::WideStringKind;<br>
+    case clang::analyze_format_string::ConversionSpecifier::PArg: { // "%P"<br>
+      return OSLogBufferItem::PointerKind;<br>
+    case clang::analyze_format_string::ConversionSpecifier::ObjCObjArg: // "%@"<br>
+      return OSLogBufferItem::ObjCObjKind;<br>
+    case clang::analyze_format_string::ConversionSpecifier::PrintErrno: // "%m"<br>
+      return OSLogBufferItem::ErrnoKind;<br>
+    default:<br>
+      return OSLogBufferItem::ScalarKind;<br>
+    }<br>
+    }<br>
+  }<br>
+<br>
+public:<br>
+  OSLogFormatStringHandler(ArrayRef<const Expr *> Args) : Args(Args) {<br>
+    ArgsData.reserve(Args.size());<br>
+  }<br>
+<br>
+  virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,<br>
+                                     const char *StartSpecifier,<br>
+                                     unsigned SpecifierLen) {<br>
+    if (!FS.consumesDataArgument() &&<br>
+        FS.getConversionSpecifier().getKind() !=<br>
+            clang::analyze_format_string::ConversionSpecifier::PrintErrno)<br>
+      return true;<br>
+<br>
+    ArgsData.emplace_back();<br>
+    unsigned ArgIndex = FS.getArgIndex();<br>
+    if (ArgIndex < Args.size())<br>
+      ArgsData.back().E = Args[ArgIndex];<br>
+<br>
+    // First get the Kind<br>
+    ArgsData.back().Kind = getKind(FS.getConversionSpecifier().getKind());<br>
+    if (ArgsData.back().Kind != OSLogBufferItem::ErrnoKind &&<br>
+        !ArgsData.back().E) {<br>
+      // missing argument<br>
+      ArgsData.pop_back();<br>
+      return false;<br>
+    }<br>
+<br>
+    switch (FS.getConversionSpecifier().getKind()) {<br>
+    case clang::analyze_format_string::ConversionSpecifier::sArg:   // "%s"<br>
+    case clang::analyze_format_string::ConversionSpecifier::SArg: { // "%S"<br>
+      auto &precision = FS.getPrecision();<br>
+      switch (precision.getHowSpecified()) {<br>
+      case clang::analyze_format_string::OptionalAmount::NotSpecified: // "%s"<br>
+        break;<br>
+      case clang::analyze_format_string::OptionalAmount::Constant: // "%.16s"<br>
+        ArgsData.back().Size = precision.getConstantAmount();<br>
+        break;<br>
+      case clang::analyze_format_string::OptionalAmount::Arg: // "%.*s"<br>
+        ArgsData.back().Count = Args[precision.getArgIndex()];<br>
+        break;<br>
+      case clang::analyze_format_string::OptionalAmount::Invalid:<br>
+        return false;<br>
+      }<br>
+      break;<br>
+    }<br>
+    case clang::analyze_format_string::ConversionSpecifier::PArg: { // "%P"<br>
+      auto &precision = FS.getPrecision();<br>
+      switch (precision.getHowSpecified()) {<br>
+      case clang::analyze_format_string::OptionalAmount::NotSpecified: // "%P"<br>
+        return false; // length must be supplied with pointer format specifier<br>
+      case clang::analyze_format_string::OptionalAmount::Constant: // "%.16P"<br>
+        ArgsData.back().Size = precision.getConstantAmount();<br>
+        break;<br>
+      case clang::analyze_format_string::OptionalAmount::Arg: // "%.*P"<br>
+        ArgsData.back().Count = Args[precision.getArgIndex()];<br>
+        break;<br>
+      case clang::analyze_format_string::OptionalAmount::Invalid:<br>
+        return false;<br>
+      }<br>
+      break;<br>
+    }<br>
+    default:<br>
+      if (FS.getPrecision().hasDataArgument()) {<br>
+        ArgsData.back().Precision = Args[FS.getPrecision().getArgIndex()];<br>
+      }<br>
+      break;<br>
+    }<br>
+    if (FS.getFieldWidth().hasDataArgument()) {<br>
+      ArgsData.back().FieldWidth = Args[FS.getFieldWidth().getArgIndex()];<br>
+    }<br>
+<br>
+    if (FS.isPrivate()) {<br>
+      ArgsData.back().Flags |= OSLogBufferItem::IsPrivate;<br>
+    }<br>
+    if (FS.isPublic()) {<br>
+      ArgsData.back().Flags |= OSLogBufferItem::IsPublic;<br>
+    }<br>
+    return true;<br>
+  }<br>
+<br>
+  void computeLayout(ASTContext &Ctx, OSLogBufferLayout &Layout) const {<br>
+    Layout.Items.clear();<br>
+    for (auto &Data : ArgsData) {<br>
+      if (Data.FieldWidth) {<br>
+        CharUnits Size = Ctx.getTypeSizeInChars((*Data.FieldWidth)->getType());<br>
+        Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, *Data.FieldWidth,<br>
+                                  Size, 0);<br>
+      }<br>
+      if (Data.Precision) {<br>
+        CharUnits Size = Ctx.getTypeSizeInChars((*Data.Precision)->getType());<br>
+        Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, *Data.Precision,<br>
+                                  Size, 0);<br>
+      }<br>
+      if (Data.Count) {<br>
+        // "%.*P" has an extra "count" that we insert before the argument.<br>
+        CharUnits Size = Ctx.getTypeSizeInChars((*Data.Count)->getType());<br>
+        Layout.Items.emplace_back(OSLogBufferItem::CountKind, *Data.Count, Size,<br>
+                                  0);<br>
+      }<br>
+      if (Data.Size)<br>
+        Layout.Items.emplace_back(Ctx, CharUnits::fromQuantity(*Data.Size),<br>
+                                  Data.Flags);<br>
+      if (Data.Kind) {<br>
+        CharUnits Size;<br>
+        if (*Data.Kind == OSLogBufferItem::ErrnoKind)<br>
+          Size = CharUnits::Zero();<br>
+        else<br>
+          Size = Ctx.getTypeSizeInChars(Data.E->getType());<br>
+        Layout.Items.emplace_back(*Data.Kind, Data.E, Size, Data.Flags);<br>
+      } else {<br>
+        auto Size = Ctx.getTypeSizeInChars(Data.E->getType());<br>
+        Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, Data.E, Size,<br>
+                                  Data.Flags);<br>
+      }<br>
+    }<br>
+  }<br>
+};<br>
+} // end anonymous namespace<br>
+<br>
+bool clang::analyze_os_log::computeOSLogBufferLayout(<br>
+    ASTContext &Ctx, const CallExpr *E, OSLogBufferLayout &Layout) {<br>
+  ArrayRef<const Expr *> Args(E->getArgs(), E->getArgs() + E->getNumArgs());<br>
+<br>
+  const Expr *StringArg;<br>
+  ArrayRef<const Expr *> VarArgs;<br>
+  switch (E->getBuiltinCallee()) {<br>
+  case Builtin::BI__builtin_os_log_format_buffer_size:<br>
+    assert(E->getNumArgs() >= 1 &&<br>
+           "__builtin_os_log_format_buffer_size takes at least 1 argument");<br>
+    StringArg = E->getArg(0);<br>
+    VarArgs = Args.slice(1);<br>
+    break;<br>
+  case Builtin::BI__builtin_os_log_format:<br>
+    assert(E->getNumArgs() >= 2 &&<br>
+           "__builtin_os_log_format takes at least 2 arguments");<br>
+    StringArg = E->getArg(1);<br>
+    VarArgs = Args.slice(2);<br>
+    break;<br>
+  default:<br>
+    llvm_unreachable("non-os_log builtin passed to computeOSLogBufferLayout");<br>
+  }<br>
+<br>
+  const StringLiteral *Lit = cast<StringLiteral>(StringArg->IgnoreParenCasts());<br>
+  assert(Lit && (Lit->isAscii() || Lit->isUTF8()));<br>
+  StringRef Data = Lit->getString();<br>
+  OSLogFormatStringHandler H(VarArgs);<br>
+  ParsePrintfString(H, Data.begin(), Data.end(), Ctx.getLangOpts(),<br>
+                    Ctx.getTargetInfo(), /*isFreeBSDKPrintf*/ false);<br>
+<br>
+  H.computeLayout(Ctx, Layout);<br>
+  return true;<br>
+}<br>
<br>
Added: cfe/trunk/lib/AST/PrintfFormatString.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/PrintfFormatString.cpp?rev=345971&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/PrintfFormatString.cpp?rev=345971&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/PrintfFormatString.cpp (added)<br>
+++ cfe/trunk/lib/AST/PrintfFormatString.cpp Fri Nov  2 06:14:11 2018<br>
@@ -0,0 +1,1029 @@<br>
+//== PrintfFormatString.cpp - Analysis of printf format strings --*- C++ -*-==//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// Handling of format string in printf and friends.  The structure of format<br>
+// strings for fprintf() are described in C99 7.19.6.1.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "clang/AST/FormatString.h"<br>
+#include "clang/AST/OSLog.h"<br>
+#include "FormatStringParsing.h"<br>
+#include "clang/Basic/TargetInfo.h"<br>
+<br>
+using clang::analyze_format_string::ArgType;<br>
+using clang::analyze_format_string::FormatStringHandler;<br>
+using clang::analyze_format_string::LengthModifier;<br>
+using clang::analyze_format_string::OptionalAmount;<br>
+using clang::analyze_format_string::ConversionSpecifier;<br>
+using clang::analyze_printf::PrintfSpecifier;<br>
+<br>
+using namespace clang;<br>
+<br>
+typedef clang::analyze_format_string::SpecifierResult<PrintfSpecifier><br>
+        PrintfSpecifierResult;<br>
+<br>
+//===----------------------------------------------------------------------===//<br>
+// Methods for parsing format strings.<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+using analyze_format_string::ParseNonPositionAmount;<br>
+<br>
+static bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS,<br>
+                           const char *Start, const char *&Beg, const char *E,<br>
+                           unsigned *argIndex) {<br>
+  if (argIndex) {<br>
+    FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex));<br>
+  } else {<br>
+    const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E,<br>
+                                           analyze_format_string::PrecisionPos);<br>
+    if (Amt.isInvalid())<br>
+      return true;<br>
+    FS.setPrecision(Amt);<br>
+  }<br>
+  return false;<br>
+}<br>
+<br>
+static bool ParseObjCFlags(FormatStringHandler &H, PrintfSpecifier &FS,<br>
+                           const char *FlagBeg, const char *E, bool Warn) {<br>
+   StringRef Flag(FlagBeg, E - FlagBeg);<br>
+   // Currently there is only one flag.<br>
+   if (Flag == "tt") {<br>
+     FS.setHasObjCTechnicalTerm(FlagBeg);<br>
+     return false;<br>
+   }<br>
+   // Handle either the case of no flag or an invalid flag.<br>
+   if (Warn) {<br>
+     if (Flag == "")<br>
+       H.HandleEmptyObjCModifierFlag(FlagBeg, E  - FlagBeg);<br>
+     else<br>
+       H.HandleInvalidObjCModifierFlag(FlagBeg, E  - FlagBeg);<br>
+   }<br>
+   return true;<br>
+}<br>
+<br>
+static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,<br>
+                                                  const char *&Beg,<br>
+                                                  const char *E,<br>
+                                                  unsigned &argIndex,<br>
+                                                  const LangOptions &LO,<br>
+                                                  const TargetInfo &Target,<br>
+                                                  bool Warn,<br>
+                                                  bool isFreeBSDKPrintf) {<br>
+<br>
+  using namespace clang::analyze_format_string;<br>
+  using namespace clang::analyze_printf;<br>
+<br>
+  const char *I = Beg;<br>
+  const char *Start = nullptr;<br>
+  UpdateOnReturn <const char*> UpdateBeg(Beg, I);<br>
+<br>
+  // Look for a '%' character that indicates the start of a format specifier.<br>
+  for ( ; I != E ; ++I) {<br>
+    char c = *I;<br>
+    if (c == '\0') {<br>
+      // Detect spurious null characters, which are likely errors.<br>
+      H.HandleNullChar(I);<br>
+      return true;<br>
+    }<br>
+    if (c == '%') {<br>
+      Start = I++;  // Record the start of the format specifier.<br>
+      break;<br>
+    }<br>
+  }<br>
+<br>
+  // No format specifier found?<br>
+  if (!Start)<br>
+    return false;<br>
+<br>
+  if (I == E) {<br>
+    // No more characters left?<br>
+    if (Warn)<br>
+      H.HandleIncompleteSpecifier(Start, E - Start);<br>
+    return true;<br>
+  }<br>
+<br>
+  PrintfSpecifier FS;<br>
+  if (ParseArgPosition(H, FS, Start, I, E))<br>
+    return true;<br>
+<br>
+  if (I == E) {<br>
+    // No more characters left?<br>
+    if (Warn)<br>
+      H.HandleIncompleteSpecifier(Start, E - Start);<br>
+    return true;<br>
+  }<br>
+<br>
+  if (*I == '{') {<br>
+    ++I;<br>
+    unsigned char PrivacyFlags = 0;<br>
+    StringRef MatchedStr;<br>
+<br>
+    do {<br>
+      StringRef Str(I, E - I);<br>
+      std::string Match = "^[\t\n\v\f\r ]*(private|public)[\t\n\v\f\r ]*(,|})";<br>
+      llvm::Regex R(Match);<br>
+      SmallVector<StringRef, 2> Matches;<br>
+<br>
+      if (R.match(Str, &Matches)) {<br>
+        MatchedStr = Matches[1];<br>
+        I += Matches[0].size();<br>
+<br>
+        // Set the privacy flag if the privacy annotation in the<br>
+        // comma-delimited segment is at least as strict as the privacy<br>
+        // annotations in previous comma-delimited segments.<br>
+        if (MatchedStr.equals("private"))<br>
+          PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPrivate;<br>
+        else if (PrivacyFlags == 0 && MatchedStr.equals("public"))<br>
+          PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPublic;<br>
+      } else {<br>
+        size_t CommaOrBracePos =<br>
+            Str.find_if([](char c) { return c == ',' || c == '}'; });<br>
+<br>
+        if (CommaOrBracePos == StringRef::npos) {<br>
+          // Neither a comma nor the closing brace was found.<br>
+          if (Warn)<br>
+            H.HandleIncompleteSpecifier(Start, E - Start);<br>
+          return true;<br>
+        }<br>
+<br>
+        I += CommaOrBracePos + 1;<br>
+      }<br>
+      // Continue until the closing brace is found.<br>
+    } while (*(I - 1) == ',');<br>
+<br>
+    // Set the privacy flag.<br>
+    switch (PrivacyFlags) {<br>
+    case 0:<br>
+      break;<br>
+    case clang::analyze_os_log::OSLogBufferItem::IsPrivate:<br>
+      FS.setIsPrivate(MatchedStr.data());<br>
+      break;<br>
+    case clang::analyze_os_log::OSLogBufferItem::IsPublic:<br>
+      FS.setIsPublic(MatchedStr.data());<br>
+      break;<br>
+    default:<br>
+      llvm_unreachable("Unexpected privacy flag value");<br>
+    }<br>
+  }<br>
+<br>
+  // Look for flags (if any).<br>
+  bool hasMore = true;<br>
+  for ( ; I != E; ++I) {<br>
+    switch (*I) {<br>
+      default: hasMore = false; break;<br>
+      case '\'':<br>
+        // FIXME: POSIX specific.  Always accept?<br>
+        FS.setHasThousandsGrouping(I);<br>
+        break;<br>
+      case '-': FS.setIsLeftJustified(I); break;<br>
+      case '+': FS.setHasPlusPrefix(I); break;<br>
+      case ' ': FS.setHasSpacePrefix(I); break;<br>
+      case '#': FS.setHasAlternativeForm(I); break;<br>
+      case '0': FS.setHasLeadingZeros(I); break;<br>
+    }<br>
+    if (!hasMore)<br>
+      break;<br>
+  }<br>
+<br>
+  if (I == E) {<br>
+    // No more characters left?<br>
+    if (Warn)<br>
+      H.HandleIncompleteSpecifier(Start, E - Start);<br>
+    return true;<br>
+  }<br>
+<br>
+  // Look for the field width (if any).<br>
+  if (ParseFieldWidth(H, FS, Start, I, E,<br>
+                      FS.usesPositionalArg() ? nullptr : &argIndex))<br>
+    return true;<br>
+<br>
+  if (I == E) {<br>
+    // No more characters left?<br>
+    if (Warn)<br>
+      H.HandleIncompleteSpecifier(Start, E - Start);<br>
+    return true;<br>
+  }<br>
+<br>
+  // Look for the precision (if any).<br>
+  if (*I == '.') {<br>
+    ++I;<br>
+    if (I == E) {<br>
+      if (Warn)<br>
+        H.HandleIncompleteSpecifier(Start, E - Start);<br>
+      return true;<br>
+    }<br>
+<br>
+    if (ParsePrecision(H, FS, Start, I, E,<br>
+                       FS.usesPositionalArg() ? nullptr : &argIndex))<br>
+      return true;<br>
+<br>
+    if (I == E) {<br>
+      // No more characters left?<br>
+      if (Warn)<br>
+        H.HandleIncompleteSpecifier(Start, E - Start);<br>
+      return true;<br>
+    }<br>
+  }<br>
+<br>
+  // Look for the length modifier.<br>
+  if (ParseLengthModifier(FS, I, E, LO) && I == E) {<br>
+    // No more characters left?<br>
+    if (Warn)<br>
+      H.HandleIncompleteSpecifier(Start, E - Start);<br>
+    return true;<br>
+  }<br>
+<br>
+  // Look for the Objective-C modifier flags, if any.<br>
+  // We parse these here, even if they don't apply to<br>
+  // the conversion specifier, and then emit an error<br>
+  // later if the conversion specifier isn't '@'.  This<br>
+  // enables better recovery, and we don't know if<br>
+  // these flags are applicable until later.<br>
+  const char *ObjCModifierFlagsStart = nullptr,<br>
+             *ObjCModifierFlagsEnd = nullptr;<br>
+  if (*I == '[') {<br>
+    ObjCModifierFlagsStart = I;<br>
+    ++I;<br>
+    auto flagStart = I;<br>
+    for (;; ++I) {<br>
+      ObjCModifierFlagsEnd = I;<br>
+      if (I == E) {<br>
+        if (Warn)<br>
+          H.HandleIncompleteSpecifier(Start, E - Start);<br>
+        return true;<br>
+      }<br>
+      // Did we find the closing ']'?<br>
+      if (*I == ']') {<br>
+        if (ParseObjCFlags(H, FS, flagStart, I, Warn))<br>
+          return true;<br>
+        ++I;<br>
+        break;<br>
+      }<br>
+      // There are no separators defined yet for multiple<br>
+      // Objective-C modifier flags.  When those are<br>
+      // defined, this is the place to check.<br>
+    }<br>
+  }<br>
+<br>
+  if (*I == '\0') {<br>
+    // Detect spurious null characters, which are likely errors.<br>
+    H.HandleNullChar(I);<br>
+    return true;<br>
+  }<br>
+<br>
+  // Finally, look for the conversion specifier.<br>
+  const char *conversionPosition = I++;<br>
+  ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier;<br>
+  switch (*conversionPosition) {<br>
+    default:<br>
+      break;<br>
+    // C99: 7.19.6.1 (section 8).<br>
+    case '%': k = ConversionSpecifier::PercentArg;   break;<br>
+    case 'A': k = ConversionSpecifier::AArg; break;<br>
+    case 'E': k = ConversionSpecifier::EArg; break;<br>
+    case 'F': k = ConversionSpecifier::FArg; break;<br>
+    case 'G': k = ConversionSpecifier::GArg; break;<br>
+    case 'X': k = ConversionSpecifier::XArg; break;<br>
+    case 'a': k = ConversionSpecifier::aArg; break;<br>
+    case 'c': k = ConversionSpecifier::cArg; break;<br>
+    case 'd': k = ConversionSpecifier::dArg; break;<br>
+    case 'e': k = ConversionSpecifier::eArg; break;<br>
+    case 'f': k = ConversionSpecifier::fArg; break;<br>
+    case 'g': k = ConversionSpecifier::gArg; break;<br>
+    case 'i': k = ConversionSpecifier::iArg; break;<br>
+    case 'n': k = ConversionSpecifier::nArg; break;<br>
+    case 'o': k = ConversionSpecifier::oArg; break;<br>
+    case 'p': k = ConversionSpecifier::pArg; break;<br>
+    case 's': k = ConversionSpecifier::sArg; break;<br>
+    case 'u': k = ConversionSpecifier::uArg; break;<br>
+    case 'x': k = ConversionSpecifier::xArg; break;<br>
+    // POSIX specific.<br>
+    case 'C': k = ConversionSpecifier::CArg; break;<br>
+    case 'S': k = ConversionSpecifier::SArg; break;<br>
+    // Apple extension for os_log<br>
+    case 'P':<br>
+      k = ConversionSpecifier::PArg;<br>
+      break;<br>
+    // Objective-C.<br>
+    case '@': k = ConversionSpecifier::ObjCObjArg; break;<br>
+    // Glibc specific.<br>
+    case 'm': k = ConversionSpecifier::PrintErrno; break;<br>
+    // FreeBSD kernel specific.<br>
+    case 'b':<br>
+      if (isFreeBSDKPrintf)<br>
+        k = ConversionSpecifier::FreeBSDbArg; // int followed by char *<br>
+      break;<br>
+    case 'r':<br>
+      if (isFreeBSDKPrintf)<br>
+        k = ConversionSpecifier::FreeBSDrArg; // int<br>
+      break;<br>
+    case 'y':<br>
+      if (isFreeBSDKPrintf)<br>
+        k = ConversionSpecifier::FreeBSDyArg; // int<br>
+      break;<br>
+    // Apple-specific.<br>
+    case 'D':<br>
+      if (isFreeBSDKPrintf)<br>
+        k = ConversionSpecifier::FreeBSDDArg; // void * followed by char *<br>
+      else if (Target.getTriple().isOSDarwin())<br>
+        k = ConversionSpecifier::DArg;<br>
+      break;<br>
+    case 'O':<br>
+      if (Target.getTriple().isOSDarwin())<br>
+        k = ConversionSpecifier::OArg;<br>
+      break;<br>
+    case 'U':<br>
+      if (Target.getTriple().isOSDarwin())<br>
+        k = ConversionSpecifier::UArg;<br>
+      break;<br>
+    // MS specific.<br>
+    case 'Z':<br>
+      if (Target.getTriple().isOSMSVCRT())<br>
+        k = ConversionSpecifier::ZArg;<br>
+  }<br>
+<br>
+  // Check to see if we used the Objective-C modifier flags with<br>
+  // a conversion specifier other than '@'.<br>
+  if (k != ConversionSpecifier::ObjCObjArg &&<br>
+      k != ConversionSpecifier::InvalidSpecifier &&<br>
+      ObjCModifierFlagsStart) {<br>
+    H.HandleObjCFlagsWithNonObjCConversion(ObjCModifierFlagsStart,<br>
+                                           ObjCModifierFlagsEnd + 1,<br>
+                                           conversionPosition);<br>
+    return true;<br>
+  }<br>
+<br>
+  PrintfConversionSpecifier CS(conversionPosition, k);<br>
+  FS.setConversionSpecifier(CS);<br>
+  if (CS.consumesDataArgument() && !FS.usesPositionalArg())<br>
+    FS.setArgIndex(argIndex++);<br>
+  // FreeBSD kernel specific.<br>
+  if (k == ConversionSpecifier::FreeBSDbArg ||<br>
+      k == ConversionSpecifier::FreeBSDDArg)<br>
+    argIndex++;<br>
+<br>
+  if (k == ConversionSpecifier::InvalidSpecifier) {<br>
+    unsigned Len = I - Start;<br>
+    if (ParseUTF8InvalidSpecifier(Start, E, Len)) {<br>
+      CS.setEndScanList(Start + Len);<br>
+      FS.setConversionSpecifier(CS);<br>
+    }<br>
+    // Assume the conversion takes one argument.<br>
+    return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, Len);<br>
+  }<br>
+  return PrintfSpecifierResult(Start, FS);<br>
+}<br>
+<br>
+bool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H,<br>
+                                                     const char *I,<br>
+                                                     const char *E,<br>
+                                                     const LangOptions &LO,<br>
+                                                     const TargetInfo &Target,<br>
+                                                     bool isFreeBSDKPrintf) {<br>
+<br>
+  unsigned argIndex = 0;<br>
+<br>
+  // Keep looking for a format specifier until we have exhausted the string.<br>
+  while (I != E) {<br>
+    const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,<br>
+                                                            LO, Target, true,<br>
+                                                            isFreeBSDKPrintf);<br>
+    // Did a fail-stop error of any kind occur when parsing the specifier?<br>
+    // If so, don't do any more processing.<br>
+    if (FSR.shouldStop())<br>
+      return true;<br>
+    // Did we exhaust the string or encounter an error that<br>
+    // we can recover from?<br>
+    if (!FSR.hasValue())<br>
+      continue;<br>
+    // We have a format specifier.  Pass it to the callback.<br>
+    if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),<br>
+                                 I - FSR.getStart()))<br>
+      return true;<br>
+  }<br>
+  assert(I == E && "Format string not exhausted");<br>
+  return false;<br>
+}<br>
+<br>
+bool clang::analyze_format_string::ParseFormatStringHasSArg(const char *I,<br>
+                                                            const char *E,<br>
+                                                            const LangOptions &LO,<br>
+                                                            const TargetInfo &Target) {<br>
+<br>
+  unsigned argIndex = 0;<br>
+<br>
+  // Keep looking for a %s format specifier until we have exhausted the string.<br>
+  FormatStringHandler H;<br>
+  while (I != E) {<br>
+    const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,<br>
+                                                            LO, Target, false,<br>
+                                                            false);<br>
+    // Did a fail-stop error of any kind occur when parsing the specifier?<br>
+    // If so, don't do any more processing.<br>
+    if (FSR.shouldStop())<br>
+      return false;<br>
+    // Did we exhaust the string or encounter an error that<br>
+    // we can recover from?<br>
+    if (!FSR.hasValue())<br>
+      continue;<br>
+    const analyze_printf::PrintfSpecifier &FS = FSR.getValue();<br>
+    // Return true if this a %s format specifier.<br>
+    if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::Kind::sArg)<br>
+      return true;<br>
+  }<br>
+  return false;<br>
+}<br>
+<br>
+//===----------------------------------------------------------------------===//<br>
+// Methods on PrintfSpecifier.<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,<br>
+                                    bool IsObjCLiteral) const {<br>
+  const PrintfConversionSpecifier &CS = getConversionSpecifier();<br>
+<br>
+  if (!CS.consumesDataArgument())<br>
+    return ArgType::Invalid();<br>
+<br>
+  if (CS.getKind() == ConversionSpecifier::cArg)<br>
+    switch (LM.getKind()) {<br>
+      case LengthModifier::None:<br>
+        return Ctx.IntTy;<br>
+      case LengthModifier::AsLong:<br>
+      case LengthModifier::AsWide:<br>
+        return ArgType(ArgType::WIntTy, "wint_t");<br>
+      case LengthModifier::AsShort:<br>
+        if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())<br>
+          return Ctx.IntTy;<br>
+        LLVM_FALLTHROUGH;<br>
+      default:<br>
+        return ArgType::Invalid();<br>
+    }<br>
+<br>
+  if (CS.isIntArg())<br>
+    switch (LM.getKind()) {<br>
+      case LengthModifier::AsLongDouble:<br>
+        // GNU extension.<br>
+        return Ctx.LongLongTy;<br>
+      case LengthModifier::None:<br>
+        return Ctx.IntTy;<br>
+      case LengthModifier::AsInt32:<br>
+        return ArgType(Ctx.IntTy, "__int32");<br>
+      case LengthModifier::AsChar: return ArgType::AnyCharTy;<br>
+      case LengthModifier::AsShort: return Ctx.ShortTy;<br>
+      case LengthModifier::AsLong: return Ctx.LongTy;<br>
+      case LengthModifier::AsLongLong:<br>
+      case LengthModifier::AsQuad:<br>
+        return Ctx.LongLongTy;<br>
+      case LengthModifier::AsInt64:<br>
+        return ArgType(Ctx.LongLongTy, "__int64");<br>
+      case LengthModifier::AsIntMax:<br>
+        return ArgType(Ctx.getIntMaxType(), "intmax_t");<br>
+      case LengthModifier::AsSizeT:<br>
+        return ArgType::makeSizeT(ArgType(Ctx.getSignedSizeType(), "ssize_t"));<br>
+      case LengthModifier::AsInt3264:<br>
+        return Ctx.getTargetInfo().getTriple().isArch64Bit()<br>
+                   ? ArgType(Ctx.LongLongTy, "__int64")<br>
+                   : ArgType(Ctx.IntTy, "__int32");<br>
+      case LengthModifier::AsPtrDiff:<br>
+        return ArgType::makePtrdiffT(<br>
+            ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));<br>
+      case LengthModifier::AsAllocate:<br>
+      case LengthModifier::AsMAllocate:<br>
+      case LengthModifier::AsWide:<br>
+        return ArgType::Invalid();<br>
+    }<br>
+<br>
+  if (CS.isUIntArg())<br>
+    switch (LM.getKind()) {<br>
+      case LengthModifier::AsLongDouble:<br>
+        // GNU extension.<br>
+        return Ctx.UnsignedLongLongTy;<br>
+      case LengthModifier::None:<br>
+        return Ctx.UnsignedIntTy;<br>
+      case LengthModifier::AsInt32:<br>
+        return ArgType(Ctx.UnsignedIntTy, "unsigned __int32");<br>
+      case LengthModifier::AsChar: return Ctx.UnsignedCharTy;<br>
+      case LengthModifier::AsShort: return Ctx.UnsignedShortTy;<br>
+      case LengthModifier::AsLong: return Ctx.UnsignedLongTy;<br>
+      case LengthModifier::AsLongLong:<br>
+      case LengthModifier::AsQuad:<br>
+        return Ctx.UnsignedLongLongTy;<br>
+      case LengthModifier::AsInt64:<br>
+        return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64");<br>
+      case LengthModifier::AsIntMax:<br>
+        return ArgType(Ctx.getUIntMaxType(), "uintmax_t");<br>
+      case LengthModifier::AsSizeT:<br>
+        return ArgType::makeSizeT(ArgType(Ctx.getSizeType(), "size_t"));<br>
+      case LengthModifier::AsInt3264:<br>
+        return Ctx.getTargetInfo().getTriple().isArch64Bit()<br>
+                   ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")<br>
+                   : ArgType(Ctx.UnsignedIntTy, "unsigned __int32");<br>
+      case LengthModifier::AsPtrDiff:<br>
+        return ArgType::makePtrdiffT(<br>
+            ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"));<br>
+      case LengthModifier::AsAllocate:<br>
+      case LengthModifier::AsMAllocate:<br>
+      case LengthModifier::AsWide:<br>
+        return ArgType::Invalid();<br>
+    }<br>
+<br>
+  if (CS.isDoubleArg()) {<br>
+    if (LM.getKind() == LengthModifier::AsLongDouble)<br>
+      return Ctx.LongDoubleTy;<br>
+    return Ctx.DoubleTy;<br>
+  }<br>
+<br>
+  if (CS.getKind() == ConversionSpecifier::nArg) {<br>
+    switch (LM.getKind()) {<br>
+      case LengthModifier::None:<br>
+        return ArgType::PtrTo(Ctx.IntTy);<br>
+      case LengthModifier::AsChar:<br>
+        return ArgType::PtrTo(Ctx.SignedCharTy);<br>
+      case LengthModifier::AsShort:<br>
+        return ArgType::PtrTo(Ctx.ShortTy);<br>
+      case LengthModifier::AsLong:<br>
+        return ArgType::PtrTo(Ctx.LongTy);<br>
+      case LengthModifier::AsLongLong:<br>
+      case LengthModifier::AsQuad:<br>
+        return ArgType::PtrTo(Ctx.LongLongTy);<br>
+      case LengthModifier::AsIntMax:<br>
+        return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));<br>
+      case LengthModifier::AsSizeT:<br>
+        return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));<br>
+      case LengthModifier::AsPtrDiff:<br>
+        return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));<br>
+      case LengthModifier::AsLongDouble:<br>
+        return ArgType(); // FIXME: Is this a known extension?<br>
+      case LengthModifier::AsAllocate:<br>
+      case LengthModifier::AsMAllocate:<br>
+      case LengthModifier::AsInt32:<br>
+      case LengthModifier::AsInt3264:<br>
+      case LengthModifier::AsInt64:<br>
+      case LengthModifier::AsWide:<br>
+        return ArgType::Invalid();<br>
+    }<br>
+  }<br>
+<br>
+  switch (CS.getKind()) {<br>
+    case ConversionSpecifier::sArg:<br>
+      if (LM.getKind() == LengthModifier::AsWideChar) {<br>
+        if (IsObjCLiteral)<br>
+          return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),<br>
+                         "const unichar *");<br>
+        return ArgType(ArgType::WCStrTy, "wchar_t *");<br>
+      }<br>
+      if (LM.getKind() == LengthModifier::AsWide)<br>
+        return ArgType(ArgType::WCStrTy, "wchar_t *");<br>
+      return ArgType::CStrTy;<br>
+    case ConversionSpecifier::SArg:<br>
+      if (IsObjCLiteral)<br>
+        return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),<br>
+                       "const unichar *");<br>
+      if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&<br>
+          LM.getKind() == LengthModifier::AsShort)<br>
+        return ArgType::CStrTy;<br>
+      return ArgType(ArgType::WCStrTy, "wchar_t *");<br>
+    case ConversionSpecifier::CArg:<br>
+      if (IsObjCLiteral)<br>
+        return ArgType(Ctx.UnsignedShortTy, "unichar");<br>
+      if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&<br>
+          LM.getKind() == LengthModifier::AsShort)<br>
+        return Ctx.IntTy;<br>
+      return ArgType(Ctx.WideCharTy, "wchar_t");<br>
+    case ConversionSpecifier::pArg:<br>
+    case ConversionSpecifier::PArg:<br>
+      return ArgType::CPointerTy;<br>
+    case ConversionSpecifier::ObjCObjArg:<br>
+      return ArgType::ObjCPointerTy;<br>
+    default:<br>
+      break;<br>
+  }<br>
+<br>
+  // FIXME: Handle other cases.<br>
+  return ArgType();<br>
+}<br>
+<br>
+bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,<br>
+                              ASTContext &Ctx, bool IsObjCLiteral) {<br>
+  // %n is different from other conversion specifiers; don't try to fix it.<br>
+  if (CS.getKind() == ConversionSpecifier::nArg)<br>
+    return false;<br>
+<br>
+  // Handle Objective-C objects first. Note that while the '%@' specifier will<br>
+  // not warn for structure pointer or void pointer arguments (because that's<br>
+  // how CoreFoundation objects are implemented), we only show a fixit for '%@'<br>
+  // if we know it's an object (block, id, class, or __attribute__((NSObject))).<br>
+  if (QT->isObjCRetainableType()) {<br>
+    if (!IsObjCLiteral)<br>
+      return false;<br>
+<br>
+    CS.setKind(ConversionSpecifier::ObjCObjArg);<br>
+<br>
+    // Disable irrelevant flags<br>
+    HasThousandsGrouping = false;<br>
+    HasPlusPrefix = false;<br>
+    HasSpacePrefix = false;<br>
+    HasAlternativeForm = false;<br>
+    HasLeadingZeroes = false;<br>
+    Precision.setHowSpecified(OptionalAmount::NotSpecified);<br>
+    LM.setKind(LengthModifier::None);<br>
+<br>
+    return true;<br>
+  }<br>
+<br>
+  // Handle strings next (char *, wchar_t *)<br>
+  if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {<br>
+    CS.setKind(ConversionSpecifier::sArg);<br>
+<br>
+    // Disable irrelevant flags<br>
+    HasAlternativeForm = 0;<br>
+    HasLeadingZeroes = 0;<br>
+<br>
+    // Set the long length modifier for wide characters<br>
+    if (QT->getPointeeType()->isWideCharType())<br>
+      LM.setKind(LengthModifier::AsWideChar);<br>
+    else<br>
+      LM.setKind(LengthModifier::None);<br>
+<br>
+    return true;<br>
+  }<br>
+<br>
+  // If it's an enum, get its underlying type.<br>
+  if (const EnumType *ETy = QT->getAs<EnumType>())<br>
+    QT = ETy->getDecl()->getIntegerType();<br>
+<br>
+  // We can only work with builtin types.<br>
+  const BuiltinType *BT = QT->getAs<BuiltinType>();<br>
+  if (!BT)<br>
+    return false;<br>
+<br>
+  // Set length modifier<br>
+  switch (BT->getKind()) {<br>
+  case BuiltinType::Bool:<br>
+  case BuiltinType::WChar_U:<br>
+  case BuiltinType::WChar_S:<br>
+  case BuiltinType::Char8: // FIXME: Treat like 'char'?<br>
+  case BuiltinType::Char16:<br>
+  case BuiltinType::Char32:<br>
+  case BuiltinType::UInt128:<br>
+  case BuiltinType::Int128:<br>
+  case BuiltinType::Half:<br>
+  case BuiltinType::Float16:<br>
+  case BuiltinType::Float128:<br>
+  case BuiltinType::ShortAccum:<br>
+  case BuiltinType::Accum:<br>
+  case BuiltinType::LongAccum:<br>
+  case BuiltinType::UShortAccum:<br>
+  case BuiltinType::UAccum:<br>
+  case BuiltinType::ULongAccum:<br>
+  case BuiltinType::ShortFract:<br>
+  case BuiltinType::Fract:<br>
+  case BuiltinType::LongFract:<br>
+  case BuiltinType::UShortFract:<br>
+  case BuiltinType::UFract:<br>
+  case BuiltinType::ULongFract:<br>
+  case BuiltinType::SatShortAccum:<br>
+  case BuiltinType::SatAccum:<br>
+  case BuiltinType::SatLongAccum:<br>
+  case BuiltinType::SatUShortAccum:<br>
+  case BuiltinType::SatUAccum:<br>
+  case BuiltinType::SatULongAccum:<br>
+  case BuiltinType::SatShortFract:<br>
+  case BuiltinType::SatFract:<br>
+  case BuiltinType::SatLongFract:<br>
+  case BuiltinType::SatUShortFract:<br>
+  case BuiltinType::SatUFract:<br>
+  case BuiltinType::SatULongFract:<br>
+    // Various types which are non-trivial to correct.<br>
+    return false;<br>
+<br>
+#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \<br>
+  case BuiltinType::Id:<br>
+#include "clang/Basic/OpenCLImageTypes.def"<br>
+#define SIGNED_TYPE(Id, SingletonId)<br>
+#define UNSIGNED_TYPE(Id, SingletonId)<br>
+#define FLOATING_TYPE(Id, SingletonId)<br>
+#define BUILTIN_TYPE(Id, SingletonId) \<br>
+  case BuiltinType::Id:<br>
+#include "clang/AST/BuiltinTypes.def"<br>
+    // Misc other stuff which doesn't make sense here.<br>
+    return false;<br>
+<br>
+  case BuiltinType::UInt:<br>
+  case BuiltinType::Int:<br>
+  case BuiltinType::Float:<br>
+  case BuiltinType::Double:<br>
+    LM.setKind(LengthModifier::None);<br>
+    break;<br>
+<br>
+  case BuiltinType::Char_U:<br>
+  case BuiltinType::UChar:<br>
+  case BuiltinType::Char_S:<br>
+  case BuiltinType::SChar:<br>
+    LM.setKind(LengthModifier::AsChar);<br>
+    break;<br>
+<br>
+  case BuiltinType::Short:<br>
+  case BuiltinType::UShort:<br>
+    LM.setKind(LengthModifier::AsShort);<br>
+    break;<br>
+<br>
+  case BuiltinType::Long:<br>
+  case BuiltinType::ULong:<br>
+    LM.setKind(LengthModifier::AsLong);<br>
+    break;<br>
+<br>
+  case BuiltinType::LongLong:<br>
+  case BuiltinType::ULongLong:<br>
+    LM.setKind(LengthModifier::AsLongLong);<br>
+    break;<br>
+<br>
+  case BuiltinType::LongDouble:<br>
+    LM.setKind(LengthModifier::AsLongDouble);<br>
+    break;<br>
+  }<br>
+<br>
+  // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.<br>
+  if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11))<br>
+    namedTypeToLengthModifier(QT, LM);<br>
+<br>
+  // If fixing the length modifier was enough, we might be done.<br>
+  if (hasValidLengthModifier(Ctx.getTargetInfo())) {<br>
+    // If we're going to offer a fix anyway, make sure the sign matches.<br>
+    switch (CS.getKind()) {<br>
+    case ConversionSpecifier::uArg:<br>
+    case ConversionSpecifier::UArg:<br>
+      if (QT->isSignedIntegerType())<br>
+        CS.setKind(clang::analyze_format_string::ConversionSpecifier::dArg);<br>
+      break;<br>
+    case ConversionSpecifier::dArg:<br>
+    case ConversionSpecifier::DArg:<br>
+    case ConversionSpecifier::iArg:<br>
+      if (QT->isUnsignedIntegerType() && !HasPlusPrefix)<br>
+        CS.setKind(clang::analyze_format_string::ConversionSpecifier::uArg);<br>
+      break;<br>
+    default:<br>
+      // Other specifiers do not have signed/unsigned variants.<br>
+      break;<br>
+    }<br>
+<br>
+    const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral);<br>
+    if (ATR.isValid() && ATR.matchesType(Ctx, QT))<br>
+      return true;<br>
+  }<br>
+<br>
+  // Set conversion specifier and disable any flags which do not apply to it.<br>
+  // Let typedefs to char fall through to int, as %c is silly for uint8_t.<br>
+  if (!isa<TypedefType>(QT) && QT->isCharType()) {<br>
+    CS.setKind(ConversionSpecifier::cArg);<br>
+    LM.setKind(LengthModifier::None);<br>
+    Precision.setHowSpecified(OptionalAmount::NotSpecified);<br>
+    HasAlternativeForm = 0;<br>
+    HasLeadingZeroes = 0;<br>
+    HasPlusPrefix = 0;<br>
+  }<br>
+  // Test for Floating type first as LongDouble can pass isUnsignedIntegerType<br>
+  else if (QT->isRealFloatingType()) {<br>
+    CS.setKind(ConversionSpecifier::fArg);<br>
+  }<br>
+  else if (QT->isSignedIntegerType()) {<br>
+    CS.setKind(ConversionSpecifier::dArg);<br>
+    HasAlternativeForm = 0;<br>
+  }<br>
+  else if (QT->isUnsignedIntegerType()) {<br>
+    CS.setKind(ConversionSpecifier::uArg);<br>
+    HasAlternativeForm = 0;<br>
+    HasPlusPrefix = 0;<br>
+  } else {<br>
+    llvm_unreachable("Unexpected type");<br>
+  }<br>
+<br>
+  return true;<br>
+}<br>
+<br>
+void PrintfSpecifier::toString(raw_ostream &os) const {<br>
+  // Whilst some features have no defined order, we are using the order<br>
+  // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)<br>
+  os << "%";<br>
+<br>
+  // Positional args<br>
+  if (usesPositionalArg()) {<br>
+    os << getPositionalArgIndex() << "$";<br>
+  }<br>
+<br>
+  // Conversion flags<br>
+  if (IsLeftJustified)    os << "-";<br>
+  if (HasPlusPrefix)      os << "+";<br>
+  if (HasSpacePrefix)     os << " ";<br>
+  if (HasAlternativeForm) os << "#";<br>
+  if (HasLeadingZeroes)   os << "0";<br>
+<br>
+  // Minimum field width<br>
+  FieldWidth.toString(os);<br>
+  // Precision<br>
+  Precision.toString(os);<br>
+  // Length modifier<br>
+  os << LM.toString();<br>
+  // Conversion specifier<br>
+  os << CS.toString();<br>
+}<br>
+<br>
+bool PrintfSpecifier::hasValidPlusPrefix() const {<br>
+  if (!HasPlusPrefix)<br>
+    return true;<br>
+<br>
+  // The plus prefix only makes sense for signed conversions<br>
+  switch (CS.getKind()) {<br>
+  case ConversionSpecifier::dArg:<br>
+  case ConversionSpecifier::DArg:<br>
+  case ConversionSpecifier::iArg:<br>
+  case ConversionSpecifier::fArg:<br>
+  case ConversionSpecifier::FArg:<br>
+  case ConversionSpecifier::eArg:<br>
+  case ConversionSpecifier::EArg:<br>
+  case ConversionSpecifier::gArg:<br>
+  case ConversionSpecifier::GArg:<br>
+  case ConversionSpecifier::aArg:<br>
+  case ConversionSpecifier::AArg:<br>
+  case ConversionSpecifier::FreeBSDrArg:<br>
+  case ConversionSpecifier::FreeBSDyArg:<br>
+    return true;<br>
+<br>
+  default:<br>
+    return false;<br>
+  }<br>
+}<br>
+<br>
+bool PrintfSpecifier::hasValidAlternativeForm() const {<br>
+  if (!HasAlternativeForm)<br>
+    return true;<br>
+<br>
+  // Alternate form flag only valid with the oxXaAeEfFgG conversions<br>
+  switch (CS.getKind()) {<br>
+  case ConversionSpecifier::oArg:<br>
+  case ConversionSpecifier::OArg:<br>
+  case ConversionSpecifier::xArg:<br>
+  case ConversionSpecifier::XArg:<br>
+  case ConversionSpecifier::aArg:<br>
+  case ConversionSpecifier::AArg:<br>
+  case ConversionSpecifier::eArg:<br>
+  case ConversionSpecifier::EArg:<br>
+  case ConversionSpecifier::fArg:<br>
+  case ConversionSpecifier::FArg:<br>
+  case ConversionSpecifier::gArg:<br>
+  case ConversionSpecifier::GArg:<br>
+  case ConversionSpecifier::FreeBSDrArg:<br>
+  case ConversionSpecifier::FreeBSDyArg:<br>
+    return true;<br>
+<br>
+  default:<br>
+    return false;<br>
+  }<br>
+}<br>
+<br>
+bool PrintfSpecifier::hasValidLeadingZeros() const {<br>
+  if (!HasLeadingZeroes)<br>
+    return true;<br>
+<br>
+  // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions<br>
+  switch (CS.getKind()) {<br>
+  case ConversionSpecifier::dArg:<br>
+  case ConversionSpecifier::DArg:<br>
+  case ConversionSpecifier::iArg:<br>
+  case ConversionSpecifier::oArg:<br>
+  case ConversionSpecifier::OArg:<br>
+  case ConversionSpecifier::uArg:<br>
+  case ConversionSpecifier::UArg:<br>
+  case ConversionSpecifier::xArg:<br>
+  case ConversionSpecifier::XArg:<br>
+  case ConversionSpecifier::aArg:<br>
+  case ConversionSpecifier::AArg:<br>
+  case ConversionSpecifier::eArg:<br>
+  case ConversionSpecifier::EArg:<br>
+  case ConversionSpecifier::fArg:<br>
+  case ConversionSpecifier::FArg:<br>
+  case ConversionSpecifier::gArg:<br>
+  case ConversionSpecifier::GArg:<br>
+  case ConversionSpecifier::FreeBSDrArg:<br>
+  case ConversionSpecifier::FreeBSDyArg:<br>
+    return true;<br>
+<br>
+  default:<br>
+    return false;<br>
+  }<br>
+}<br>
+<br>
+bool PrintfSpecifier::hasValidSpacePrefix() const {<br>
+  if (!HasSpacePrefix)<br>
+    return true;<br>
+<br>
+  // The space prefix only makes sense for signed conversions<br>
+  switch (CS.getKind()) {<br>
+  case ConversionSpecifier::dArg:<br>
+  case ConversionSpecifier::DArg:<br>
+  case ConversionSpecifier::iArg:<br>
+  case ConversionSpecifier::fArg:<br>
+  case ConversionSpecifier::FArg:<br>
+  case ConversionSpecifier::eArg:<br>
+  case ConversionSpecifier::EArg:<br>
+  case ConversionSpecifier::gArg:<br>
+  case ConversionSpecifier::GArg:<br>
+  case ConversionSpecifier::aArg:<br>
+  case ConversionSpecifier::AArg:<br>
+  case ConversionSpecifier::FreeBSDrArg:<br>
+  case ConversionSpecifier::FreeBSDyArg:<br>
+    return true;<br>
+<br>
+  default:<br>
+    return false;<br>
+  }<br>
+}<br>
+<br>
+bool PrintfSpecifier::hasValidLeftJustified() const {<br>
+  if (!IsLeftJustified)<br>
+    return true;<br>
+<br>
+  // The left justified flag is valid for all conversions except n<br>
+  switch (CS.getKind()) {<br>
+  case ConversionSpecifier::nArg:<br>
+    return false;<br>
+<br>
+  default:<br>
+    return true;<br>
+  }<br>
+}<br>
+<br>
+bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {<br>
+  if (!HasThousandsGrouping)<br>
+    return true;<br>
+<br>
+  switch (CS.getKind()) {<br>
+    case ConversionSpecifier::dArg:<br>
+    case ConversionSpecifier::DArg:<br>
+    case ConversionSpecifier::iArg:<br>
+    case ConversionSpecifier::uArg:<br>
+    case ConversionSpecifier::UArg:<br>
+    case ConversionSpecifier::fArg:<br>
+    case ConversionSpecifier::FArg:<br>
+    case ConversionSpecifier::gArg:<br>
+    case ConversionSpecifier::GArg:<br>
+      return true;<br>
+    default:<br>
+      return false;<br>
+  }<br>
+}<br>
+<br>
+bool PrintfSpecifier::hasValidPrecision() const {<br>
+  if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)<br>
+    return true;<br>
+<br>
+  // Precision is only valid with the diouxXaAeEfFgGsP conversions<br>
+  switch (CS.getKind()) {<br>
+  case ConversionSpecifier::dArg:<br>
+  case ConversionSpecifier::DArg:<br>
+  case ConversionSpecifier::iArg:<br>
+  case ConversionSpecifier::oArg:<br>
+  case ConversionSpecifier::OArg:<br>
+  case ConversionSpecifier::uArg:<br>
+  case ConversionSpecifier::UArg:<br>
+  case ConversionSpecifier::xArg:<br>
+  case ConversionSpecifier::XArg:<br>
+  case ConversionSpecifier::aArg:<br>
+  case ConversionSpecifier::AArg:<br>
+  case ConversionSpecifier::eArg:<br>
+  case ConversionSpecifier::EArg:<br>
+  case ConversionSpecifier::fArg:<br>
+  case ConversionSpecifier::FArg:<br>
+  case ConversionSpecifier::gArg:<br>
+  case ConversionSpecifier::GArg:<br>
+  case ConversionSpecifier::sArg:<br>
+  case ConversionSpecifier::FreeBSDrArg:<br>
+  case ConversionSpecifier::FreeBSDyArg:<br>
+  case ConversionSpecifier::PArg:<br>
+    return true;<br>
+<br>
+  default:<br>
+    return false;<br>
+  }<br>
+}<br>
+bool PrintfSpecifier::hasValidFieldWidth() const {<br>
+  if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)<br>
+      return true;<br>
+<br>
+  // The field width is valid for all conversions except n<br>
+  switch (CS.getKind()) {<br>
+  case ConversionSpecifier::nArg:<br>
+    return false;<br>
+<br>
+  default:<br>
+    return true;<br>
+  }<br>
+}<br>
<br>
Added: cfe/trunk/lib/AST/ScanfFormatString.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ScanfFormatString.cpp?rev=345971&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ScanfFormatString.cpp?rev=345971&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/ScanfFormatString.cpp (added)<br>
+++ cfe/trunk/lib/AST/ScanfFormatString.cpp Fri Nov  2 06:14:11 2018<br>
@@ -0,0 +1,563 @@<br>
+//= ScanfFormatString.cpp - Analysis of printf format strings --*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// Handling of format string in scanf and friends.  The structure of format<br>
+// strings for fscanf() are described in C99 7.19.6.2.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "clang/AST/FormatString.h"<br>
+#include "FormatStringParsing.h"<br>
+#include "clang/Basic/TargetInfo.h"<br>
+<br>
+using clang::analyze_format_string::ArgType;<br>
+using clang::analyze_format_string::FormatStringHandler;<br>
+using clang::analyze_format_string::LengthModifier;<br>
+using clang::analyze_format_string::OptionalAmount;<br>
+using clang::analyze_format_string::ConversionSpecifier;<br>
+using clang::analyze_scanf::ScanfConversionSpecifier;<br>
+using clang::analyze_scanf::ScanfSpecifier;<br>
+using clang::UpdateOnReturn;<br>
+using namespace clang;<br>
+<br>
+typedef clang::analyze_format_string::SpecifierResult<ScanfSpecifier><br>
+        ScanfSpecifierResult;<br>
+<br>
+static bool ParseScanList(FormatStringHandler &H,<br>
+                          ScanfConversionSpecifier &CS,<br>
+                          const char *&Beg, const char *E) {<br>
+  const char *I = Beg;<br>
+  const char *start = I - 1;<br>
+  UpdateOnReturn <const char*> UpdateBeg(Beg, I);<br>
+<br>
+  // No more characters?<br>
+  if (I == E) {<br>
+    H.HandleIncompleteScanList(start, I);<br>
+    return true;<br>
+  }<br>
+<br>
+  // Special case: ']' is the first character.<br>
+  if (*I == ']') {<br>
+    if (++I == E) {<br>
+      H.HandleIncompleteScanList(start, I - 1);<br>
+      return true;<br>
+    }<br>
+  }<br>
+<br>
+  // Special case: "^]" are the first characters.<br>
+  if (I + 1 != E && I[0] == '^' && I[1] == ']') {<br>
+    I += 2;<br>
+    if (I == E) {<br>
+      H.HandleIncompleteScanList(start, I - 1);<br>
+      return true;<br>
+    }<br>
+  }<br>
+<br>
+  // Look for a ']' character which denotes the end of the scan list.<br>
+  while (*I != ']') {<br>
+    if (++I == E) {<br>
+      H.HandleIncompleteScanList(start, I - 1);<br>
+      return true;<br>
+    }<br>
+  }<br>
+<br>
+  CS.setEndScanList(I);<br>
+  return false;<br>
+}<br>
+<br>
+// FIXME: Much of this is copy-paste from ParsePrintfSpecifier.<br>
+// We can possibly refactor.<br>
+static ScanfSpecifierResult ParseScanfSpecifier(FormatStringHandler &H,<br>
+                                                const char *&Beg,<br>
+                                                const char *E,<br>
+                                                unsigned &argIndex,<br>
+                                                const LangOptions &LO,<br>
+                                                const TargetInfo &Target) {<br>
+  using namespace clang::analyze_format_string;<br>
+  using namespace clang::analyze_scanf;<br>
+  const char *I = Beg;<br>
+  const char *Start = nullptr;<br>
+  UpdateOnReturn <const char*> UpdateBeg(Beg, I);<br>
+<br>
+    // Look for a '%' character that indicates the start of a format specifier.<br>
+  for ( ; I != E ; ++I) {<br>
+    char c = *I;<br>
+    if (c == '\0') {<br>
+        // Detect spurious null characters, which are likely errors.<br>
+      H.HandleNullChar(I);<br>
+      return true;<br>
+    }<br>
+    if (c == '%') {<br>
+      Start = I++;  // Record the start of the format specifier.<br>
+      break;<br>
+    }<br>
+  }<br>
+<br>
+    // No format specifier found?<br>
+  if (!Start)<br>
+    return false;<br>
+<br>
+  if (I == E) {<br>
+      // No more characters left?<br>
+    H.HandleIncompleteSpecifier(Start, E - Start);<br>
+    return true;<br>
+  }<br>
+<br>
+  ScanfSpecifier FS;<br>
+  if (ParseArgPosition(H, FS, Start, I, E))<br>
+    return true;<br>
+<br>
+  if (I == E) {<br>
+      // No more characters left?<br>
+    H.HandleIncompleteSpecifier(Start, E - Start);<br>
+    return true;<br>
+  }<br>
+<br>
+  // Look for '*' flag if it is present.<br>
+  if (*I == '*') {<br>
+    FS.setSuppressAssignment(I);<br>
+    if (++I == E) {<br>
+      H.HandleIncompleteSpecifier(Start, E - Start);<br>
+      return true;<br>
+    }<br>
+  }<br>
+<br>
+  // Look for the field width (if any).  Unlike printf, this is either<br>
+  // a fixed integer or isn't present.<br>
+  const OptionalAmount &Amt = clang::analyze_format_string::ParseAmount(I, E);<br>
+  if (Amt.getHowSpecified() != OptionalAmount::NotSpecified) {<br>
+    assert(Amt.getHowSpecified() == OptionalAmount::Constant);<br>
+    FS.setFieldWidth(Amt);<br>
+<br>
+    if (I == E) {<br>
+      // No more characters left?<br>
+      H.HandleIncompleteSpecifier(Start, E - Start);<br>
+      return true;<br>
+    }<br>
+  }<br>
+<br>
+  // Look for the length modifier.<br>
+  if (ParseLengthModifier(FS, I, E, LO, /*scanf=*/true) && I == E) {<br>
+      // No more characters left?<br>
+    H.HandleIncompleteSpecifier(Start, E - Start);<br>
+    return true;<br>
+  }<br>
+<br>
+  // Detect spurious null characters, which are likely errors.<br>
+  if (*I == '\0') {<br>
+    H.HandleNullChar(I);<br>
+    return true;<br>
+  }<br>
+<br>
+  // Finally, look for the conversion specifier.<br>
+  const char *conversionPosition = I++;<br>
+  ScanfConversionSpecifier::Kind k = ScanfConversionSpecifier::InvalidSpecifier;<br>
+  switch (*conversionPosition) {<br>
+    default:<br>
+      break;<br>
+    case '%': k = ConversionSpecifier::PercentArg;   break;<br>
+    case 'A': k = ConversionSpecifier::AArg; break;<br>
+    case 'E': k = ConversionSpecifier::EArg; break;<br>
+    case 'F': k = ConversionSpecifier::FArg; break;<br>
+    case 'G': k = ConversionSpecifier::GArg; break;<br>
+    case 'X': k = ConversionSpecifier::XArg; break;<br>
+    case 'a': k = ConversionSpecifier::aArg; break;<br>
+    case 'd': k = ConversionSpecifier::dArg; break;<br>
+    case 'e': k = ConversionSpecifier::eArg; break;<br>
+    case 'f': k = ConversionSpecifier::fArg; break;<br>
+    case 'g': k = ConversionSpecifier::gArg; break;<br>
+    case 'i': k = ConversionSpecifier::iArg; break;<br>
+    case 'n': k = ConversionSpecifier::nArg; break;<br>
+    case 'c': k = ConversionSpecifier::cArg; break;<br>
+    case 'C': k = ConversionSpecifier::CArg; break;<br>
+    case 'S': k = ConversionSpecifier::SArg; break;<br>
+    case '[': k = ConversionSpecifier::ScanListArg; break;<br>
+    case 'u': k = ConversionSpecifier::uArg; break;<br>
+    case 'x': k = ConversionSpecifier::xArg; break;<br>
+    case 'o': k = ConversionSpecifier::oArg; break;<br>
+    case 's': k = ConversionSpecifier::sArg; break;<br>
+    case 'p': k = ConversionSpecifier::pArg; break;<br>
+    // Apple extensions<br>
+      // Apple-specific<br>
+    case 'D':<br>
+      if (Target.getTriple().isOSDarwin())<br>
+        k = ConversionSpecifier::DArg;<br>
+      break;<br>
+    case 'O':<br>
+      if (Target.getTriple().isOSDarwin())<br>
+        k = ConversionSpecifier::OArg;<br>
+      break;<br>
+    case 'U':<br>
+      if (Target.getTriple().isOSDarwin())<br>
+        k = ConversionSpecifier::UArg;<br>
+      break;<br>
+  }<br>
+  ScanfConversionSpecifier CS(conversionPosition, k);<br>
+  if (k == ScanfConversionSpecifier::ScanListArg) {<br>
+    if (ParseScanList(H, CS, I, E))<br>
+      return true;<br>
+  }<br>
+  FS.setConversionSpecifier(CS);<br>
+  if (CS.consumesDataArgument() && !FS.getSuppressAssignment()<br>
+      && !FS.usesPositionalArg())<br>
+    FS.setArgIndex(argIndex++);<br>
+<br>
+  // FIXME: '%' and '*' doesn't make sense.  Issue a warning.<br>
+  // FIXME: 'ConsumedSoFar' and '*' doesn't make sense.<br>
+<br>
+  if (k == ScanfConversionSpecifier::InvalidSpecifier) {<br>
+    unsigned Len = I - Beg;<br>
+    if (ParseUTF8InvalidSpecifier(Beg, E, Len)) {<br>
+      CS.setEndScanList(Beg + Len);<br>
+      FS.setConversionSpecifier(CS);<br>
+    }<br>
+    // Assume the conversion takes one argument.<br>
+    return !H.HandleInvalidScanfConversionSpecifier(FS, Beg, Len);<br>
+  }<br>
+  return ScanfSpecifierResult(Start, FS);<br>
+}<br>
+<br>
+ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {<br>
+  const ScanfConversionSpecifier &CS = getConversionSpecifier();<br>
+<br>
+  if (!CS.consumesDataArgument())<br>
+    return ArgType::Invalid();<br>
+<br>
+  switch(CS.getKind()) {<br>
+    // Signed int.<br>
+    case ConversionSpecifier::dArg:<br>
+    case ConversionSpecifier::DArg:<br>
+    case ConversionSpecifier::iArg:<br>
+      switch (LM.getKind()) {<br>
+        case LengthModifier::None:<br>
+          return ArgType::PtrTo(Ctx.IntTy);<br>
+        case LengthModifier::AsChar:<br>
+          return ArgType::PtrTo(ArgType::AnyCharTy);<br>
+        case LengthModifier::AsShort:<br>
+          return ArgType::PtrTo(Ctx.ShortTy);<br>
+        case LengthModifier::AsLong:<br>
+          return ArgType::PtrTo(Ctx.LongTy);<br>
+        case LengthModifier::AsLongLong:<br>
+        case LengthModifier::AsQuad:<br>
+          return ArgType::PtrTo(Ctx.LongLongTy);<br>
+        case LengthModifier::AsInt64:<br>
+          return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64"));<br>
+        case LengthModifier::AsIntMax:<br>
+          return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));<br>
+        case LengthModifier::AsSizeT:<br>
+          return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));<br>
+        case LengthModifier::AsPtrDiff:<br>
+          return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));<br>
+        case LengthModifier::AsLongDouble:<br>
+          // GNU extension.<br>
+          return ArgType::PtrTo(Ctx.LongLongTy);<br>
+        case LengthModifier::AsAllocate:<br>
+        case LengthModifier::AsMAllocate:<br>
+        case LengthModifier::AsInt32:<br>
+        case LengthModifier::AsInt3264:<br>
+        case LengthModifier::AsWide:<br>
+          return ArgType::Invalid();<br>
+      }<br>
+<br>
+    // Unsigned int.<br>
+    case ConversionSpecifier::oArg:<br>
+    case ConversionSpecifier::OArg:<br>
+    case ConversionSpecifier::uArg:<br>
+    case ConversionSpecifier::UArg:<br>
+    case ConversionSpecifier::xArg:<br>
+    case ConversionSpecifier::XArg:<br>
+      switch (LM.getKind()) {<br>
+        case LengthModifier::None:<br>
+          return ArgType::PtrTo(Ctx.UnsignedIntTy);<br>
+        case LengthModifier::AsChar:<br>
+          return ArgType::PtrTo(Ctx.UnsignedCharTy);<br>
+        case LengthModifier::AsShort:<br>
+          return ArgType::PtrTo(Ctx.UnsignedShortTy);<br>
+        case LengthModifier::AsLong:<br>
+          return ArgType::PtrTo(Ctx.UnsignedLongTy);<br>
+        case LengthModifier::AsLongLong:<br>
+        case LengthModifier::AsQuad:<br>
+          return ArgType::PtrTo(Ctx.UnsignedLongLongTy);<br>
+        case LengthModifier::AsInt64:<br>
+          return ArgType::PtrTo(ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64"));<br>
+        case LengthModifier::AsIntMax:<br>
+          return ArgType::PtrTo(ArgType(Ctx.getUIntMaxType(), "uintmax_t"));<br>
+        case LengthModifier::AsSizeT:<br>
+          return ArgType::PtrTo(ArgType(Ctx.getSizeType(), "size_t"));<br>
+        case LengthModifier::AsPtrDiff:<br>
+          return ArgType::PtrTo(<br>
+              ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"));<br>
+        case LengthModifier::AsLongDouble:<br>
+          // GNU extension.<br>
+          return ArgType::PtrTo(Ctx.UnsignedLongLongTy);<br>
+        case LengthModifier::AsAllocate:<br>
+        case LengthModifier::AsMAllocate:<br>
+        case LengthModifier::AsInt32:<br>
+        case LengthModifier::AsInt3264:<br>
+        case LengthModifier::AsWide:<br>
+          return ArgType::Invalid();<br>
+      }<br>
+<br>
+    // Float.<br>
+    case ConversionSpecifier::aArg:<br>
+    case ConversionSpecifier::AArg:<br>
+    case ConversionSpecifier::eArg:<br>
+    case ConversionSpecifier::EArg:<br>
+    case ConversionSpecifier::fArg:<br>
+    case ConversionSpecifier::FArg:<br>
+    case ConversionSpecifier::gArg:<br>
+    case ConversionSpecifier::GArg:<br>
+      switch (LM.getKind()) {<br>
+        case LengthModifier::None:<br>
+          return ArgType::PtrTo(Ctx.FloatTy);<br>
+        case LengthModifier::AsLong:<br>
+          return ArgType::PtrTo(Ctx.DoubleTy);<br>
+        case LengthModifier::AsLongDouble:<br>
+          return ArgType::PtrTo(Ctx.LongDoubleTy);<br>
+        default:<br>
+          return ArgType::Invalid();<br>
+      }<br>
+<br>
+    // Char, string and scanlist.<br>
+    case ConversionSpecifier::cArg:<br>
+    case ConversionSpecifier::sArg:<br>
+    case ConversionSpecifier::ScanListArg:<br>
+      switch (LM.getKind()) {<br>
+        case LengthModifier::None:<br>
+          return ArgType::PtrTo(ArgType::AnyCharTy);<br>
+        case LengthModifier::AsLong:<br>
+        case LengthModifier::AsWide:<br>
+          return ArgType::PtrTo(ArgType(Ctx.getWideCharType(), "wchar_t"));<br>
+        case LengthModifier::AsAllocate:<br>
+        case LengthModifier::AsMAllocate:<br>
+          return ArgType::PtrTo(ArgType::CStrTy);<br>
+        case LengthModifier::AsShort:<br>
+          if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())<br>
+            return ArgType::PtrTo(ArgType::AnyCharTy);<br>
+          LLVM_FALLTHROUGH;<br>
+        default:<br>
+          return ArgType::Invalid();<br>
+      }<br>
+    case ConversionSpecifier::CArg:<br>
+    case ConversionSpecifier::SArg:<br>
+      // FIXME: Mac OS X specific?<br>
+      switch (LM.getKind()) {<br>
+        case LengthModifier::None:<br>
+        case LengthModifier::AsWide:<br>
+          return ArgType::PtrTo(ArgType(Ctx.getWideCharType(), "wchar_t"));<br>
+        case LengthModifier::AsAllocate:<br>
+        case LengthModifier::AsMAllocate:<br>
+          return ArgType::PtrTo(ArgType(ArgType::WCStrTy, "wchar_t *"));<br>
+        case LengthModifier::AsShort:<br>
+          if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())<br>
+            return ArgType::PtrTo(ArgType::AnyCharTy);<br>
+          LLVM_FALLTHROUGH;<br>
+        default:<br>
+          return ArgType::Invalid();<br>
+      }<br>
+<br>
+    // Pointer.<br>
+    case ConversionSpecifier::pArg:<br>
+      return ArgType::PtrTo(ArgType::CPointerTy);<br>
+<br>
+    // Write-back.<br>
+    case ConversionSpecifier::nArg:<br>
+      switch (LM.getKind()) {<br>
+        case LengthModifier::None:<br>
+          return ArgType::PtrTo(Ctx.IntTy);<br>
+        case LengthModifier::AsChar:<br>
+          return ArgType::PtrTo(Ctx.SignedCharTy);<br>
+        case LengthModifier::AsShort:<br>
+          return ArgType::PtrTo(Ctx.ShortTy);<br>
+        case LengthModifier::AsLong:<br>
+          return ArgType::PtrTo(Ctx.LongTy);<br>
+        case LengthModifier::AsLongLong:<br>
+        case LengthModifier::AsQuad:<br>
+          return ArgType::PtrTo(Ctx.LongLongTy);<br>
+        case LengthModifier::AsInt64:<br>
+          return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64"));<br>
+        case LengthModifier::AsIntMax:<br>
+          return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));<br>
+        case LengthModifier::AsSizeT:<br>
+          return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));<br>
+        case LengthModifier::AsPtrDiff:<br>
+          return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));<br>
+        case LengthModifier::AsLongDouble:<br>
+          return ArgType(); // FIXME: Is this a known extension?<br>
+        case LengthModifier::AsAllocate:<br>
+        case LengthModifier::AsMAllocate:<br>
+        case LengthModifier::AsInt32:<br>
+        case LengthModifier::AsInt3264:<br>
+        case LengthModifier::AsWide:<br>
+          return ArgType::Invalid();<br>
+        }<br>
+<br>
+    default:<br>
+      break;<br>
+  }<br>
+<br>
+  return ArgType();<br>
+}<br>
+<br>
+bool ScanfSpecifier::fixType(QualType QT, QualType RawQT,<br>
+                             const LangOptions &LangOpt,<br>
+                             ASTContext &Ctx) {<br>
+<br>
+  // %n is different from other conversion specifiers; don't try to fix it.<br>
+  if (CS.getKind() == ConversionSpecifier::nArg)<br>
+    return false;<br>
+<br>
+  if (!QT->isPointerType())<br>
+    return false;<br>
+<br>
+  QualType PT = QT->getPointeeType();<br>
+<br>
+  // If it's an enum, get its underlying type.<br>
+  if (const EnumType *ETy = PT->getAs<EnumType>()) {<br>
+    // Don't try to fix incomplete enums.<br>
+    if (!ETy->getDecl()->isComplete())<br>
+      return false;<br>
+    PT = ETy->getDecl()->getIntegerType();<br>
+  }<br>
+<br>
+  const BuiltinType *BT = PT->getAs<BuiltinType>();<br>
+  if (!BT)<br>
+    return false;<br>
+<br>
+  // Pointer to a character.<br>
+  if (PT->isAnyCharacterType()) {<br>
+    CS.setKind(ConversionSpecifier::sArg);<br>
+    if (PT->isWideCharType())<br>
+      LM.setKind(LengthModifier::AsWideChar);<br>
+    else<br>
+      LM.setKind(LengthModifier::None);<br>
+<br>
+    // If we know the target array length, we can use it as a field width.<br>
+    if (const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(RawQT)) {<br>
+      if (CAT->getSizeModifier() == ArrayType::Normal)<br>
+        FieldWidth = OptionalAmount(OptionalAmount::Constant,<br>
+                                    CAT->getSize().getZExtValue() - 1,<br>
+                                    "", 0, false);<br>
+<br>
+    }<br>
+    return true;<br>
+  }<br>
+<br>
+  // Figure out the length modifier.<br>
+  switch (BT->getKind()) {<br>
+    // no modifier<br>
+    case BuiltinType::UInt:<br>
+    case BuiltinType::Int:<br>
+    case BuiltinType::Float:<br>
+      LM.setKind(LengthModifier::None);<br>
+      break;<br>
+<br>
+    // hh<br>
+    case BuiltinType::Char_U:<br>
+    case BuiltinType::UChar:<br>
+    case BuiltinType::Char_S:<br>
+    case BuiltinType::SChar:<br>
+      LM.setKind(LengthModifier::AsChar);<br>
+      break;<br>
+<br>
+    // h<br>
+    case BuiltinType::Short:<br>
+    case BuiltinType::UShort:<br>
+      LM.setKind(LengthModifier::AsShort);<br>
+      break;<br>
+<br>
+    // l<br>
+    case BuiltinType::Long:<br>
+    case BuiltinType::ULong:<br>
+    case BuiltinType::Double:<br>
+      LM.setKind(LengthModifier::AsLong);<br>
+      break;<br>
+<br>
+    // ll<br>
+    case BuiltinType::LongLong:<br>
+    case BuiltinType::ULongLong:<br>
+      LM.setKind(LengthModifier::AsLongLong);<br>
+      break;<br>
+<br>
+    // L<br>
+    case BuiltinType::LongDouble:<br>
+      LM.setKind(LengthModifier::AsLongDouble);<br>
+      break;<br>
+<br>
+    // Don't know.<br>
+    default:<br>
+      return false;<br>
+  }<br>
+<br>
+  // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.<br>
+  if (isa<TypedefType>(PT) && (LangOpt.C99 || LangOpt.CPlusPlus11))<br>
+    namedTypeToLengthModifier(PT, LM);<br>
+<br>
+  // If fixing the length modifier was enough, we are done.<br>
+  if (hasValidLengthModifier(Ctx.getTargetInfo())) {<br>
+    const analyze_scanf::ArgType &AT = getArgType(Ctx);<br>
+    if (AT.isValid() && AT.matchesType(Ctx, QT))<br>
+      return true;<br>
+  }<br>
+<br>
+  // Figure out the conversion specifier.<br>
+  if (PT->isRealFloatingType())<br>
+    CS.setKind(ConversionSpecifier::fArg);<br>
+  else if (PT->isSignedIntegerType())<br>
+    CS.setKind(ConversionSpecifier::dArg);<br>
+  else if (PT->isUnsignedIntegerType())<br>
+    CS.setKind(ConversionSpecifier::uArg);<br>
+  else<br>
+    llvm_unreachable("Unexpected type");<br>
+<br>
+  return true;<br>
+}<br>
+<br>
+void ScanfSpecifier::toString(raw_ostream &os) const {<br>
+  os << "%";<br>
+<br>
+  if (usesPositionalArg())<br>
+    os << getPositionalArgIndex() << "$";<br>
+  if (SuppressAssignment)<br>
+    os << "*";<br>
+<br>
+  FieldWidth.toString(os);<br>
+  os << LM.toString();<br>
+  os << CS.toString();<br>
+}<br>
+<br>
+bool clang::analyze_format_string::ParseScanfString(FormatStringHandler &H,<br>
+                                                    const char *I,<br>
+                                                    const char *E,<br>
+                                                    const LangOptions &LO,<br>
+                                                    const TargetInfo &Target) {<br>
+<br>
+  unsigned argIndex = 0;<br>
+<br>
+  // Keep looking for a format specifier until we have exhausted the string.<br>
+  while (I != E) {<br>
+    const ScanfSpecifierResult &FSR = ParseScanfSpecifier(H, I, E, argIndex,<br>
+                                                          LO, Target);<br>
+    // Did a fail-stop error of any kind occur when parsing the specifier?<br>
+    // If so, don't do any more processing.<br>
+    if (FSR.shouldStop())<br>
+      return true;<br>
+      // Did we exhaust the string or encounter an error that<br>
+      // we can recover from?<br>
+    if (!FSR.hasValue())<br>
+      continue;<br>
+      // We have a format specifier.  Pass it to the callback.<br>
+    if (!H.HandleScanfSpecifier(FSR.getValue(), FSR.getStart(),<br>
+                                I - FSR.getStart())) {<br>
+      return true;<br>
+    }<br>
+  }<br>
+  assert(I == E && "Format string not exhausted");<br>
+  return false;<br>
+}<br>
<br>
Modified: cfe/trunk/lib/Analysis/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CMakeLists.txt?rev=345971&r1=345970&r2=345971&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CMakeLists.txt?rev=345971&r1=345970&r2=345971&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Analysis/CMakeLists.txt (original)<br>
+++ cfe/trunk/lib/Analysis/CMakeLists.txt Fri Nov  2 06:14:11 2018<br>
@@ -16,15 +16,11 @@ add_clang_library(clangAnalysis<br>
   CodeInjector.cpp<br>
   Dominators.cpp<br>
   ExprMutationAnalyzer.cpp<br>
-  FormatString.cpp<br>
   LiveVariables.cpp<br>
-  OSLog.cpp<br>
   ObjCNoReturn.cpp<br>
   PostOrderCFGView.cpp<br>
-  PrintfFormatString.cpp<br>
   ProgramPoint.cpp<br>
   ReachableCode.cpp<br>
-  ScanfFormatString.cpp<br>
   ThreadSafety.cpp<br>
   ThreadSafetyCommon.cpp<br>
   ThreadSafetyLogical.cpp<br>
<br>
Removed: cfe/trunk/lib/Analysis/FormatString.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/FormatString.cpp?rev=345970&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/FormatString.cpp?rev=345970&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Analysis/FormatString.cpp (original)<br>
+++ cfe/trunk/lib/Analysis/FormatString.cpp (removed)<br>
@@ -1,955 +0,0 @@<br>
-// FormatString.cpp - Common stuff for handling printf/scanf formats -*- C++ -*-<br>
-//<br>
-//                     The LLVM Compiler Infrastructure<br>
-//<br>
-// This file is distributed under the University of Illinois Open Source<br>
-// License. See LICENSE.TXT for details.<br>
-//<br>
-//===----------------------------------------------------------------------===//<br>
-//<br>
-// Shared details for processing format strings of printf and scanf<br>
-// (and friends).<br>
-//<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-#include "FormatStringParsing.h"<br>
-#include "clang/Basic/LangOptions.h"<br>
-#include "clang/Basic/TargetInfo.h"<br>
-#include "llvm/Support/ConvertUTF.h"<br>
-<br>
-using clang::analyze_format_string::ArgType;<br>
-using clang::analyze_format_string::FormatStringHandler;<br>
-using clang::analyze_format_string::FormatSpecifier;<br>
-using clang::analyze_format_string::LengthModifier;<br>
-using clang::analyze_format_string::OptionalAmount;<br>
-using clang::analyze_format_string::PositionContext;<br>
-using clang::analyze_format_string::ConversionSpecifier;<br>
-using namespace clang;<br>
-<br>
-// Key function to FormatStringHandler.<br>
-FormatStringHandler::~FormatStringHandler() {}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Functions for parsing format strings components in both printf and<br>
-// scanf format strings.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-OptionalAmount<br>
-clang::analyze_format_string::ParseAmount(const char *&Beg, const char *E) {<br>
-  const char *I = Beg;<br>
-  UpdateOnReturn <const char*> UpdateBeg(Beg, I);<br>
-<br>
-  unsigned accumulator = 0;<br>
-  bool hasDigits = false;<br>
-<br>
-  for ( ; I != E; ++I) {<br>
-    char c = *I;<br>
-    if (c >= '0' && c <= '9') {<br>
-      hasDigits = true;<br>
-      accumulator = (accumulator * 10) + (c - '0');<br>
-      continue;<br>
-    }<br>
-<br>
-    if (hasDigits)<br>
-      return OptionalAmount(OptionalAmount::Constant, accumulator, Beg, I - Beg,<br>
-          false);<br>
-<br>
-    break;<br>
-  }<br>
-<br>
-  return OptionalAmount();<br>
-}<br>
-<br>
-OptionalAmount<br>
-clang::analyze_format_string::ParseNonPositionAmount(const char *&Beg,<br>
-                                                     const char *E,<br>
-                                                     unsigned &argIndex) {<br>
-  if (*Beg == '*') {<br>
-    ++Beg;<br>
-    return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg, 0, false);<br>
-  }<br>
-<br>
-  return ParseAmount(Beg, E);<br>
-}<br>
-<br>
-OptionalAmount<br>
-clang::analyze_format_string::ParsePositionAmount(FormatStringHandler &H,<br>
-                                                  const char *Start,<br>
-                                                  const char *&Beg,<br>
-                                                  const char *E,<br>
-                                                  PositionContext p) {<br>
-  if (*Beg == '*') {<br>
-    const char *I = Beg + 1;<br>
-    const OptionalAmount &Amt = ParseAmount(I, E);<br>
-<br>
-    if (Amt.getHowSpecified() == OptionalAmount::NotSpecified) {<br>
-      H.HandleInvalidPosition(Beg, I - Beg, p);<br>
-      return OptionalAmount(false);<br>
-    }<br>
-<br>
-    if (I == E) {<br>
-      // No more characters left?<br>
-      H.HandleIncompleteSpecifier(Start, E - Start);<br>
-      return OptionalAmount(false);<br>
-    }<br>
-<br>
-    assert(Amt.getHowSpecified() == OptionalAmount::Constant);<br>
-<br>
-    if (*I == '$') {<br>
-      // Handle positional arguments<br>
-<br>
-      // Special case: '*0$', since this is an easy mistake.<br>
-      if (Amt.getConstantAmount() == 0) {<br>
-        H.HandleZeroPosition(Beg, I - Beg + 1);<br>
-        return OptionalAmount(false);<br>
-      }<br>
-<br>
-      const char *Tmp = Beg;<br>
-      Beg = ++I;<br>
-<br>
-      return OptionalAmount(OptionalAmount::Arg, Amt.getConstantAmount() - 1,<br>
-                            Tmp, 0, true);<br>
-    }<br>
-<br>
-    H.HandleInvalidPosition(Beg, I - Beg, p);<br>
-    return OptionalAmount(false);<br>
-  }<br>
-<br>
-  return ParseAmount(Beg, E);<br>
-}<br>
-<br>
-<br>
-bool<br>
-clang::analyze_format_string::ParseFieldWidth(FormatStringHandler &H,<br>
-                                              FormatSpecifier &CS,<br>
-                                              const char *Start,<br>
-                                              const char *&Beg, const char *E,<br>
-                                              unsigned *argIndex) {<br>
-  // FIXME: Support negative field widths.<br>
-  if (argIndex) {<br>
-    CS.setFieldWidth(ParseNonPositionAmount(Beg, E, *argIndex));<br>
-  }<br>
-  else {<br>
-    const OptionalAmount Amt =<br>
-      ParsePositionAmount(H, Start, Beg, E,<br>
-                          analyze_format_string::FieldWidthPos);<br>
-<br>
-    if (Amt.isInvalid())<br>
-      return true;<br>
-    CS.setFieldWidth(Amt);<br>
-  }<br>
-  return false;<br>
-}<br>
-<br>
-bool<br>
-clang::analyze_format_string::ParseArgPosition(FormatStringHandler &H,<br>
-                                               FormatSpecifier &FS,<br>
-                                               const char *Start,<br>
-                                               const char *&Beg,<br>
-                                               const char *E) {<br>
-  const char *I = Beg;<br>
-<br>
-  const OptionalAmount &Amt = ParseAmount(I, E);<br>
-<br>
-  if (I == E) {<br>
-    // No more characters left?<br>
-    H.HandleIncompleteSpecifier(Start, E - Start);<br>
-    return true;<br>
-  }<br>
-<br>
-  if (Amt.getHowSpecified() == OptionalAmount::Constant && *(I++) == '$') {<br>
-    // Warn that positional arguments are non-standard.<br>
-    H.HandlePosition(Start, I - Start);<br>
-<br>
-    // Special case: '%0$', since this is an easy mistake.<br>
-    if (Amt.getConstantAmount() == 0) {<br>
-      H.HandleZeroPosition(Start, I - Start);<br>
-      return true;<br>
-    }<br>
-<br>
-    FS.setArgIndex(Amt.getConstantAmount() - 1);<br>
-    FS.setUsesPositionalArg();<br>
-    // Update the caller's pointer if we decided to consume<br>
-    // these characters.<br>
-    Beg = I;<br>
-    return false;<br>
-  }<br>
-<br>
-  return false;<br>
-}<br>
-<br>
-bool<br>
-clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS,<br>
-                                                  const char *&I,<br>
-                                                  const char *E,<br>
-                                                  const LangOptions &LO,<br>
-                                                  bool IsScanf) {<br>
-  LengthModifier::Kind lmKind = LengthModifier::None;<br>
-  const char *lmPosition = I;<br>
-  switch (*I) {<br>
-    default:<br>
-      return false;<br>
-    case 'h':<br>
-      ++I;<br>
-      if (I != E && *I == 'h') {<br>
-        ++I;<br>
-        lmKind = LengthModifier::AsChar;<br>
-      } else {<br>
-        lmKind = LengthModifier::AsShort;<br>
-      }<br>
-      break;<br>
-    case 'l':<br>
-      ++I;<br>
-      if (I != E && *I == 'l') {<br>
-        ++I;<br>
-        lmKind = LengthModifier::AsLongLong;<br>
-      } else {<br>
-        lmKind = LengthModifier::AsLong;<br>
-      }<br>
-      break;<br>
-    case 'j': lmKind = LengthModifier::AsIntMax;     ++I; break;<br>
-    case 'z': lmKind = LengthModifier::AsSizeT;      ++I; break;<br>
-    case 't': lmKind = LengthModifier::AsPtrDiff;    ++I; break;<br>
-    case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break;<br>
-    case 'q': lmKind = LengthModifier::AsQuad;       ++I; break;<br>
-    case 'a':<br>
-      if (IsScanf && !LO.C99 && !LO.CPlusPlus11) {<br>
-        // For scanf in C90, look at the next character to see if this should<br>
-        // be parsed as the GNU extension 'a' length modifier. If not, this<br>
-        // will be parsed as a conversion specifier.<br>
-        ++I;<br>
-        if (I != E && (*I == 's' || *I == 'S' || *I == '[')) {<br>
-          lmKind = LengthModifier::AsAllocate;<br>
-          break;<br>
-        }<br>
-        --I;<br>
-      }<br>
-      return false;<br>
-    case 'm':<br>
-      if (IsScanf) {<br>
-        lmKind = LengthModifier::AsMAllocate;<br>
-        ++I;<br>
-        break;<br>
-      }<br>
-      return false;<br>
-    // printf: AsInt64, AsInt32, AsInt3264<br>
-    // scanf:  AsInt64<br>
-    case 'I':<br>
-      if (I + 1 != E && I + 2 != E) {<br>
-        if (I[1] == '6' && I[2] == '4') {<br>
-          I += 3;<br>
-          lmKind = LengthModifier::AsInt64;<br>
-          break;<br>
-        }<br>
-        if (IsScanf)<br>
-          return false;<br>
-<br>
-        if (I[1] == '3' && I[2] == '2') {<br>
-          I += 3;<br>
-          lmKind = LengthModifier::AsInt32;<br>
-          break;<br>
-        }<br>
-      }<br>
-      ++I;<br>
-      lmKind = LengthModifier::AsInt3264;<br>
-      break;<br>
-    case 'w':<br>
-      lmKind = LengthModifier::AsWide; ++I; break;<br>
-  }<br>
-  LengthModifier lm(lmPosition, lmKind);<br>
-  FS.setLengthModifier(lm);<br>
-  return true;<br>
-}<br>
-<br>
-bool clang::analyze_format_string::ParseUTF8InvalidSpecifier(<br>
-    const char *SpecifierBegin, const char *FmtStrEnd, unsigned &Len) {<br>
-  if (SpecifierBegin + 1 >= FmtStrEnd)<br>
-    return false;<br>
-<br>
-  const llvm::UTF8 *SB =<br>
-      reinterpret_cast<const llvm::UTF8 *>(SpecifierBegin + 1);<br>
-  const llvm::UTF8 *SE = reinterpret_cast<const llvm::UTF8 *>(FmtStrEnd);<br>
-  const char FirstByte = *SB;<br>
-<br>
-  // If the invalid specifier is a multibyte UTF-8 string, return the<br>
-  // total length accordingly so that the conversion specifier can be<br>
-  // properly updated to reflect a complete UTF-8 specifier.<br>
-  unsigned NumBytes = llvm::getNumBytesForUTF8(FirstByte);<br>
-  if (NumBytes == 1)<br>
-    return false;<br>
-  if (SB + NumBytes > SE)<br>
-    return false;<br>
-<br>
-  Len = NumBytes + 1;<br>
-  return true;<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Methods on ArgType.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-clang::analyze_format_string::ArgType::MatchKind<br>
-ArgType::matchesType(ASTContext &C, QualType argTy) const {<br>
-  if (Ptr) {<br>
-    // It has to be a pointer.<br>
-    const PointerType *PT = argTy->getAs<PointerType>();<br>
-    if (!PT)<br>
-      return NoMatch;<br>
-<br>
-    // We cannot write through a const qualified pointer.<br>
-    if (PT->getPointeeType().isConstQualified())<br>
-      return NoMatch;<br>
-<br>
-    argTy = PT->getPointeeType();<br>
-  }<br>
-<br>
-  switch (K) {<br>
-    case InvalidTy:<br>
-      llvm_unreachable("ArgType must be valid");<br>
-<br>
-    case UnknownTy:<br>
-      return Match;<br>
-<br>
-    case AnyCharTy: {<br>
-      if (const EnumType *ETy = argTy->getAs<EnumType>()) {<br>
-        // If the enum is incomplete we know nothing about the underlying type.<br>
-        // Assume that it's 'int'.<br>
-        if (!ETy->getDecl()->isComplete())<br>
-          return NoMatch;<br>
-        argTy = ETy->getDecl()->getIntegerType();<br>
-      }<br>
-<br>
-      if (const BuiltinType *BT = argTy->getAs<BuiltinType>())<br>
-        switch (BT->getKind()) {<br>
-          default:<br>
-            break;<br>
-          case BuiltinType::Char_S:<br>
-          case BuiltinType::SChar:<br>
-          case BuiltinType::UChar:<br>
-          case BuiltinType::Char_U:<br>
-            return Match;<br>
-        }<br>
-      return NoMatch;<br>
-    }<br>
-<br>
-    case SpecificTy: {<br>
-      if (const EnumType *ETy = argTy->getAs<EnumType>()) {<br>
-        // If the enum is incomplete we know nothing about the underlying type.<br>
-        // Assume that it's 'int'.<br>
-        if (!ETy->getDecl()->isComplete())<br>
-          argTy = C.IntTy;<br>
-        else<br>
-          argTy = ETy->getDecl()->getIntegerType();<br>
-      }<br>
-      argTy = C.getCanonicalType(argTy).getUnqualifiedType();<br>
-<br>
-      if (T == argTy)<br>
-        return Match;<br>
-      // Check for "compatible types".<br>
-      if (const BuiltinType *BT = argTy->getAs<BuiltinType>())<br>
-        switch (BT->getKind()) {<br>
-          default:<br>
-            break;<br>
-          case BuiltinType::Char_S:<br>
-          case BuiltinType::SChar:<br>
-          case BuiltinType::Char_U:<br>
-          case BuiltinType::UChar:<br>
-            return T == C.UnsignedCharTy || T == C.SignedCharTy ? Match<br>
-                                                                : NoMatch;<br>
-          case BuiltinType::Short:<br>
-            return T == C.UnsignedShortTy ? Match : NoMatch;<br>
-          case BuiltinType::UShort:<br>
-            return T == C.ShortTy ? Match : NoMatch;<br>
-          case BuiltinType::Int:<br>
-            return T == C.UnsignedIntTy ? Match : NoMatch;<br>
-          case BuiltinType::UInt:<br>
-            return T == C.IntTy ? Match : NoMatch;<br>
-          case BuiltinType::Long:<br>
-            return T == C.UnsignedLongTy ? Match : NoMatch;<br>
-          case BuiltinType::ULong:<br>
-            return T == C.LongTy ? Match : NoMatch;<br>
-          case BuiltinType::LongLong:<br>
-            return T == C.UnsignedLongLongTy ? Match : NoMatch;<br>
-          case BuiltinType::ULongLong:<br>
-            return T == C.LongLongTy ? Match : NoMatch;<br>
-        }<br>
-      return NoMatch;<br>
-    }<br>
-<br>
-    case CStrTy: {<br>
-      const PointerType *PT = argTy->getAs<PointerType>();<br>
-      if (!PT)<br>
-        return NoMatch;<br>
-      QualType pointeeTy = PT->getPointeeType();<br>
-      if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>())<br>
-        switch (BT->getKind()) {<br>
-          case BuiltinType::Void:<br>
-          case BuiltinType::Char_U:<br>
-          case BuiltinType::UChar:<br>
-          case BuiltinType::Char_S:<br>
-          case BuiltinType::SChar:<br>
-            return Match;<br>
-          default:<br>
-            break;<br>
-        }<br>
-<br>
-      return NoMatch;<br>
-    }<br>
-<br>
-    case WCStrTy: {<br>
-      const PointerType *PT = argTy->getAs<PointerType>();<br>
-      if (!PT)<br>
-        return NoMatch;<br>
-      QualType pointeeTy =<br>
-        C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType();<br>
-      return pointeeTy == C.getWideCharType() ? Match : NoMatch;<br>
-    }<br>
-<br>
-    case WIntTy: {<br>
-      QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType();<br>
-<br>
-      if (C.getCanonicalType(argTy).getUnqualifiedType() == WInt)<br>
-        return Match;<br>
-<br>
-      QualType PromoArg = argTy->isPromotableIntegerType()<br>
-                              ? C.getPromotedIntegerType(argTy)<br>
-                              : argTy;<br>
-      PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType();<br>
-<br>
-      // If the promoted argument is the corresponding signed type of the<br>
-      // wint_t type, then it should match.<br>
-      if (PromoArg->hasSignedIntegerRepresentation() &&<br>
-          C.getCorrespondingUnsignedType(PromoArg) == WInt)<br>
-        return Match;<br>
-<br>
-      return WInt == PromoArg ? Match : NoMatch;<br>
-    }<br>
-<br>
-    case CPointerTy:<br>
-      if (argTy->isVoidPointerType()) {<br>
-        return Match;<br>
-      } if (argTy->isPointerType() || argTy->isObjCObjectPointerType() ||<br>
-            argTy->isBlockPointerType() || argTy->isNullPtrType()) {<br>
-        return NoMatchPedantic;<br>
-      } else {<br>
-        return NoMatch;<br>
-      }<br>
-<br>
-    case ObjCPointerTy: {<br>
-      if (argTy->getAs<ObjCObjectPointerType>() ||<br>
-          argTy->getAs<BlockPointerType>())<br>
-        return Match;<br>
-<br>
-      // Handle implicit toll-free bridging.<br>
-      if (const PointerType *PT = argTy->getAs<PointerType>()) {<br>
-        // Things such as CFTypeRef are really just opaque pointers<br>
-        // to C structs representing CF types that can often be bridged<br>
-        // to Objective-C objects.  Since the compiler doesn't know which<br>
-        // structs can be toll-free bridged, we just accept them all.<br>
-        QualType pointee = PT->getPointeeType();<br>
-        if (pointee->getAsStructureType() || pointee->isVoidType())<br>
-          return Match;<br>
-      }<br>
-      return NoMatch;<br>
-    }<br>
-  }<br>
-<br>
-  llvm_unreachable("Invalid ArgType Kind!");<br>
-}<br>
-<br>
-QualType ArgType::getRepresentativeType(ASTContext &C) const {<br>
-  QualType Res;<br>
-  switch (K) {<br>
-    case InvalidTy:<br>
-      llvm_unreachable("No representative type for Invalid ArgType");<br>
-    case UnknownTy:<br>
-      llvm_unreachable("No representative type for Unknown ArgType");<br>
-    case AnyCharTy:<br>
-      Res = C.CharTy;<br>
-      break;<br>
-    case SpecificTy:<br>
-      Res = T;<br>
-      break;<br>
-    case CStrTy:<br>
-      Res = C.getPointerType(C.CharTy);<br>
-      break;<br>
-    case WCStrTy:<br>
-      Res = C.getPointerType(C.getWideCharType());<br>
-      break;<br>
-    case ObjCPointerTy:<br>
-      Res = C.ObjCBuiltinIdTy;<br>
-      break;<br>
-    case CPointerTy:<br>
-      Res = C.VoidPtrTy;<br>
-      break;<br>
-    case WIntTy: {<br>
-      Res = C.getWIntType();<br>
-      break;<br>
-    }<br>
-  }<br>
-<br>
-  if (Ptr)<br>
-    Res = C.getPointerType(Res);<br>
-  return Res;<br>
-}<br>
-<br>
-std::string ArgType::getRepresentativeTypeName(ASTContext &C) const {<br>
-  std::string S = getRepresentativeType(C).getAsString();<br>
-<br>
-  std::string Alias;<br>
-  if (Name) {<br>
-    // Use a specific name for this type, e.g. "size_t".<br>
-    Alias = Name;<br>
-    if (Ptr) {<br>
-      // If ArgType is actually a pointer to T, append an asterisk.<br>
-      Alias += (Alias[Alias.size()-1] == '*') ? "*" : " *";<br>
-    }<br>
-    // If Alias is the same as the underlying type, e.g. wchar_t, then drop it.<br>
-    if (S == Alias)<br>
-      Alias.clear();<br>
-  }<br>
-<br>
-  if (!Alias.empty())<br>
-    return std::string("'") + Alias + "' (aka '" + S + "')";<br>
-  return std::string("'") + S + "'";<br>
-}<br>
-<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Methods on OptionalAmount.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-ArgType<br>
-analyze_format_string::OptionalAmount::getArgType(ASTContext &Ctx) const {<br>
-  return Ctx.IntTy;<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Methods on LengthModifier.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-const char *<br>
-analyze_format_string::LengthModifier::toString() const {<br>
-  switch (kind) {<br>
-  case AsChar:<br>
-    return "hh";<br>
-  case AsShort:<br>
-    return "h";<br>
-  case AsLong: // or AsWideChar<br>
-    return "l";<br>
-  case AsLongLong:<br>
-    return "ll";<br>
-  case AsQuad:<br>
-    return "q";<br>
-  case AsIntMax:<br>
-    return "j";<br>
-  case AsSizeT:<br>
-    return "z";<br>
-  case AsPtrDiff:<br>
-    return "t";<br>
-  case AsInt32:<br>
-    return "I32";<br>
-  case AsInt3264:<br>
-    return "I";<br>
-  case AsInt64:<br>
-    return "I64";<br>
-  case AsLongDouble:<br>
-    return "L";<br>
-  case AsAllocate:<br>
-    return "a";<br>
-  case AsMAllocate:<br>
-    return "m";<br>
-  case AsWide:<br>
-    return "w";<br>
-  case None:<br>
-    return "";<br>
-  }<br>
-  return nullptr;<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Methods on ConversionSpecifier.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-const char *ConversionSpecifier::toString() const {<br>
-  switch (kind) {<br>
-  case dArg: return "d";<br>
-  case DArg: return "D";<br>
-  case iArg: return "i";<br>
-  case oArg: return "o";<br>
-  case OArg: return "O";<br>
-  case uArg: return "u";<br>
-  case UArg: return "U";<br>
-  case xArg: return "x";<br>
-  case XArg: return "X";<br>
-  case fArg: return "f";<br>
-  case FArg: return "F";<br>
-  case eArg: return "e";<br>
-  case EArg: return "E";<br>
-  case gArg: return "g";<br>
-  case GArg: return "G";<br>
-  case aArg: return "a";<br>
-  case AArg: return "A";<br>
-  case cArg: return "c";<br>
-  case sArg: return "s";<br>
-  case pArg: return "p";<br>
-  case PArg:<br>
-    return "P";<br>
-  case nArg: return "n";<br>
-  case PercentArg:  return "%";<br>
-  case ScanListArg: return "[";<br>
-  case InvalidSpecifier: return nullptr;<br>
-<br>
-  // POSIX unicode extensions.<br>
-  case CArg: return "C";<br>
-  case SArg: return "S";<br>
-<br>
-  // Objective-C specific specifiers.<br>
-  case ObjCObjArg: return "@";<br>
-<br>
-  // FreeBSD kernel specific specifiers.<br>
-  case FreeBSDbArg: return "b";<br>
-  case FreeBSDDArg: return "D";<br>
-  case FreeBSDrArg: return "r";<br>
-  case FreeBSDyArg: return "y";<br>
-<br>
-  // GlibC specific specifiers.<br>
-  case PrintErrno: return "m";<br>
-<br>
-  // MS specific specifiers.<br>
-  case ZArg: return "Z";<br>
-  }<br>
-  return nullptr;<br>
-}<br>
-<br>
-Optional<ConversionSpecifier><br>
-ConversionSpecifier::getStandardSpecifier() const {<br>
-  ConversionSpecifier::Kind NewKind;<br>
-<br>
-  switch (getKind()) {<br>
-  default:<br>
-    return None;<br>
-  case DArg:<br>
-    NewKind = dArg;<br>
-    break;<br>
-  case UArg:<br>
-    NewKind = uArg;<br>
-    break;<br>
-  case OArg:<br>
-    NewKind = oArg;<br>
-    break;<br>
-  }<br>
-<br>
-  ConversionSpecifier FixedCS(*this);<br>
-  FixedCS.setKind(NewKind);<br>
-  return FixedCS;<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Methods on OptionalAmount.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-void OptionalAmount::toString(raw_ostream &os) const {<br>
-  switch (hs) {<br>
-  case Invalid:<br>
-  case NotSpecified:<br>
-    return;<br>
-  case Arg:<br>
-    if (UsesDotPrefix)<br>
-        os << ".";<br>
-    if (usesPositionalArg())<br>
-      os << "*" << getPositionalArgIndex() << "$";<br>
-    else<br>
-      os << "*";<br>
-    break;<br>
-  case Constant:<br>
-    if (UsesDotPrefix)<br>
-        os << ".";<br>
-    os << amt;<br>
-    break;<br>
-  }<br>
-}<br>
-<br>
-bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target) const {<br>
-  switch (LM.getKind()) {<br>
-    case LengthModifier::None:<br>
-      return true;<br>
-<br>
-    // Handle most integer flags<br>
-    case LengthModifier::AsShort:<br>
-      if (Target.getTriple().isOSMSVCRT()) {<br>
-        switch (CS.getKind()) {<br>
-          case ConversionSpecifier::cArg:<br>
-          case ConversionSpecifier::CArg:<br>
-          case ConversionSpecifier::sArg:<br>
-          case ConversionSpecifier::SArg:<br>
-          case ConversionSpecifier::ZArg:<br>
-            return true;<br>
-          default:<br>
-            break;<br>
-        }<br>
-      }<br>
-      LLVM_FALLTHROUGH;<br>
-    case LengthModifier::AsChar:<br>
-    case LengthModifier::AsLongLong:<br>
-    case LengthModifier::AsQuad:<br>
-    case LengthModifier::AsIntMax:<br>
-    case LengthModifier::AsSizeT:<br>
-    case LengthModifier::AsPtrDiff:<br>
-      switch (CS.getKind()) {<br>
-        case ConversionSpecifier::dArg:<br>
-        case ConversionSpecifier::DArg:<br>
-        case ConversionSpecifier::iArg:<br>
-        case ConversionSpecifier::oArg:<br>
-        case ConversionSpecifier::OArg:<br>
-        case ConversionSpecifier::uArg:<br>
-        case ConversionSpecifier::UArg:<br>
-        case ConversionSpecifier::xArg:<br>
-        case ConversionSpecifier::XArg:<br>
-        case ConversionSpecifier::nArg:<br>
-          return true;<br>
-        case ConversionSpecifier::FreeBSDrArg:<br>
-        case ConversionSpecifier::FreeBSDyArg:<br>
-          return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS4();<br>
-        default:<br>
-          return false;<br>
-      }<br>
-<br>
-    // Handle 'l' flag<br>
-    case LengthModifier::AsLong: // or AsWideChar<br>
-      switch (CS.getKind()) {<br>
-        case ConversionSpecifier::dArg:<br>
-        case ConversionSpecifier::DArg:<br>
-        case ConversionSpecifier::iArg:<br>
-        case ConversionSpecifier::oArg:<br>
-        case ConversionSpecifier::OArg:<br>
-        case ConversionSpecifier::uArg:<br>
-        case ConversionSpecifier::UArg:<br>
-        case ConversionSpecifier::xArg:<br>
-        case ConversionSpecifier::XArg:<br>
-        case ConversionSpecifier::aArg:<br>
-        case ConversionSpecifier::AArg:<br>
-        case ConversionSpecifier::fArg:<br>
-        case ConversionSpecifier::FArg:<br>
-        case ConversionSpecifier::eArg:<br>
-        case ConversionSpecifier::EArg:<br>
-        case ConversionSpecifier::gArg:<br>
-        case ConversionSpecifier::GArg:<br>
-        case ConversionSpecifier::nArg:<br>
-        case ConversionSpecifier::cArg:<br>
-        case ConversionSpecifier::sArg:<br>
-        case ConversionSpecifier::ScanListArg:<br>
-        case ConversionSpecifier::ZArg:<br>
-          return true;<br>
-        case ConversionSpecifier::FreeBSDrArg:<br>
-        case ConversionSpecifier::FreeBSDyArg:<br>
-          return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS4();<br>
-        default:<br>
-          return false;<br>
-      }<br>
-<br>
-    case LengthModifier::AsLongDouble:<br>
-      switch (CS.getKind()) {<br>
-        case ConversionSpecifier::aArg:<br>
-        case ConversionSpecifier::AArg:<br>
-        case ConversionSpecifier::fArg:<br>
-        case ConversionSpecifier::FArg:<br>
-        case ConversionSpecifier::eArg:<br>
-        case ConversionSpecifier::EArg:<br>
-        case ConversionSpecifier::gArg:<br>
-        case ConversionSpecifier::GArg:<br>
-          return true;<br>
-        // GNU libc extension.<br>
-        case ConversionSpecifier::dArg:<br>
-        case ConversionSpecifier::iArg:<br>
-        case ConversionSpecifier::oArg:<br>
-        case ConversionSpecifier::uArg:<br>
-        case ConversionSpecifier::xArg:<br>
-        case ConversionSpecifier::XArg:<br>
-          return !Target.getTriple().isOSDarwin() &&<br>
-                 !Target.getTriple().isOSWindows();<br>
-        default:<br>
-          return false;<br>
-      }<br>
-<br>
-    case LengthModifier::AsAllocate:<br>
-      switch (CS.getKind()) {<br>
-        case ConversionSpecifier::sArg:<br>
-        case ConversionSpecifier::SArg:<br>
-        case ConversionSpecifier::ScanListArg:<br>
-          return true;<br>
-        default:<br>
-          return false;<br>
-      }<br>
-<br>
-    case LengthModifier::AsMAllocate:<br>
-      switch (CS.getKind()) {<br>
-        case ConversionSpecifier::cArg:<br>
-        case ConversionSpecifier::CArg:<br>
-        case ConversionSpecifier::sArg:<br>
-        case ConversionSpecifier::SArg:<br>
-        case ConversionSpecifier::ScanListArg:<br>
-          return true;<br>
-        default:<br>
-          return false;<br>
-      }<br>
-    case LengthModifier::AsInt32:<br>
-    case LengthModifier::AsInt3264:<br>
-    case LengthModifier::AsInt64:<br>
-      switch (CS.getKind()) {<br>
-        case ConversionSpecifier::dArg:<br>
-        case ConversionSpecifier::iArg:<br>
-        case ConversionSpecifier::oArg:<br>
-        case ConversionSpecifier::uArg:<br>
-        case ConversionSpecifier::xArg:<br>
-        case ConversionSpecifier::XArg:<br>
-          return Target.getTriple().isOSMSVCRT();<br>
-        default:<br>
-          return false;<br>
-      }<br>
-    case LengthModifier::AsWide:<br>
-      switch (CS.getKind()) {<br>
-        case ConversionSpecifier::cArg:<br>
-        case ConversionSpecifier::CArg:<br>
-        case ConversionSpecifier::sArg:<br>
-        case ConversionSpecifier::SArg:<br>
-        case ConversionSpecifier::ZArg:<br>
-          return Target.getTriple().isOSMSVCRT();<br>
-        default:<br>
-          return false;<br>
-      }<br>
-  }<br>
-  llvm_unreachable("Invalid LengthModifier Kind!");<br>
-}<br>
-<br>
-bool FormatSpecifier::hasStandardLengthModifier() const {<br>
-  switch (LM.getKind()) {<br>
-    case LengthModifier::None:<br>
-    case LengthModifier::AsChar:<br>
-    case LengthModifier::AsShort:<br>
-    case LengthModifier::AsLong:<br>
-    case LengthModifier::AsLongLong:<br>
-    case LengthModifier::AsIntMax:<br>
-    case LengthModifier::AsSizeT:<br>
-    case LengthModifier::AsPtrDiff:<br>
-    case LengthModifier::AsLongDouble:<br>
-      return true;<br>
-    case LengthModifier::AsAllocate:<br>
-    case LengthModifier::AsMAllocate:<br>
-    case LengthModifier::AsQuad:<br>
-    case LengthModifier::AsInt32:<br>
-    case LengthModifier::AsInt3264:<br>
-    case LengthModifier::AsInt64:<br>
-    case LengthModifier::AsWide:<br>
-      return false;<br>
-  }<br>
-  llvm_unreachable("Invalid LengthModifier Kind!");<br>
-}<br>
-<br>
-bool FormatSpecifier::hasStandardConversionSpecifier(<br>
-    const LangOptions &LangOpt) const {<br>
-  switch (CS.getKind()) {<br>
-    case ConversionSpecifier::cArg:<br>
-    case ConversionSpecifier::dArg:<br>
-    case ConversionSpecifier::iArg:<br>
-    case ConversionSpecifier::oArg:<br>
-    case ConversionSpecifier::uArg:<br>
-    case ConversionSpecifier::xArg:<br>
-    case ConversionSpecifier::XArg:<br>
-    case ConversionSpecifier::fArg:<br>
-    case ConversionSpecifier::FArg:<br>
-    case ConversionSpecifier::eArg:<br>
-    case ConversionSpecifier::EArg:<br>
-    case ConversionSpecifier::gArg:<br>
-    case ConversionSpecifier::GArg:<br>
-    case ConversionSpecifier::aArg:<br>
-    case ConversionSpecifier::AArg:<br>
-    case ConversionSpecifier::sArg:<br>
-    case ConversionSpecifier::pArg:<br>
-    case ConversionSpecifier::nArg:<br>
-    case ConversionSpecifier::ObjCObjArg:<br>
-    case ConversionSpecifier::ScanListArg:<br>
-    case ConversionSpecifier::PercentArg:<br>
-    case ConversionSpecifier::PArg:<br>
-      return true;<br>
-    case ConversionSpecifier::CArg:<br>
-    case ConversionSpecifier::SArg:<br>
-      return LangOpt.ObjC;<br>
-    case ConversionSpecifier::InvalidSpecifier:<br>
-    case ConversionSpecifier::FreeBSDbArg:<br>
-    case ConversionSpecifier::FreeBSDDArg:<br>
-    case ConversionSpecifier::FreeBSDrArg:<br>
-    case ConversionSpecifier::FreeBSDyArg:<br>
-    case ConversionSpecifier::PrintErrno:<br>
-    case ConversionSpecifier::DArg:<br>
-    case ConversionSpecifier::OArg:<br>
-    case ConversionSpecifier::UArg:<br>
-    case ConversionSpecifier::ZArg:<br>
-      return false;<br>
-  }<br>
-  llvm_unreachable("Invalid ConversionSpecifier Kind!");<br>
-}<br>
-<br>
-bool FormatSpecifier::hasStandardLengthConversionCombination() const {<br>
-  if (LM.getKind() == LengthModifier::AsLongDouble) {<br>
-    switch(CS.getKind()) {<br>
-        case ConversionSpecifier::dArg:<br>
-        case ConversionSpecifier::iArg:<br>
-        case ConversionSpecifier::oArg:<br>
-        case ConversionSpecifier::uArg:<br>
-        case ConversionSpecifier::xArg:<br>
-        case ConversionSpecifier::XArg:<br>
-          return false;<br>
-        default:<br>
-          return true;<br>
-    }<br>
-  }<br>
-  return true;<br>
-}<br>
-<br>
-Optional<LengthModifier> FormatSpecifier::getCorrectedLengthModifier() const {<br>
-  if (CS.isAnyIntArg() || CS.getKind() == ConversionSpecifier::nArg) {<br>
-    if (LM.getKind() == LengthModifier::AsLongDouble ||<br>
-        LM.getKind() == LengthModifier::AsQuad) {<br>
-      LengthModifier FixedLM(LM);<br>
-      FixedLM.setKind(LengthModifier::AsLongLong);<br>
-      return FixedLM;<br>
-    }<br>
-  }<br>
-<br>
-  return None;<br>
-}<br>
-<br>
-bool FormatSpecifier::namedTypeToLengthModifier(QualType QT,<br>
-                                                LengthModifier &LM) {<br>
-  assert(isa<TypedefType>(QT) && "Expected a TypedefType");<br>
-  const TypedefNameDecl *Typedef = cast<TypedefType>(QT)->getDecl();<br>
-<br>
-  for (;;) {<br>
-    const IdentifierInfo *Identifier = Typedef->getIdentifier();<br>
-    if (Identifier->getName() == "size_t") {<br>
-      LM.setKind(LengthModifier::AsSizeT);<br>
-      return true;<br>
-    } else if (Identifier->getName() == "ssize_t") {<br>
-      // Not C99, but common in Unix.<br>
-      LM.setKind(LengthModifier::AsSizeT);<br>
-      return true;<br>
-    } else if (Identifier->getName() == "intmax_t") {<br>
-      LM.setKind(LengthModifier::AsIntMax);<br>
-      return true;<br>
-    } else if (Identifier->getName() == "uintmax_t") {<br>
-      LM.setKind(LengthModifier::AsIntMax);<br>
-      return true;<br>
-    } else if (Identifier->getName() == "ptrdiff_t") {<br>
-      LM.setKind(LengthModifier::AsPtrDiff);<br>
-      return true;<br>
-    }<br>
-<br>
-    QualType T = Typedef->getUnderlyingType();<br>
-    if (!isa<TypedefType>(T))<br>
-      break;<br>
-<br>
-    Typedef = cast<TypedefType>(T)->getDecl();<br>
-  }<br>
-  return false;<br>
-}<br>
<br>
Removed: cfe/trunk/lib/Analysis/FormatStringParsing.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/FormatStringParsing.h?rev=345970&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/FormatStringParsing.h?rev=345970&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Analysis/FormatStringParsing.h (original)<br>
+++ cfe/trunk/lib/Analysis/FormatStringParsing.h (removed)<br>
@@ -1,79 +0,0 @@<br>
-#ifndef LLVM_CLANG_LIB_ANALYSIS_FORMATSTRINGPARSING_H<br>
-#define LLVM_CLANG_LIB_ANALYSIS_FORMATSTRINGPARSING_H<br>
-<br>
-#include "clang/AST/ASTContext.h"<br>
-#include "clang/AST/Type.h"<br>
-#include "clang/Analysis/Analyses/FormatString.h"<br>
-<br>
-namespace clang {<br>
-<br>
-class LangOptions;<br>
-<br>
-template <typename T><br>
-class UpdateOnReturn {<br>
-  T &ValueToUpdate;<br>
-  const T &ValueToCopy;<br>
-public:<br>
-  UpdateOnReturn(T &valueToUpdate, const T &valueToCopy)<br>
-    : ValueToUpdate(valueToUpdate), ValueToCopy(valueToCopy) {}<br>
-<br>
-  ~UpdateOnReturn() {<br>
-    ValueToUpdate = ValueToCopy;<br>
-  }<br>
-};<br>
-<br>
-namespace analyze_format_string {<br>
-<br>
-OptionalAmount ParseAmount(const char *&Beg, const char *E);<br>
-OptionalAmount ParseNonPositionAmount(const char *&Beg, const char *E,<br>
-                                      unsigned &argIndex);<br>
-<br>
-OptionalAmount ParsePositionAmount(FormatStringHandler &H,<br>
-                                   const char *Start, const char *&Beg,<br>
-                                   const char *E, PositionContext p);<br>
-<br>
-bool ParseFieldWidth(FormatStringHandler &H,<br>
-                     FormatSpecifier &CS,<br>
-                     const char *Start, const char *&Beg, const char *E,<br>
-                     unsigned *argIndex);<br>
-<br>
-bool ParseArgPosition(FormatStringHandler &H,<br>
-                      FormatSpecifier &CS, const char *Start,<br>
-                      const char *&Beg, const char *E);<br>
-<br>
-/// Returns true if a LengthModifier was parsed and installed in the<br>
-/// FormatSpecifier& argument, and false otherwise.<br>
-bool ParseLengthModifier(FormatSpecifier &FS, const char *&Beg, const char *E,<br>
-                         const LangOptions &LO, bool IsScanf = false);<br>
-<br>
-/// Returns true if the invalid specifier in \p SpecifierBegin is a UTF-8<br>
-/// string; check that it won't go further than \p FmtStrEnd and write<br>
-/// up the total size in \p Len.<br>
-bool ParseUTF8InvalidSpecifier(const char *SpecifierBegin,<br>
-                               const char *FmtStrEnd, unsigned &Len);<br>
-<br>
-template <typename T> class SpecifierResult {<br>
-  T FS;<br>
-  const char *Start;<br>
-  bool Stop;<br>
-public:<br>
-  SpecifierResult(bool stop = false)<br>
-  : Start(nullptr), Stop(stop) {}<br>
-  SpecifierResult(const char *start,<br>
-                  const T &fs)<br>
-  : FS(fs), Start(start), Stop(false) {}<br>
-<br>
-  const char *getStart() const { return Start; }<br>
-  bool shouldStop() const { return Stop; }<br>
-  bool hasValue() const { return Start != nullptr; }<br>
-  const T &getValue() const {<br>
-    assert(hasValue());<br>
-    return FS;<br>
-  }<br>
-  const T &getValue() { return FS; }<br>
-};<br>
-<br>
-} // end analyze_format_string namespace<br>
-} // end clang namespace<br>
-<br>
-#endif<br>
<br>
Removed: cfe/trunk/lib/Analysis/OSLog.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/OSLog.cpp?rev=345970&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/OSLog.cpp?rev=345970&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Analysis/OSLog.cpp (original)<br>
+++ cfe/trunk/lib/Analysis/OSLog.cpp (removed)<br>
@@ -1,203 +0,0 @@<br>
-// TODO: header template<br>
-<br>
-#include "clang/Analysis/Analyses/OSLog.h"<br>
-#include "clang/AST/Attr.h"<br>
-#include "clang/AST/Decl.h"<br>
-#include "clang/AST/DeclCXX.h"<br>
-#include "clang/AST/ExprObjC.h"<br>
-#include "clang/Analysis/Analyses/FormatString.h"<br>
-#include "clang/Basic/Builtins.h"<br>
-#include "llvm/ADT/SmallBitVector.h"<br>
-<br>
-using namespace clang;<br>
-<br>
-using clang::analyze_os_log::OSLogBufferItem;<br>
-using clang::analyze_os_log::OSLogBufferLayout;<br>
-<br>
-namespace {<br>
-class OSLogFormatStringHandler<br>
-    : public analyze_format_string::FormatStringHandler {<br>
-private:<br>
-  struct ArgData {<br>
-    const Expr *E = nullptr;<br>
-    Optional<OSLogBufferItem::Kind> Kind;<br>
-    Optional<unsigned> Size;<br>
-    Optional<const Expr *> Count;<br>
-    Optional<const Expr *> Precision;<br>
-    Optional<const Expr *> FieldWidth;<br>
-    unsigned char Flags = 0;<br>
-  };<br>
-  SmallVector<ArgData, 4> ArgsData;<br>
-  ArrayRef<const Expr *> Args;<br>
-<br>
-  OSLogBufferItem::Kind<br>
-  getKind(analyze_format_string::ConversionSpecifier::Kind K) {<br>
-    switch (K) {<br>
-    case clang::analyze_format_string::ConversionSpecifier::sArg: // "%s"<br>
-      return OSLogBufferItem::StringKind;<br>
-    case clang::analyze_format_string::ConversionSpecifier::SArg: // "%S"<br>
-      return OSLogBufferItem::WideStringKind;<br>
-    case clang::analyze_format_string::ConversionSpecifier::PArg: { // "%P"<br>
-      return OSLogBufferItem::PointerKind;<br>
-    case clang::analyze_format_string::ConversionSpecifier::ObjCObjArg: // "%@"<br>
-      return OSLogBufferItem::ObjCObjKind;<br>
-    case clang::analyze_format_string::ConversionSpecifier::PrintErrno: // "%m"<br>
-      return OSLogBufferItem::ErrnoKind;<br>
-    default:<br>
-      return OSLogBufferItem::ScalarKind;<br>
-    }<br>
-    }<br>
-  }<br>
-<br>
-public:<br>
-  OSLogFormatStringHandler(ArrayRef<const Expr *> Args) : Args(Args) {<br>
-    ArgsData.reserve(Args.size());<br>
-  }<br>
-<br>
-  virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,<br>
-                                     const char *StartSpecifier,<br>
-                                     unsigned SpecifierLen) {<br>
-    if (!FS.consumesDataArgument() &&<br>
-        FS.getConversionSpecifier().getKind() !=<br>
-            clang::analyze_format_string::ConversionSpecifier::PrintErrno)<br>
-      return true;<br>
-<br>
-    ArgsData.emplace_back();<br>
-    unsigned ArgIndex = FS.getArgIndex();<br>
-    if (ArgIndex < Args.size())<br>
-      ArgsData.back().E = Args[ArgIndex];<br>
-<br>
-    // First get the Kind<br>
-    ArgsData.back().Kind = getKind(FS.getConversionSpecifier().getKind());<br>
-    if (ArgsData.back().Kind != OSLogBufferItem::ErrnoKind &&<br>
-        !ArgsData.back().E) {<br>
-      // missing argument<br>
-      ArgsData.pop_back();<br>
-      return false;<br>
-    }<br>
-<br>
-    switch (FS.getConversionSpecifier().getKind()) {<br>
-    case clang::analyze_format_string::ConversionSpecifier::sArg:   // "%s"<br>
-    case clang::analyze_format_string::ConversionSpecifier::SArg: { // "%S"<br>
-      auto &precision = FS.getPrecision();<br>
-      switch (precision.getHowSpecified()) {<br>
-      case clang::analyze_format_string::OptionalAmount::NotSpecified: // "%s"<br>
-        break;<br>
-      case clang::analyze_format_string::OptionalAmount::Constant: // "%.16s"<br>
-        ArgsData.back().Size = precision.getConstantAmount();<br>
-        break;<br>
-      case clang::analyze_format_string::OptionalAmount::Arg: // "%.*s"<br>
-        ArgsData.back().Count = Args[precision.getArgIndex()];<br>
-        break;<br>
-      case clang::analyze_format_string::OptionalAmount::Invalid:<br>
-        return false;<br>
-      }<br>
-      break;<br>
-    }<br>
-    case clang::analyze_format_string::ConversionSpecifier::PArg: { // "%P"<br>
-      auto &precision = FS.getPrecision();<br>
-      switch (precision.getHowSpecified()) {<br>
-      case clang::analyze_format_string::OptionalAmount::NotSpecified: // "%P"<br>
-        return false; // length must be supplied with pointer format specifier<br>
-      case clang::analyze_format_string::OptionalAmount::Constant: // "%.16P"<br>
-        ArgsData.back().Size = precision.getConstantAmount();<br>
-        break;<br>
-      case clang::analyze_format_string::OptionalAmount::Arg: // "%.*P"<br>
-        ArgsData.back().Count = Args[precision.getArgIndex()];<br>
-        break;<br>
-      case clang::analyze_format_string::OptionalAmount::Invalid:<br>
-        return false;<br>
-      }<br>
-      break;<br>
-    }<br>
-    default:<br>
-      if (FS.getPrecision().hasDataArgument()) {<br>
-        ArgsData.back().Precision = Args[FS.getPrecision().getArgIndex()];<br>
-      }<br>
-      break;<br>
-    }<br>
-    if (FS.getFieldWidth().hasDataArgument()) {<br>
-      ArgsData.back().FieldWidth = Args[FS.getFieldWidth().getArgIndex()];<br>
-    }<br>
-<br>
-    if (FS.isPrivate()) {<br>
-      ArgsData.back().Flags |= OSLogBufferItem::IsPrivate;<br>
-    }<br>
-    if (FS.isPublic()) {<br>
-      ArgsData.back().Flags |= OSLogBufferItem::IsPublic;<br>
-    }<br>
-    return true;<br>
-  }<br>
-<br>
-  void computeLayout(ASTContext &Ctx, OSLogBufferLayout &Layout) const {<br>
-    Layout.Items.clear();<br>
-    for (auto &Data : ArgsData) {<br>
-      if (Data.FieldWidth) {<br>
-        CharUnits Size = Ctx.getTypeSizeInChars((*Data.FieldWidth)->getType());<br>
-        Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, *Data.FieldWidth,<br>
-                                  Size, 0);<br>
-      }<br>
-      if (Data.Precision) {<br>
-        CharUnits Size = Ctx.getTypeSizeInChars((*Data.Precision)->getType());<br>
-        Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, *Data.Precision,<br>
-                                  Size, 0);<br>
-      }<br>
-      if (Data.Count) {<br>
-        // "%.*P" has an extra "count" that we insert before the argument.<br>
-        CharUnits Size = Ctx.getTypeSizeInChars((*Data.Count)->getType());<br>
-        Layout.Items.emplace_back(OSLogBufferItem::CountKind, *Data.Count, Size,<br>
-                                  0);<br>
-      }<br>
-      if (Data.Size)<br>
-        Layout.Items.emplace_back(Ctx, CharUnits::fromQuantity(*Data.Size),<br>
-                                  Data.Flags);<br>
-      if (Data.Kind) {<br>
-        CharUnits Size;<br>
-        if (*Data.Kind == OSLogBufferItem::ErrnoKind)<br>
-          Size = CharUnits::Zero();<br>
-        else<br>
-          Size = Ctx.getTypeSizeInChars(Data.E->getType());<br>
-        Layout.Items.emplace_back(*Data.Kind, Data.E, Size, Data.Flags);<br>
-      } else {<br>
-        auto Size = Ctx.getTypeSizeInChars(Data.E->getType());<br>
-        Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, Data.E, Size,<br>
-                                  Data.Flags);<br>
-      }<br>
-    }<br>
-  }<br>
-};<br>
-} // end anonymous namespace<br>
-<br>
-bool clang::analyze_os_log::computeOSLogBufferLayout(<br>
-    ASTContext &Ctx, const CallExpr *E, OSLogBufferLayout &Layout) {<br>
-  ArrayRef<const Expr *> Args(E->getArgs(), E->getArgs() + E->getNumArgs());<br>
-<br>
-  const Expr *StringArg;<br>
-  ArrayRef<const Expr *> VarArgs;<br>
-  switch (E->getBuiltinCallee()) {<br>
-  case Builtin::BI__builtin_os_log_format_buffer_size:<br>
-    assert(E->getNumArgs() >= 1 &&<br>
-           "__builtin_os_log_format_buffer_size takes at least 1 argument");<br>
-    StringArg = E->getArg(0);<br>
-    VarArgs = Args.slice(1);<br>
-    break;<br>
-  case Builtin::BI__builtin_os_log_format:<br>
-    assert(E->getNumArgs() >= 2 &&<br>
-           "__builtin_os_log_format takes at least 2 arguments");<br>
-    StringArg = E->getArg(1);<br>
-    VarArgs = Args.slice(2);<br>
-    break;<br>
-  default:<br>
-    llvm_unreachable("non-os_log builtin passed to computeOSLogBufferLayout");<br>
-  }<br>
-<br>
-  const StringLiteral *Lit = cast<StringLiteral>(StringArg->IgnoreParenCasts());<br>
-  assert(Lit && (Lit->isAscii() || Lit->isUTF8()));<br>
-  StringRef Data = Lit->getString();<br>
-  OSLogFormatStringHandler H(VarArgs);<br>
-  ParsePrintfString(H, Data.begin(), Data.end(), Ctx.getLangOpts(),<br>
-                    Ctx.getTargetInfo(), /*isFreeBSDKPrintf*/ false);<br>
-<br>
-  H.computeLayout(Ctx, Layout);<br>
-  return true;<br>
-}<br>
<br>
Removed: cfe/trunk/lib/Analysis/PrintfFormatString.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/PrintfFormatString.cpp?rev=345970&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/PrintfFormatString.cpp?rev=345970&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Analysis/PrintfFormatString.cpp (original)<br>
+++ cfe/trunk/lib/Analysis/PrintfFormatString.cpp (removed)<br>
@@ -1,1029 +0,0 @@<br>
-//== PrintfFormatString.cpp - Analysis of printf format strings --*- C++ -*-==//<br>
-//<br>
-//                     The LLVM Compiler Infrastructure<br>
-//<br>
-// This file is distributed under the University of Illinois Open Source<br>
-// License. See LICENSE.TXT for details.<br>
-//<br>
-//===----------------------------------------------------------------------===//<br>
-//<br>
-// Handling of format string in printf and friends.  The structure of format<br>
-// strings for fprintf() are described in C99 7.19.6.1.<br>
-//<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-#include "clang/Analysis/Analyses/FormatString.h"<br>
-#include "clang/Analysis/Analyses/OSLog.h"<br>
-#include "FormatStringParsing.h"<br>
-#include "clang/Basic/TargetInfo.h"<br>
-<br>
-using clang::analyze_format_string::ArgType;<br>
-using clang::analyze_format_string::FormatStringHandler;<br>
-using clang::analyze_format_string::LengthModifier;<br>
-using clang::analyze_format_string::OptionalAmount;<br>
-using clang::analyze_format_string::ConversionSpecifier;<br>
-using clang::analyze_printf::PrintfSpecifier;<br>
-<br>
-using namespace clang;<br>
-<br>
-typedef clang::analyze_format_string::SpecifierResult<PrintfSpecifier><br>
-        PrintfSpecifierResult;<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Methods for parsing format strings.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-using analyze_format_string::ParseNonPositionAmount;<br>
-<br>
-static bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS,<br>
-                           const char *Start, const char *&Beg, const char *E,<br>
-                           unsigned *argIndex) {<br>
-  if (argIndex) {<br>
-    FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex));<br>
-  } else {<br>
-    const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E,<br>
-                                           analyze_format_string::PrecisionPos);<br>
-    if (Amt.isInvalid())<br>
-      return true;<br>
-    FS.setPrecision(Amt);<br>
-  }<br>
-  return false;<br>
-}<br>
-<br>
-static bool ParseObjCFlags(FormatStringHandler &H, PrintfSpecifier &FS,<br>
-                           const char *FlagBeg, const char *E, bool Warn) {<br>
-   StringRef Flag(FlagBeg, E - FlagBeg);<br>
-   // Currently there is only one flag.<br>
-   if (Flag == "tt") {<br>
-     FS.setHasObjCTechnicalTerm(FlagBeg);<br>
-     return false;<br>
-   }<br>
-   // Handle either the case of no flag or an invalid flag.<br>
-   if (Warn) {<br>
-     if (Flag == "")<br>
-       H.HandleEmptyObjCModifierFlag(FlagBeg, E  - FlagBeg);<br>
-     else<br>
-       H.HandleInvalidObjCModifierFlag(FlagBeg, E  - FlagBeg);<br>
-   }<br>
-   return true;<br>
-}<br>
-<br>
-static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,<br>
-                                                  const char *&Beg,<br>
-                                                  const char *E,<br>
-                                                  unsigned &argIndex,<br>
-                                                  const LangOptions &LO,<br>
-                                                  const TargetInfo &Target,<br>
-                                                  bool Warn,<br>
-                                                  bool isFreeBSDKPrintf) {<br>
-<br>
-  using namespace clang::analyze_format_string;<br>
-  using namespace clang::analyze_printf;<br>
-<br>
-  const char *I = Beg;<br>
-  const char *Start = nullptr;<br>
-  UpdateOnReturn <const char*> UpdateBeg(Beg, I);<br>
-<br>
-  // Look for a '%' character that indicates the start of a format specifier.<br>
-  for ( ; I != E ; ++I) {<br>
-    char c = *I;<br>
-    if (c == '\0') {<br>
-      // Detect spurious null characters, which are likely errors.<br>
-      H.HandleNullChar(I);<br>
-      return true;<br>
-    }<br>
-    if (c == '%') {<br>
-      Start = I++;  // Record the start of the format specifier.<br>
-      break;<br>
-    }<br>
-  }<br>
-<br>
-  // No format specifier found?<br>
-  if (!Start)<br>
-    return false;<br>
-<br>
-  if (I == E) {<br>
-    // No more characters left?<br>
-    if (Warn)<br>
-      H.HandleIncompleteSpecifier(Start, E - Start);<br>
-    return true;<br>
-  }<br>
-<br>
-  PrintfSpecifier FS;<br>
-  if (ParseArgPosition(H, FS, Start, I, E))<br>
-    return true;<br>
-<br>
-  if (I == E) {<br>
-    // No more characters left?<br>
-    if (Warn)<br>
-      H.HandleIncompleteSpecifier(Start, E - Start);<br>
-    return true;<br>
-  }<br>
-<br>
-  if (*I == '{') {<br>
-    ++I;<br>
-    unsigned char PrivacyFlags = 0;<br>
-    StringRef MatchedStr;<br>
-<br>
-    do {<br>
-      StringRef Str(I, E - I);<br>
-      std::string Match = "^[\t\n\v\f\r ]*(private|public)[\t\n\v\f\r ]*(,|})";<br>
-      llvm::Regex R(Match);<br>
-      SmallVector<StringRef, 2> Matches;<br>
-<br>
-      if (R.match(Str, &Matches)) {<br>
-        MatchedStr = Matches[1];<br>
-        I += Matches[0].size();<br>
-<br>
-        // Set the privacy flag if the privacy annotation in the<br>
-        // comma-delimited segment is at least as strict as the privacy<br>
-        // annotations in previous comma-delimited segments.<br>
-        if (MatchedStr.equals("private"))<br>
-          PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPrivate;<br>
-        else if (PrivacyFlags == 0 && MatchedStr.equals("public"))<br>
-          PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPublic;<br>
-      } else {<br>
-        size_t CommaOrBracePos =<br>
-            Str.find_if([](char c) { return c == ',' || c == '}'; });<br>
-<br>
-        if (CommaOrBracePos == StringRef::npos) {<br>
-          // Neither a comma nor the closing brace was found.<br>
-          if (Warn)<br>
-            H.HandleIncompleteSpecifier(Start, E - Start);<br>
-          return true;<br>
-        }<br>
-<br>
-        I += CommaOrBracePos + 1;<br>
-      }<br>
-      // Continue until the closing brace is found.<br>
-    } while (*(I - 1) == ',');<br>
-<br>
-    // Set the privacy flag.<br>
-    switch (PrivacyFlags) {<br>
-    case 0:<br>
-      break;<br>
-    case clang::analyze_os_log::OSLogBufferItem::IsPrivate:<br>
-      FS.setIsPrivate(MatchedStr.data());<br>
-      break;<br>
-    case clang::analyze_os_log::OSLogBufferItem::IsPublic:<br>
-      FS.setIsPublic(MatchedStr.data());<br>
-      break;<br>
-    default:<br>
-      llvm_unreachable("Unexpected privacy flag value");<br>
-    }<br>
-  }<br>
-<br>
-  // Look for flags (if any).<br>
-  bool hasMore = true;<br>
-  for ( ; I != E; ++I) {<br>
-    switch (*I) {<br>
-      default: hasMore = false; break;<br>
-      case '\'':<br>
-        // FIXME: POSIX specific.  Always accept?<br>
-        FS.setHasThousandsGrouping(I);<br>
-        break;<br>
-      case '-': FS.setIsLeftJustified(I); break;<br>
-      case '+': FS.setHasPlusPrefix(I); break;<br>
-      case ' ': FS.setHasSpacePrefix(I); break;<br>
-      case '#': FS.setHasAlternativeForm(I); break;<br>
-      case '0': FS.setHasLeadingZeros(I); break;<br>
-    }<br>
-    if (!hasMore)<br>
-      break;<br>
-  }<br>
-<br>
-  if (I == E) {<br>
-    // No more characters left?<br>
-    if (Warn)<br>
-      H.HandleIncompleteSpecifier(Start, E - Start);<br>
-    return true;<br>
-  }<br>
-<br>
-  // Look for the field width (if any).<br>
-  if (ParseFieldWidth(H, FS, Start, I, E,<br>
-                      FS.usesPositionalArg() ? nullptr : &argIndex))<br>
-    return true;<br>
-<br>
-  if (I == E) {<br>
-    // No more characters left?<br>
-    if (Warn)<br>
-      H.HandleIncompleteSpecifier(Start, E - Start);<br>
-    return true;<br>
-  }<br>
-<br>
-  // Look for the precision (if any).<br>
-  if (*I == '.') {<br>
-    ++I;<br>
-    if (I == E) {<br>
-      if (Warn)<br>
-        H.HandleIncompleteSpecifier(Start, E - Start);<br>
-      return true;<br>
-    }<br>
-<br>
-    if (ParsePrecision(H, FS, Start, I, E,<br>
-                       FS.usesPositionalArg() ? nullptr : &argIndex))<br>
-      return true;<br>
-<br>
-    if (I == E) {<br>
-      // No more characters left?<br>
-      if (Warn)<br>
-        H.HandleIncompleteSpecifier(Start, E - Start);<br>
-      return true;<br>
-    }<br>
-  }<br>
-<br>
-  // Look for the length modifier.<br>
-  if (ParseLengthModifier(FS, I, E, LO) && I == E) {<br>
-    // No more characters left?<br>
-    if (Warn)<br>
-      H.HandleIncompleteSpecifier(Start, E - Start);<br>
-    return true;<br>
-  }<br>
-<br>
-  // Look for the Objective-C modifier flags, if any.<br>
-  // We parse these here, even if they don't apply to<br>
-  // the conversion specifier, and then emit an error<br>
-  // later if the conversion specifier isn't '@'.  This<br>
-  // enables better recovery, and we don't know if<br>
-  // these flags are applicable until later.<br>
-  const char *ObjCModifierFlagsStart = nullptr,<br>
-             *ObjCModifierFlagsEnd = nullptr;<br>
-  if (*I == '[') {<br>
-    ObjCModifierFlagsStart = I;<br>
-    ++I;<br>
-    auto flagStart = I;<br>
-    for (;; ++I) {<br>
-      ObjCModifierFlagsEnd = I;<br>
-      if (I == E) {<br>
-        if (Warn)<br>
-          H.HandleIncompleteSpecifier(Start, E - Start);<br>
-        return true;<br>
-      }<br>
-      // Did we find the closing ']'?<br>
-      if (*I == ']') {<br>
-        if (ParseObjCFlags(H, FS, flagStart, I, Warn))<br>
-          return true;<br>
-        ++I;<br>
-        break;<br>
-      }<br>
-      // There are no separators defined yet for multiple<br>
-      // Objective-C modifier flags.  When those are<br>
-      // defined, this is the place to check.<br>
-    }<br>
-  }<br>
-<br>
-  if (*I == '\0') {<br>
-    // Detect spurious null characters, which are likely errors.<br>
-    H.HandleNullChar(I);<br>
-    return true;<br>
-  }<br>
-<br>
-  // Finally, look for the conversion specifier.<br>
-  const char *conversionPosition = I++;<br>
-  ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier;<br>
-  switch (*conversionPosition) {<br>
-    default:<br>
-      break;<br>
-    // C99: 7.19.6.1 (section 8).<br>
-    case '%': k = ConversionSpecifier::PercentArg;   break;<br>
-    case 'A': k = ConversionSpecifier::AArg; break;<br>
-    case 'E': k = ConversionSpecifier::EArg; break;<br>
-    case 'F': k = ConversionSpecifier::FArg; break;<br>
-    case 'G': k = ConversionSpecifier::GArg; break;<br>
-    case 'X': k = ConversionSpecifier::XArg; break;<br>
-    case 'a': k = ConversionSpecifier::aArg; break;<br>
-    case 'c': k = ConversionSpecifier::cArg; break;<br>
-    case 'd': k = ConversionSpecifier::dArg; break;<br>
-    case 'e': k = ConversionSpecifier::eArg; break;<br>
-    case 'f': k = ConversionSpecifier::fArg; break;<br>
-    case 'g': k = ConversionSpecifier::gArg; break;<br>
-    case 'i': k = ConversionSpecifier::iArg; break;<br>
-    case 'n': k = ConversionSpecifier::nArg; break;<br>
-    case 'o': k = ConversionSpecifier::oArg; break;<br>
-    case 'p': k = ConversionSpecifier::pArg; break;<br>
-    case 's': k = ConversionSpecifier::sArg; break;<br>
-    case 'u': k = ConversionSpecifier::uArg; break;<br>
-    case 'x': k = ConversionSpecifier::xArg; break;<br>
-    // POSIX specific.<br>
-    case 'C': k = ConversionSpecifier::CArg; break;<br>
-    case 'S': k = ConversionSpecifier::SArg; break;<br>
-    // Apple extension for os_log<br>
-    case 'P':<br>
-      k = ConversionSpecifier::PArg;<br>
-      break;<br>
-    // Objective-C.<br>
-    case '@': k = ConversionSpecifier::ObjCObjArg; break;<br>
-    // Glibc specific.<br>
-    case 'm': k = ConversionSpecifier::PrintErrno; break;<br>
-    // FreeBSD kernel specific.<br>
-    case 'b':<br>
-      if (isFreeBSDKPrintf)<br>
-        k = ConversionSpecifier::FreeBSDbArg; // int followed by char *<br>
-      break;<br>
-    case 'r':<br>
-      if (isFreeBSDKPrintf)<br>
-        k = ConversionSpecifier::FreeBSDrArg; // int<br>
-      break;<br>
-    case 'y':<br>
-      if (isFreeBSDKPrintf)<br>
-        k = ConversionSpecifier::FreeBSDyArg; // int<br>
-      break;<br>
-    // Apple-specific.<br>
-    case 'D':<br>
-      if (isFreeBSDKPrintf)<br>
-        k = ConversionSpecifier::FreeBSDDArg; // void * followed by char *<br>
-      else if (Target.getTriple().isOSDarwin())<br>
-        k = ConversionSpecifier::DArg;<br>
-      break;<br>
-    case 'O':<br>
-      if (Target.getTriple().isOSDarwin())<br>
-        k = ConversionSpecifier::OArg;<br>
-      break;<br>
-    case 'U':<br>
-      if (Target.getTriple().isOSDarwin())<br>
-        k = ConversionSpecifier::UArg;<br>
-      break;<br>
-    // MS specific.<br>
-    case 'Z':<br>
-      if (Target.getTriple().isOSMSVCRT())<br>
-        k = ConversionSpecifier::ZArg;<br>
-  }<br>
-<br>
-  // Check to see if we used the Objective-C modifier flags with<br>
-  // a conversion specifier other than '@'.<br>
-  if (k != ConversionSpecifier::ObjCObjArg &&<br>
-      k != ConversionSpecifier::InvalidSpecifier &&<br>
-      ObjCModifierFlagsStart) {<br>
-    H.HandleObjCFlagsWithNonObjCConversion(ObjCModifierFlagsStart,<br>
-                                           ObjCModifierFlagsEnd + 1,<br>
-                                           conversionPosition);<br>
-    return true;<br>
-  }<br>
-<br>
-  PrintfConversionSpecifier CS(conversionPosition, k);<br>
-  FS.setConversionSpecifier(CS);<br>
-  if (CS.consumesDataArgument() && !FS.usesPositionalArg())<br>
-    FS.setArgIndex(argIndex++);<br>
-  // FreeBSD kernel specific.<br>
-  if (k == ConversionSpecifier::FreeBSDbArg ||<br>
-      k == ConversionSpecifier::FreeBSDDArg)<br>
-    argIndex++;<br>
-<br>
-  if (k == ConversionSpecifier::InvalidSpecifier) {<br>
-    unsigned Len = I - Start;<br>
-    if (ParseUTF8InvalidSpecifier(Start, E, Len)) {<br>
-      CS.setEndScanList(Start + Len);<br>
-      FS.setConversionSpecifier(CS);<br>
-    }<br>
-    // Assume the conversion takes one argument.<br>
-    return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, Len);<br>
-  }<br>
-  return PrintfSpecifierResult(Start, FS);<br>
-}<br>
-<br>
-bool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H,<br>
-                                                     const char *I,<br>
-                                                     const char *E,<br>
-                                                     const LangOptions &LO,<br>
-                                                     const TargetInfo &Target,<br>
-                                                     bool isFreeBSDKPrintf) {<br>
-<br>
-  unsigned argIndex = 0;<br>
-<br>
-  // Keep looking for a format specifier until we have exhausted the string.<br>
-  while (I != E) {<br>
-    const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,<br>
-                                                            LO, Target, true,<br>
-                                                            isFreeBSDKPrintf);<br>
-    // Did a fail-stop error of any kind occur when parsing the specifier?<br>
-    // If so, don't do any more processing.<br>
-    if (FSR.shouldStop())<br>
-      return true;<br>
-    // Did we exhaust the string or encounter an error that<br>
-    // we can recover from?<br>
-    if (!FSR.hasValue())<br>
-      continue;<br>
-    // We have a format specifier.  Pass it to the callback.<br>
-    if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),<br>
-                                 I - FSR.getStart()))<br>
-      return true;<br>
-  }<br>
-  assert(I == E && "Format string not exhausted");<br>
-  return false;<br>
-}<br>
-<br>
-bool clang::analyze_format_string::ParseFormatStringHasSArg(const char *I,<br>
-                                                            const char *E,<br>
-                                                            const LangOptions &LO,<br>
-                                                            const TargetInfo &Target) {<br>
-<br>
-  unsigned argIndex = 0;<br>
-<br>
-  // Keep looking for a %s format specifier until we have exhausted the string.<br>
-  FormatStringHandler H;<br>
-  while (I != E) {<br>
-    const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,<br>
-                                                            LO, Target, false,<br>
-                                                            false);<br>
-    // Did a fail-stop error of any kind occur when parsing the specifier?<br>
-    // If so, don't do any more processing.<br>
-    if (FSR.shouldStop())<br>
-      return false;<br>
-    // Did we exhaust the string or encounter an error that<br>
-    // we can recover from?<br>
-    if (!FSR.hasValue())<br>
-      continue;<br>
-    const analyze_printf::PrintfSpecifier &FS = FSR.getValue();<br>
-    // Return true if this a %s format specifier.<br>
-    if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::Kind::sArg)<br>
-      return true;<br>
-  }<br>
-  return false;<br>
-}<br>
-<br>
-//===----------------------------------------------------------------------===//<br>
-// Methods on PrintfSpecifier.<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,<br>
-                                    bool IsObjCLiteral) const {<br>
-  const PrintfConversionSpecifier &CS = getConversionSpecifier();<br>
-<br>
-  if (!CS.consumesDataArgument())<br>
-    return ArgType::Invalid();<br>
-<br>
-  if (CS.getKind() == ConversionSpecifier::cArg)<br>
-    switch (LM.getKind()) {<br>
-      case LengthModifier::None:<br>
-        return Ctx.IntTy;<br>
-      case LengthModifier::AsLong:<br>
-      case LengthModifier::AsWide:<br>
-        return ArgType(ArgType::WIntTy, "wint_t");<br>
-      case LengthModifier::AsShort:<br>
-        if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())<br>
-          return Ctx.IntTy;<br>
-        LLVM_FALLTHROUGH;<br>
-      default:<br>
-        return ArgType::Invalid();<br>
-    }<br>
-<br>
-  if (CS.isIntArg())<br>
-    switch (LM.getKind()) {<br>
-      case LengthModifier::AsLongDouble:<br>
-        // GNU extension.<br>
-        return Ctx.LongLongTy;<br>
-      case LengthModifier::None:<br>
-        return Ctx.IntTy;<br>
-      case LengthModifier::AsInt32:<br>
-        return ArgType(Ctx.IntTy, "__int32");<br>
-      case LengthModifier::AsChar: return ArgType::AnyCharTy;<br>
-      case LengthModifier::AsShort: return Ctx.ShortTy;<br>
-      case LengthModifier::AsLong: return Ctx.LongTy;<br>
-      case LengthModifier::AsLongLong:<br>
-      case LengthModifier::AsQuad:<br>
-        return Ctx.LongLongTy;<br>
-      case LengthModifier::AsInt64:<br>
-        return ArgType(Ctx.LongLongTy, "__int64");<br>
-      case LengthModifier::AsIntMax:<br>
-        return ArgType(Ctx.getIntMaxType(), "intmax_t");<br>
-      case LengthModifier::AsSizeT:<br>
-        return ArgType::makeSizeT(ArgType(Ctx.getSignedSizeType(), "ssize_t"));<br>
-      case LengthModifier::AsInt3264:<br>
-        return Ctx.getTargetInfo().getTriple().isArch64Bit()<br>
-                   ? ArgType(Ctx.LongLongTy, "__int64")<br>
-                   : ArgType(Ctx.IntTy, "__int32");<br>
-      case LengthModifier::AsPtrDiff:<br>
-        return ArgType::makePtrdiffT(<br>
-            ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));<br>
-      case LengthModifier::AsAllocate:<br>
-      case LengthModifier::AsMAllocate:<br>
-      case LengthModifier::AsWide:<br>
-        return ArgType::Invalid();<br>
-    }<br>
-<br>
-  if (CS.isUIntArg())<br>
-    switch (LM.getKind()) {<br>
-      case LengthModifier::AsLongDouble:<br>
-        // GNU extension.<br>
-        return Ctx.UnsignedLongLongTy;<br>
-      case LengthModifier::None:<br>
-        return Ctx.UnsignedIntTy;<br>
-      case LengthModifier::AsInt32:<br>
-        return ArgType(Ctx.UnsignedIntTy, "unsigned __int32");<br>
-      case LengthModifier::AsChar: return Ctx.UnsignedCharTy;<br>
-      case LengthModifier::AsShort: return Ctx.UnsignedShortTy;<br>
-      case LengthModifier::AsLong: return Ctx.UnsignedLongTy;<br>
-      case LengthModifier::AsLongLong:<br>
-      case LengthModifier::AsQuad:<br>
-        return Ctx.UnsignedLongLongTy;<br>
-      case LengthModifier::AsInt64:<br>
-        return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64");<br>
-      case LengthModifier::AsIntMax:<br>
-        return ArgType(Ctx.getUIntMaxType(), "uintmax_t");<br>
-      case LengthModifier::AsSizeT:<br>
-        return ArgType::makeSizeT(ArgType(Ctx.getSizeType(), "size_t"));<br>
-      case LengthModifier::AsInt3264:<br>
-        return Ctx.getTargetInfo().getTriple().isArch64Bit()<br>
-                   ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")<br>
-                   : ArgType(Ctx.UnsignedIntTy, "unsigned __int32");<br>
-      case LengthModifier::AsPtrDiff:<br>
-        return ArgType::makePtrdiffT(<br>
-            ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"));<br>
-      case LengthModifier::AsAllocate:<br>
-      case LengthModifier::AsMAllocate:<br>
-      case LengthModifier::AsWide:<br>
-        return ArgType::Invalid();<br>
-    }<br>
-<br>
-  if (CS.isDoubleArg()) {<br>
-    if (LM.getKind() == LengthModifier::AsLongDouble)<br>
-      return Ctx.LongDoubleTy;<br>
-    return Ctx.DoubleTy;<br>
-  }<br>
-<br>
-  if (CS.getKind() == ConversionSpecifier::nArg) {<br>
-    switch (LM.getKind()) {<br>
-      case LengthModifier::None:<br>
-        return ArgType::PtrTo(Ctx.IntTy);<br>
-      case LengthModifier::AsChar:<br>
-        return ArgType::PtrTo(Ctx.SignedCharTy);<br>
-      case LengthModifier::AsShort:<br>
-        return ArgType::PtrTo(Ctx.ShortTy);<br>
-      case LengthModifier::AsLong:<br>
-        return ArgType::PtrTo(Ctx.LongTy);<br>
-      case LengthModifier::AsLongLong:<br>
-      case LengthModifier::AsQuad:<br>
-        return ArgType::PtrTo(Ctx.LongLongTy);<br>
-      case LengthModifier::AsIntMax:<br>
-        return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));<br>
-      case LengthModifier::AsSizeT:<br>
-        return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));<br>
-      case LengthModifier::AsPtrDiff:<br>
-        return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));<br>
-      case LengthModifier::AsLongDouble:<br>
-        return ArgType(); // FIXME: Is this a known extension?<br>
-      case LengthModifier::AsAllocate:<br>
-      case LengthModifier::AsMAllocate:<br>
-      case LengthModifier::AsInt32:<br>
-      case LengthModifier::AsInt3264:<br>
-      case LengthModifier::AsInt64:<br>
-      case LengthModifier::AsWide:<br>
-        return ArgType::Invalid();<br>
-    }<br>
-  }<br>
-<br>
-  switch (CS.getKind()) {<br>
-    case ConversionSpecifier::sArg:<br>
-      if (LM.getKind() == LengthModifier::AsWideChar) {<br>
-        if (IsObjCLiteral)<br>
-          return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),<br>
-                         "const unichar *");<br>
-        return ArgType(ArgType::WCStrTy, "wchar_t *");<br>
-      }<br>
-      if (LM.getKind() == LengthModifier::AsWide)<br>
-        return ArgType(ArgType::WCStrTy, "wchar_t *");<br>
-      return ArgType::CStrTy;<br>
-    case ConversionSpecifier::SArg:<br>
-      if (IsObjCLiteral)<br>
-        return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),<br>
-                       "const unichar *");<br>
-      if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&<br>
-          LM.getKind() == LengthModifier::AsShort)<br>
-        return ArgType::CStrTy;<br>
-      return ArgType(ArgType::WCStrTy, "wchar_t *");<br>
-    case ConversionSpecifier::CArg:<br>
-      if (IsObjCLiteral)<br>
-        return ArgType(Ctx.UnsignedShortTy, "unichar");<br>
-      if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&<br>
-          LM.getKind() == LengthModifier::AsShort)<br>
-        return Ctx.IntTy;<br>
-      return ArgType(Ctx.WideCharTy, "wchar_t");<br>
-    case ConversionSpecifier::pArg:<br>
-    case ConversionSpecifier::PArg:<br>
-      return ArgType::CPointerTy;<br>
-    case ConversionSpecifier::ObjCObjArg:<br>
-      return ArgType::ObjCPointerTy;<br>
-    default:<br>
-      break;<br>
-  }<br>
-<br>
-  // FIXME: Handle other cases.<br>
-  return ArgType();<br>
-}<br>
-<br>
-bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,<br>
-                              ASTContext &Ctx, bool IsObjCLiteral) {<br>
-  // %n is different from other conversion specifiers; don't try to fix it.<br>
-  if (CS.getKind() == ConversionSpecifier::nArg)<br>
-    return false;<br>
-<br>
-  // Handle Objective-C objects first. Note that while the '%@' specifier will<br>
-  // not warn for structure pointer or void pointer arguments (because that's<br>
-  // how CoreFoundation objects are implemented), we only show a fixit for '%@'<br>
-  // if we know it's an object (block, id, class, or __attribute__((NSObject))).<br>
-  if (QT->isObjCRetainableType()) {<br>
-    if (!IsObjCLiteral)<br>
-      return false;<br>
-<br>
-    CS.setKind(ConversionSpecifier::ObjCObjArg);<br>
-<br>
-    // Disable irrelevant flags<br>
-    HasThousandsGrouping = false;<br>
-    HasPlusPrefix = false;<br>
-    HasSpacePrefix = false;<br>
-    HasAlternativeForm = false;<br>
-    HasLeadingZeroes = false;<br>
-    Precision.setHowSpecified(OptionalAmount::NotSpecified);<br>
-    LM.setKind(LengthModifier::None);<br>
-<br>
-    return true;<br>
-  }<br>
-<br>
-  // Handle strings next (char *, wchar_t *)<br>
-  if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {<br>
-    CS.setKind(ConversionSpecifier::sArg);<br>
-<br>
-    // Disable irrelevant flags<br>
-    HasAlternativeForm = 0;<br>
-    HasLeadingZeroes = 0;<br>
-<br>
-    // Set the long length modifier for wide characters<br>
-    if (QT->getPointeeType()->isWideCharType())<br>
-      LM.setKind(LengthModifier::AsWideChar);<br>
-    else<br>
-      LM.setKind(LengthModifier::None);<br>
-<br>
-    return true;<br>
-  }<br>
-<br>
-  // If it's an enum, get its underlying type.<br>
-  if (const EnumType *ETy = QT->getAs<EnumType>())<br>
-    QT = ETy->getDecl()->getIntegerType();<br>
-<br>
-  // We can only work with builtin types.<br>
-  const BuiltinType *BT = QT->getAs<BuiltinType>();<br>
-  if (!BT)<br>
-    return false;<br>
-<br>
-  // Set length modifier<br>
-  switch (BT->getKind()) {<br>
-  case BuiltinType::Bool:<br>
-  case BuiltinType::WChar_U:<br>
-  case BuiltinType::WChar_S:<br>
-  case BuiltinType::Char8: // FIXME: Treat like 'char'?<br>
-  case BuiltinType::Char16:<br>
-  case BuiltinType::Char32:<br>
-  case BuiltinType::UInt128:<br>
-  case BuiltinType::Int128:<br>
-  case BuiltinType::Half:<br>
-  case BuiltinType::Float16:<br>
-  case BuiltinType::Float128:<br>
-  case BuiltinType::ShortAccum:<br>
-  case BuiltinType::Accum:<br>
-  case BuiltinType::LongAccum:<br>
-  case BuiltinType::UShortAccum:<br>
-  case BuiltinType::UAccum:<br>
-  case BuiltinType::ULongAccum:<br>
-  case BuiltinType::ShortFract:<br>
-  case BuiltinType::Fract:<br>
-  case BuiltinType::LongFract:<br>
-  case BuiltinType::UShortFract:<br>
-  case BuiltinType::UFract:<br>
-  case BuiltinType::ULongFract:<br>
-  case BuiltinType::SatShortAccum:<br>
-  case BuiltinType::SatAccum:<br>
-  case BuiltinType::SatLongAccum:<br>
-  case BuiltinType::SatUShortAccum:<br>
-  case BuiltinType::SatUAccum:<br>
-  case BuiltinType::SatULongAccum:<br>
-  case BuiltinType::SatShortFract:<br>
-  case BuiltinType::SatFract:<br>
-  case BuiltinType::SatLongFract:<br>
-  case BuiltinType::SatUShortFract:<br>
-  case BuiltinType::SatUFract:<br>
-  case BuiltinType::SatULongFract:<br>
-    // Various types which are non-trivial to correct.<br>
-    return false;<br>
-<br>
-#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \<br>
-  case BuiltinType::Id:<br>
-#include "clang/Basic/OpenCLImageTypes.def"<br>
-#define SIGNED_TYPE(Id, SingletonId)<br>
-#define UNSIGNED_TYPE(Id, SingletonId)<br>
-#define FLOATING_TYPE(Id, SingletonId)<br>
-#define BUILTIN_TYPE(Id, SingletonId) \<br>
-  case BuiltinType::Id:<br>
-#include "clang/AST/BuiltinTypes.def"<br>
-    // Misc other stuff which doesn't make sense here.<br>
-    return false;<br>
-<br>
-  case BuiltinType::UInt:<br>
-  case BuiltinType::Int:<br>
-  case BuiltinType::Float:<br>
-  case BuiltinType::Double:<br>
-    LM.setKind(LengthModifier::None);<br>
-    break;<br>
-<br>
-  case BuiltinType::Char_U:<br>
-  case BuiltinType::UChar:<br>
-  case BuiltinType::Char_S:<br>
-  case BuiltinType::SChar:<br>
-    LM.setKind(LengthModifier::AsChar);<br>
-    break;<br>
-<br>
-  case BuiltinType::Short:<br>
-  case BuiltinType::UShort:<br>
-    LM.setKind(LengthModifier::AsShort);<br>
-    break;<br>
-<br>
-  case BuiltinType::Long:<br>
-  case BuiltinType::ULong:<br>
-    LM.setKind(LengthModifier::AsLong);<br>
-    break;<br>
-<br>
-  case BuiltinType::LongLong:<br>
-  case BuiltinType::ULongLong:<br>
-    LM.setKind(LengthModifier::AsLongLong);<br>
-    break;<br>
-<br>
-  case BuiltinType::LongDouble:<br>
-    LM.setKind(LengthModifier::AsLongDouble);<br>
-    break;<br>
-  }<br>
-<br>
-  // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.<br>
-  if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11))<br>
-    namedTypeToLengthModifier(QT, LM);<br>
-<br>
-  // If fixing the length modifier was enough, we might be done.<br>
-  if (hasValidLengthModifier(Ctx.getTargetInfo())) {<br>
-    // If we're going to offer a fix anyway, make sure the sign matches.<br>
-    switch (CS.getKind()) {<br>
-    case ConversionSpecifier::uArg:<br>
-    case ConversionSpecifier::UArg:<br>
-      if (QT->isSignedIntegerType())<br>
-        CS.setKind(clang::analyze_format_string::ConversionSpecifier::dArg);<br>
-      break;<br>
-    case ConversionSpecifier::dArg:<br>
-    case ConversionSpecifier::DArg:<br>
-    case ConversionSpecifier::iArg:<br>
-      if (QT->isUnsignedIntegerType() && !HasPlusPrefix)<br>
-        CS.setKind(clang::analyze_format_string::ConversionSpecifier::uArg);<br>
-      break;<br>
-    default:<br>
-      // Other specifiers do not have signed/unsigned variants.<br>
-      break;<br>
-    }<br>
-<br>
-    const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral);<br>
-    if (ATR.isValid() && ATR.matchesType(Ctx, QT))<br>
-      return true;<br>
-  }<br>
-<br>
-  // Set conversion specifier and disable any flags which do not apply to it.<br>
-  // Let typedefs to char fall through to int, as %c is silly for uint8_t.<br>
-  if (!isa<TypedefType>(QT) && QT->isCharType()) {<br>
-    CS.setKind(ConversionSpecifier::cArg);<br>
-    LM.setKind(LengthModifier::None);<br>
-    Precision.setHowSpecified(OptionalAmount::NotSpecified);<br>
-    HasAlternativeForm = 0;<br>
-    HasLeadingZeroes = 0;<br>
-    HasPlusPrefix = 0;<br>
-  }<br>
-  // Test for Floating type first as LongDouble can pass isUnsignedIntegerType<br>
-  else if (QT->isRealFloatingType()) {<br>
-    CS.setKind(ConversionSpecifier::fArg);<br>
-  }<br>
-  else if (QT->isSignedIntegerType()) {<br>
-    CS.setKind(ConversionSpecifier::dArg);<br>
-    HasAlternativeForm = 0;<br>
-  }<br>
-  else if (QT->isUnsignedIntegerType()) {<br>
-    CS.setKind(ConversionSpecifier::uArg);<br>
-    HasAlternativeForm = 0;<br>
-    HasPlusPrefix = 0;<br>
-  } else {<br>
-    llvm_unreachable("Unexpected type");<br>
-  }<br>
-<br>
-  return true;<br>
-}<br>
-<br>
-void PrintfSpecifier::toString(raw_ostream &os) const {<br>
-  // Whilst some features have no defined order, we are using the order<br>
-  // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)<br>
-  os << "%";<br>
-<br>
-  // Positional args<br>
-  if (usesPositionalArg()) {<br>
-    os << getPositionalArgIndex() << "$";<br>
-  }<br>
-<br>
-  // Conversion flags<br>
-  if (IsLeftJustified)    os << "-";<br>
-  if (HasPlusPrefix)      os << "+";<br>
-  if (HasSpacePrefix)     os << " ";<br>
-  if (HasAlternativeForm) os << "#";<br>
-  if (HasLeadingZeroes)   os << "0";<br>
-<br>
-  // Minimum field width<br>
-  FieldWidth.toString(os);<br>
-  // Precision<br>
-  Precision.toString(os);<br>
-  // Length modifier<br>
-  os << LM.toString();<br>
-  // Conversion specifier<br>
-  os << CS.toString();<br>
-}<br>
-<br>
-bool PrintfSpecifier::hasValidPlusPrefix() const {<br>
-  if (!HasPlusPrefix)<br>
-    return true;<br>
-<br>
-  // The plus prefix only makes sense for signed conversions<br>
-  switch (CS.getKind()) {<br>
-  case ConversionSpecifier::dArg:<br>
-  case ConversionSpecifier::DArg:<br>
-  case ConversionSpecifier::iArg:<br>
-  case ConversionSpecifier::fArg:<br>
-  case ConversionSpecifier::FArg:<br>
-  case ConversionSpecifier::eArg:<br>
-  case ConversionSpecifier::EArg:<br>
-  case ConversionSpecifier::gArg:<br>
-  case ConversionSpecifier::GArg:<br>
-  case ConversionSpecifier::aArg:<br>
-  case ConversionSpecifier::AArg:<br>
-  case ConversionSpecifier::FreeBSDrArg:<br>
-  case ConversionSpecifier::FreeBSDyArg:<br>
-    return true;<br>
-<br>
-  default:<br>
-    return false;<br>
-  }<br>
-}<br>
-<br>
-bool PrintfSpecifier::hasValidAlternativeForm() const {<br>
-  if (!HasAlternativeForm)<br>
-    return true;<br>
-<br>
-  // Alternate form flag only valid with the oxXaAeEfFgG conversions<br>
-  switch (CS.getKind()) {<br>
-  case ConversionSpecifier::oArg:<br>
-  case ConversionSpecifier::OArg:<br>
-  case ConversionSpecifier::xArg:<br>
-  case ConversionSpecifier::XArg:<br>
-  case ConversionSpecifier::aArg:<br>
-  case ConversionSpecifier::AArg:<br>
-  case ConversionSpecifier::eArg:<br>
-  case ConversionSpecifier::EArg:<br>
-  case ConversionSpecifier::fArg:<br>
-  case ConversionSpecifier::FArg:<br>
-  case ConversionSpecifier::gArg:<br>
-  case ConversionSpecifier::GArg:<br>
-  case ConversionSpecifier::FreeBSDrArg:<br>
-  case ConversionSpecifier::FreeBSDyArg:<br>
-    return true;<br>
-<br>
-  default:<br>
-    return false;<br>
-  }<br>
-}<br>
-<br>
-bool PrintfSpecifier::hasValidLeadingZeros() const {<br>
-  if (!HasLeadingZeroes)<br>
-    return true;<br>
-<br>
-  // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions<br>
-  switch (CS.getKind()) {<br>
-  case ConversionSpecifier::dArg:<br>
-  case ConversionSpecifier::DArg:<br>
-  case ConversionSpecifier::iArg:<br>
-  case ConversionSpecifier::oArg:<br>
-  case ConversionSpecifier::OArg:<br>
-  case ConversionSpecifier::uArg:<br>
-  case ConversionSpecifier::UArg:<br>
-  case ConversionSpecifier::xArg:<br>
-  case ConversionSpecifier::XArg:<br>
-  case ConversionSpecifier::aArg:<br>
-  case ConversionSpecifier::AArg:<br>
-  case ConversionSpecifier::eArg:<br>
-  case ConversionSpecifier::EArg:<br>
-  case ConversionSpecifier::fArg:<br>
-  case ConversionSpecifier::FArg:<br>
-  case ConversionSpecifier::gArg:<br>
-  case ConversionSpecifier::GArg:<br>
-  case ConversionSpecifier::FreeBSDrArg:<br>
-  case ConversionSpecifier::FreeBSDyArg:<br>
-    return true;<br>
-<br>
-  default:<br>
-    return false;<br>
-  }<br>
-}<br>
-<br>
-bool PrintfSpecifier::hasValidSpacePrefix() const {<br>
-  if (!HasSpacePrefix)<br>
-    return true;<br>
-<br>
-  // The space prefix only makes sense for signed conversions<br>
-  switch (CS.getKind()) {<br>
-  case ConversionSpecifier::dArg:<br>
-  case ConversionSpecifier::DArg:<br>
-  case ConversionSpecifier::iArg:<br>
-  case ConversionSpecifier::fArg:<br>
-  case ConversionSpecifier::FArg:<br>
-  case ConversionSpecifier::eArg:<br>
-  case ConversionSpecifier::EArg:<br>
-  case ConversionSpecifier::gArg:<br>
-  case ConversionSpecifier::GArg:<br>
-  case ConversionSpecifier::aArg:<br>
-  case ConversionSpecifier::AArg:<br>
-  case ConversionSpecifier::FreeBSDrArg:<br>
-  case ConversionSpecifier::FreeBSDyArg:<br>
-    return true;<br>
-<br>
-  default:<br>
-    return false;<br>
-  }<br>
-}<br>
-<br>
-bool PrintfSpecifier::hasValidLeftJustified() const {<br>
-  if (!IsLeftJustified)<br>
-    return true;<br>
-<br>
-  // The left justified flag is valid for all conversions except n<br>
-  switch (CS.getKind()) {<br>
-  case ConversionSpecifier::nArg:<br>
-    return false;<br>
-<br>
-  default:<br>
-    return true;<br>
-  }<br>
-}<br>
-<br>
-bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {<br>
-  if (!HasThousandsGrouping)<br>
-    return true;<br>
-<br>
-  switch (CS.getKind()) {<br>
-    case ConversionSpecifier::dArg:<br>
-    case ConversionSpecifier::DArg:<br>
-    case ConversionSpecifier::iArg:<br>
-    case ConversionSpecifier::uArg:<br>
-    case ConversionSpecifier::UArg:<br>
-    case ConversionSpecifier::fArg:<br>
-    case ConversionSpecifier::FArg:<br>
-    case ConversionSpecifier::gArg:<br>
-    case ConversionSpecifier::GArg:<br>
-      return true;<br>
-    default:<br>
-      return false;<br>
-  }<br>
-}<br>
-<br>
-bool PrintfSpecifier::hasValidPrecision() const {<br>
-  if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)<br>
-    return true;<br>
-<br>
-  // Precision is only valid with the diouxXaAeEfFgGsP conversions<br>
-  switch (CS.getKind()) {<br>
-  case ConversionSpecifier::dArg:<br>
-  case ConversionSpecifier::DArg:<br>
-  case ConversionSpecifier::iArg:<br>
-  case ConversionSpecifier::oArg:<br>
-  case ConversionSpecifier::OArg:<br>
-  case ConversionSpecifier::uArg:<br>
-  case ConversionSpecifier::UArg:<br>
-  case ConversionSpecifier::xArg:<br>
-  case ConversionSpecifier::XArg:<br>
-  case ConversionSpecifier::aArg:<br>
-  case ConversionSpecifier::AArg:<br>
-  case ConversionSpecifier::eArg:<br>
-  case ConversionSpecifier::EArg:<br>
-  case ConversionSpecifier::fArg:<br>
-  case ConversionSpecifier::FArg:<br>
-  case ConversionSpecifier::gArg:<br>
-  case ConversionSpecifier::GArg:<br>
-  case ConversionSpecifier::sArg:<br>
-  case ConversionSpecifier::FreeBSDrArg:<br>
-  case ConversionSpecifier::FreeBSDyArg:<br>
-  case ConversionSpecifier::PArg:<br>
-    return true;<br>
-<br>
-  default:<br>
-    return false;<br>
-  }<br>
-}<br>
-bool PrintfSpecifier::hasValidFieldWidth() const {<br>
-  if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)<br>
-      return true;<br>
-<br>
-  // The field width is valid for all conversions except n<br>
-  switch (CS.getKind()) {<br>
-  case ConversionSpecifier::nArg:<br>
-    return false;<br>
-<br>
-  default:<br>
-    return true;<br>
-  }<br>
-}<br>
<br>
Removed: cfe/trunk/lib/Analysis/ScanfFormatString.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ScanfFormatString.cpp?rev=345970&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ScanfFormatString.cpp?rev=345970&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Analysis/ScanfFormatString.cpp (original)<br>
+++ cfe/trunk/lib/Analysis/ScanfFormatString.cpp (removed)<br>
@@ -1,563 +0,0 @@<br>
-//= ScanfFormatString.cpp - Analysis of printf format strings --*- C++ -*-===//<br>
-//<br>
-//                     The LLVM Compiler Infrastructure<br>
-//<br>
-// This file is distributed under the University of Illinois Open Source<br>
-// License. See LICENSE.TXT for details.<br>
-//<br>
-//===----------------------------------------------------------------------===//<br>
-//<br>
-// Handling of format string in scanf and friends.  The structure of format<br>
-// strings for fscanf() are described in C99 7.19.6.2.<br>
-//<br>
-//===----------------------------------------------------------------------===//<br>
-<br>
-#include "clang/Analysis/Analyses/FormatString.h"<br>
-#include "FormatStringParsing.h"<br>
-#include "clang/Basic/TargetInfo.h"<br>
-<br>
-using clang::analyze_format_string::ArgType;<br>
-using clang::analyze_format_string::FormatStringHandler;<br>
-using clang::analyze_format_string::LengthModifier;<br>
-using clang::analyze_format_string::OptionalAmount;<br>
-using clang::analyze_format_string::ConversionSpecifier;<br>
-using clang::analyze_scanf::ScanfConversionSpecifier;<br>
-using clang::analyze_scanf::ScanfSpecifier;<br>
-using clang::UpdateOnReturn;<br>
-using namespace clang;<br>
-<br>
-typedef clang::analyze_format_string::SpecifierResult<ScanfSpecifier><br>
-        ScanfSpecifierResult;<br>
-<br>
-static bool ParseScanList(FormatStringHandler &H,<br>
-                          ScanfConversionSpecifier &CS,<br>
-                          const char *&Beg, const char *E) {<br>
-  const char *I = Beg;<br>
-  const char *start = I - 1;<br>
-  UpdateOnReturn <const char*> UpdateBeg(Beg, I);<br>
-<br>
-  // No more characters?<br>
-  if (I == E) {<br>
-    H.HandleIncompleteScanList(start, I);<br>
-    return true;<br>
-  }<br>
-<br>
-  // Special case: ']' is the first character.<br>
-  if (*I == ']') {<br>
-    if (++I == E) {<br>
-      H.HandleIncompleteScanList(start, I - 1);<br>
-      return true;<br>
-    }<br>
-  }<br>
-<br>
-  // Special case: "^]" are the first characters.<br>
-  if (I + 1 != E && I[0] == '^' && I[1] == ']') {<br>
-    I += 2;<br>
-    if (I == E) {<br>
-      H.HandleIncompleteScanList(start, I - 1);<br>
-      return true;<br>
-    }<br>
-  }<br>
-<br>
-  // Look for a ']' character which denotes the end of the scan list.<br>
-  while (*I != ']') {<br>
-    if (++I == E) {<br>
-      H.HandleIncompleteScanList(start, I - 1);<br>
-      return true;<br>
-    }<br>
-  }<br>
-<br>
-  CS.setEndScanList(I);<br>
-  return false;<br>
-}<br>
-<br>
-// FIXME: Much of this is copy-paste from ParsePrintfSpecifier.<br>
-// We can possibly refactor.<br>
-static ScanfSpecifierResult ParseScanfSpecifier(FormatStringHandler &H,<br>
-                                                const char *&Beg,<br>
-                                                const char *E,<br>
-                                                unsigned &argIndex,<br>
-                                                const LangOptions &LO,<br>
-                                                const TargetInfo &Target) {<br>
-  using namespace clang::analyze_format_string;<br>
-  using namespace clang::analyze_scanf;<br>
-  const char *I = Beg;<br>
-  const char *Start = nullptr;<br>
-  UpdateOnReturn <const char*> UpdateBeg(Beg, I);<br>
-<br>
-    // Look for a '%' character that indicates the start of a format specifier.<br>
-  for ( ; I != E ; ++I) {<br>
-    char c = *I;<br>
-    if (c == '\0') {<br>
-        // Detect spurious null characters, which are likely errors.<br>
-      H.HandleNullChar(I);<br>
-      return true;<br>
-    }<br>
-    if (c == '%') {<br>
-      Start = I++;  // Record the start of the format specifier.<br>
-      break;<br>
-    }<br>
-  }<br>
-<br>
-    // No format specifier found?<br>
-  if (!Start)<br>
-    return false;<br>
-<br>
-  if (I == E) {<br>
-      // No more characters left?<br>
-    H.HandleIncompleteSpecifier(Start, E - Start);<br>
-    return true;<br>
-  }<br>
-<br>
-  ScanfSpecifier FS;<br>
-  if (ParseArgPosition(H, FS, Start, I, E))<br>
-    return true;<br>
-<br>
-  if (I == E) {<br>
-      // No more characters left?<br>
-    H.HandleIncompleteSpecifier(Start, E - Start);<br>
-    return true;<br>
-  }<br>
-<br>
-  // Look for '*' flag if it is present.<br>
-  if (*I == '*') {<br>
-    FS.setSuppressAssignment(I);<br>
-    if (++I == E) {<br>
-      H.HandleIncompleteSpecifier(Start, E - Start);<br>
-      return true;<br>
-    }<br>
-  }<br>
-<br>
-  // Look for the field width (if any).  Unlike printf, this is either<br>
-  // a fixed integer or isn't present.<br>
-  const OptionalAmount &Amt = clang::analyze_format_string::ParseAmount(I, E);<br>
-  if (Amt.getHowSpecified() != OptionalAmount::NotSpecified) {<br>
-    assert(Amt.getHowSpecified() == OptionalAmount::Constant);<br>
-    FS.setFieldWidth(Amt);<br>
-<br>
-    if (I == E) {<br>
-      // No more characters left?<br>
-      H.HandleIncompleteSpecifier(Start, E - Start);<br>
-      return true;<br>
-    }<br>
-  }<br>
-<br>
-  // Look for the length modifier.<br>
-  if (ParseLengthModifier(FS, I, E, LO, /*scanf=*/true) && I == E) {<br>
-      // No more characters left?<br>
-    H.HandleIncompleteSpecifier(Start, E - Start);<br>
-    return true;<br>
-  }<br>
-<br>
-  // Detect spurious null characters, which are likely errors.<br>
-  if (*I == '\0') {<br>
-    H.HandleNullChar(I);<br>
-    return true;<br>
-  }<br>
-<br>
-  // Finally, look for the conversion specifier.<br>
-  const char *conversionPosition = I++;<br>
-  ScanfConversionSpecifier::Kind k = ScanfConversionSpecifier::InvalidSpecifier;<br>
-  switch (*conversionPosition) {<br>
-    default:<br>
-      break;<br>
-    case '%': k = ConversionSpecifier::PercentArg;   break;<br>
-    case 'A': k = ConversionSpecifier::AArg; break;<br>
-    case 'E': k = ConversionSpecifier::EArg; break;<br>
-    case 'F': k = ConversionSpecifier::FArg; break;<br>
-    case 'G': k = ConversionSpecifier::GArg; break;<br>
-    case 'X': k = ConversionSpecifier::XArg; break;<br>
-    case 'a': k = ConversionSpecifier::aArg; break;<br>
-    case 'd': k = ConversionSpecifier::dArg; break;<br>
-    case 'e': k = ConversionSpecifier::eArg; break;<br>
-    case 'f': k = ConversionSpecifier::fArg; break;<br>
-    case 'g': k = ConversionSpecifier::gArg; break;<br>
-    case 'i': k = ConversionSpecifier::iArg; break;<br>
-    case 'n': k = ConversionSpecifier::nArg; break;<br>
-    case 'c': k = ConversionSpecifier::cArg; break;<br>
-    case 'C': k = ConversionSpecifier::CArg; break;<br>
-    case 'S': k = ConversionSpecifier::SArg; break;<br>
-    case '[': k = ConversionSpecifier::ScanListArg; break;<br>
-    case 'u': k = ConversionSpecifier::uArg; break;<br>
-    case 'x': k = ConversionSpecifier::xArg; break;<br>
-    case 'o': k = ConversionSpecifier::oArg; break;<br>
-    case 's': k = ConversionSpecifier::sArg; break;<br>
-    case 'p': k = ConversionSpecifier::pArg; break;<br>
-    // Apple extensions<br>
-      // Apple-specific<br>
-    case 'D':<br>
-      if (Target.getTriple().isOSDarwin())<br>
-        k = ConversionSpecifier::DArg;<br>
-      break;<br>
-    case 'O':<br>
-      if (Target.getTriple().isOSDarwin())<br>
-        k = ConversionSpecifier::OArg;<br>
-      break;<br>
-    case 'U':<br>
-      if (Target.getTriple().isOSDarwin())<br>
-        k = ConversionSpecifier::UArg;<br>
-      break;<br>
-  }<br>
-  ScanfConversionSpecifier CS(conversionPosition, k);<br>
-  if (k == ScanfConversionSpecifier::ScanListArg) {<br>
-    if (ParseScanList(H, CS, I, E))<br>
-      return true;<br>
-  }<br>
-  FS.setConversionSpecifier(CS);<br>
-  if (CS.consumesDataArgument() && !FS.getSuppressAssignment()<br>
-      && !FS.usesPositionalArg())<br>
-    FS.setArgIndex(argIndex++);<br>
-<br>
-  // FIXME: '%' and '*' doesn't make sense.  Issue a warning.<br>
-  // FIXME: 'ConsumedSoFar' and '*' doesn't make sense.<br>
-<br>
-  if (k == ScanfConversionSpecifier::InvalidSpecifier) {<br>
-    unsigned Len = I - Beg;<br>
-    if (ParseUTF8InvalidSpecifier(Beg, E, Len)) {<br>
-      CS.setEndScanList(Beg + Len);<br>
-      FS.setConversionSpecifier(CS);<br>
-    }<br>
-    // Assume the conversion takes one argument.<br>
-    return !H.HandleInvalidScanfConversionSpecifier(FS, Beg, Len);<br>
-  }<br>
-  return ScanfSpecifierResult(Start, FS);<br>
-}<br>
-<br>
-ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {<br>
-  const ScanfConversionSpecifier &CS = getConversionSpecifier();<br>
-<br>
-  if (!CS.consumesDataArgument())<br>
-    return ArgType::Invalid();<br>
-<br>
-  switch(CS.getKind()) {<br>
-    // Signed int.<br>
-    case ConversionSpecifier::dArg:<br>
-    case ConversionSpecifier::DArg:<br>
-    case ConversionSpecifier::iArg:<br>
-      switch (LM.getKind()) {<br>
-        case LengthModifier::None:<br>
-          return ArgType::PtrTo(Ctx.IntTy);<br>
-        case LengthModifier::AsChar:<br>
-          return ArgType::PtrTo(ArgType::AnyCharTy);<br>
-        case LengthModifier::AsShort:<br>
-          return ArgType::PtrTo(Ctx.ShortTy);<br>
-        case LengthModifier::AsLong:<br>
-          return ArgType::PtrTo(Ctx.LongTy);<br>
-        case LengthModifier::AsLongLong:<br>
-        case LengthModifier::AsQuad:<br>
-          return ArgType::PtrTo(Ctx.LongLongTy);<br>
-        case LengthModifier::AsInt64:<br>
-          return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64"));<br>
-        case LengthModifier::AsIntMax:<br>
-          return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));<br>
-        case LengthModifier::AsSizeT:<br>
-          return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));<br>
-        case LengthModifier::AsPtrDiff:<br>
-          return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));<br>
-        case LengthModifier::AsLongDouble:<br>
-          // GNU extension.<br>
-          return ArgType::PtrTo(Ctx.LongLongTy);<br>
-        case LengthModifier::AsAllocate:<br>
-        case LengthModifier::AsMAllocate:<br>
-        case LengthModifier::AsInt32:<br>
-        case LengthModifier::AsInt3264:<br>
-        case LengthModifier::AsWide:<br>
-          return ArgType::Invalid();<br>
-      }<br>
-<br>
-    // Unsigned int.<br>
-    case ConversionSpecifier::oArg:<br>
-    case ConversionSpecifier::OArg:<br>
-    case ConversionSpecifier::uArg:<br>
-    case ConversionSpecifier::UArg:<br>
-    case ConversionSpecifier::xArg:<br>
-    case ConversionSpecifier::XArg:<br>
-      switch (LM.getKind()) {<br>
-        case LengthModifier::None:<br>
-          return ArgType::PtrTo(Ctx.UnsignedIntTy);<br>
-        case LengthModifier::AsChar:<br>
-          return ArgType::PtrTo(Ctx.UnsignedCharTy);<br>
-        case LengthModifier::AsShort:<br>
-          return ArgType::PtrTo(Ctx.UnsignedShortTy);<br>
-        case LengthModifier::AsLong:<br>
-          return ArgType::PtrTo(Ctx.UnsignedLongTy);<br>
-        case LengthModifier::AsLongLong:<br>
-        case LengthModifier::AsQuad:<br>
-          return ArgType::PtrTo(Ctx.UnsignedLongLongTy);<br>
-        case LengthModifier::AsInt64:<br>
-          return ArgType::PtrTo(ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64"));<br>
-        case LengthModifier::AsIntMax:<br>
-          return ArgType::PtrTo(ArgType(Ctx.getUIntMaxType(), "uintmax_t"));<br>
-        case LengthModifier::AsSizeT:<br>
-          return ArgType::PtrTo(ArgType(Ctx.getSizeType(), "size_t"));<br>
-        case LengthModifier::AsPtrDiff:<br>
-          return ArgType::PtrTo(<br>
-              ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"));<br>
-        case LengthModifier::AsLongDouble:<br>
-          // GNU extension.<br>
-          return ArgType::PtrTo(Ctx.UnsignedLongLongTy);<br>
-        case LengthModifier::AsAllocate:<br>
-        case LengthModifier::AsMAllocate:<br>
-        case LengthModifier::AsInt32:<br>
-        case LengthModifier::AsInt3264:<br>
-        case LengthModifier::AsWide:<br>
-          return ArgType::Invalid();<br>
-      }<br>
-<br>
-    // Float.<br>
-    case ConversionSpecifier::aArg:<br>
-    case ConversionSpecifier::AArg:<br>
-    case ConversionSpecifier::eArg:<br>
-    case ConversionSpecifier::EArg:<br>
-    case ConversionSpecifier::fArg:<br>
-    case ConversionSpecifier::FArg:<br>
-    case ConversionSpecifier::gArg:<br>
-    case ConversionSpecifier::GArg:<br>
-      switch (LM.getKind()) {<br>
-        case LengthModifier::None:<br>
-          return ArgType::PtrTo(Ctx.FloatTy);<br>
-        case LengthModifier::AsLong:<br>
-          return ArgType::PtrTo(Ctx.DoubleTy);<br>
-        case LengthModifier::AsLongDouble:<br>
-          return ArgType::PtrTo(Ctx.LongDoubleTy);<br>
-        default:<br>
-          return ArgType::Invalid();<br>
-      }<br>
-<br>
-    // Char, string and scanlist.<br>
-    case ConversionSpecifier::cArg:<br>
-    case ConversionSpecifier::sArg:<br>
-    case ConversionSpecifier::ScanListArg:<br>
-      switch (LM.getKind()) {<br>
-        case LengthModifier::None:<br>
-          return ArgType::PtrTo(ArgType::AnyCharTy);<br>
-        case LengthModifier::AsLong:<br>
-        case LengthModifier::AsWide:<br>
-          return ArgType::PtrTo(ArgType(Ctx.getWideCharType(), "wchar_t"));<br>
-        case LengthModifier::AsAllocate:<br>
-        case LengthModifier::AsMAllocate:<br>
-          return ArgType::PtrTo(ArgType::CStrTy);<br>
-        case LengthModifier::AsShort:<br>
-          if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())<br>
-            return ArgType::PtrTo(ArgType::AnyCharTy);<br>
-          LLVM_FALLTHROUGH;<br>
-        default:<br>
-          return ArgType::Invalid();<br>
-      }<br>
-    case ConversionSpecifier::CArg:<br>
-    case ConversionSpecifier::SArg:<br>
-      // FIXME: Mac OS X specific?<br>
-      switch (LM.getKind()) {<br>
-        case LengthModifier::None:<br>
-        case LengthModifier::AsWide:<br>
-          return ArgType::PtrTo(ArgType(Ctx.getWideCharType(), "wchar_t"));<br>
-        case LengthModifier::AsAllocate:<br>
-        case LengthModifier::AsMAllocate:<br>
-          return ArgType::PtrTo(ArgType(ArgType::WCStrTy, "wchar_t *"));<br>
-        case LengthModifier::AsShort:<br>
-          if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())<br>
-            return ArgType::PtrTo(ArgType::AnyCharTy);<br>
-          LLVM_FALLTHROUGH;<br>
-        default:<br>
-          return ArgType::Invalid();<br>
-      }<br>
-<br>
-    // Pointer.<br>
-    case ConversionSpecifier::pArg:<br>
-      return ArgType::PtrTo(ArgType::CPointerTy);<br>
-<br>
-    // Write-back.<br>
-    case ConversionSpecifier::nArg:<br>
-      switch (LM.getKind()) {<br>
-        case LengthModifier::None:<br>
-          return ArgType::PtrTo(Ctx.IntTy);<br>
-        case LengthModifier::AsChar:<br>
-          return ArgType::PtrTo(Ctx.SignedCharTy);<br>
-        case LengthModifier::AsShort:<br>
-          return ArgType::PtrTo(Ctx.ShortTy);<br>
-        case LengthModifier::AsLong:<br>
-          return ArgType::PtrTo(Ctx.LongTy);<br>
-        case LengthModifier::AsLongLong:<br>
-        case LengthModifier::AsQuad:<br>
-          return ArgType::PtrTo(Ctx.LongLongTy);<br>
-        case LengthModifier::AsInt64:<br>
-          return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64"));<br>
-        case LengthModifier::AsIntMax:<br>
-          return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));<br>
-        case LengthModifier::AsSizeT:<br>
-          return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));<br>
-        case LengthModifier::AsPtrDiff:<br>
-          return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));<br>
-        case LengthModifier::AsLongDouble:<br>
-          return ArgType(); // FIXME: Is this a known extension?<br>
-        case LengthModifier::AsAllocate:<br>
-        case LengthModifier::AsMAllocate:<br>
-        case LengthModifier::AsInt32:<br>
-        case LengthModifier::AsInt3264:<br>
-        case LengthModifier::AsWide:<br>
-          return ArgType::Invalid();<br>
-        }<br>
-<br>
-    default:<br>
-      break;<br>
-  }<br>
-<br>
-  return ArgType();<br>
-}<br>
-<br>
-bool ScanfSpecifier::fixType(QualType QT, QualType RawQT,<br>
-                             const LangOptions &LangOpt,<br>
-                             ASTContext &Ctx) {<br>
-<br>
-  // %n is different from other conversion specifiers; don't try to fix it.<br>
-  if (CS.getKind() == ConversionSpecifier::nArg)<br>
-    return false;<br>
-<br>
-  if (!QT->isPointerType())<br>
-    return false;<br>
-<br>
-  QualType PT = QT->getPointeeType();<br>
-<br>
-  // If it's an enum, get its underlying type.<br>
-  if (const EnumType *ETy = PT->getAs<EnumType>()) {<br>
-    // Don't try to fix incomplete enums.<br>
-    if (!ETy->getDecl()->isComplete())<br>
-      return false;<br>
-    PT = ETy->getDecl()->getIntegerType();<br>
-  }<br>
-<br>
-  const BuiltinType *BT = PT->getAs<BuiltinType>();<br>
-  if (!BT)<br>
-    return false;<br>
-<br>
-  // Pointer to a character.<br>
-  if (PT->isAnyCharacterType()) {<br>
-    CS.setKind(ConversionSpecifier::sArg);<br>
-    if (PT->isWideCharType())<br>
-      LM.setKind(LengthModifier::AsWideChar);<br>
-    else<br>
-      LM.setKind(LengthModifier::None);<br>
-<br>
-    // If we know the target array length, we can use it as a field width.<br>
-    if (const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(RawQT)) {<br>
-      if (CAT->getSizeModifier() == ArrayType::Normal)<br>
-        FieldWidth = OptionalAmount(OptionalAmount::Constant,<br>
-                                    CAT->getSize().getZExtValue() - 1,<br>
-                                    "", 0, false);<br>
-<br>
-    }<br>
-    return true;<br>
-  }<br>
-<br>
-  // Figure out the length modifier.<br>
-  switch (BT->getKind()) {<br>
-    // no modifier<br>
-    case BuiltinType::UInt:<br>
-    case BuiltinType::Int:<br>
-    case BuiltinType::Float:<br>
-      LM.setKind(LengthModifier::None);<br>
-      break;<br>
-<br>
-    // hh<br>
-    case BuiltinType::Char_U:<br>
-    case BuiltinType::UChar:<br>
-    case BuiltinType::Char_S:<br>
-    case BuiltinType::SChar:<br>
-      LM.setKind(LengthModifier::AsChar);<br>
-      break;<br>
-<br>
-    // h<br>
-    case BuiltinType::Short:<br>
-    case BuiltinType::UShort:<br>
-      LM.setKind(LengthModifier::AsShort);<br>
-      break;<br>
-<br>
-    // l<br>
-    case BuiltinType::Long:<br>
-    case BuiltinType::ULong:<br>
-    case BuiltinType::Double:<br>
-      LM.setKind(LengthModifier::AsLong);<br>
-      break;<br>
-<br>
-    // ll<br>
-    case BuiltinType::LongLong:<br>
-    case BuiltinType::ULongLong:<br>
-      LM.setKind(LengthModifier::AsLongLong);<br>
-      break;<br>
-<br>
-    // L<br>
-    case BuiltinType::LongDouble:<br>
-      LM.setKind(LengthModifier::AsLongDouble);<br>
-      break;<br>
-<br>
-    // Don't know.<br>
-    default:<br>
-      return false;<br>
-  }<br>
-<br>
-  // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.<br>
-  if (isa<TypedefType>(PT) && (LangOpt.C99 || LangOpt.CPlusPlus11))<br>
-    namedTypeToLengthModifier(PT, LM);<br>
-<br>
-  // If fixing the length modifier was enough, we are done.<br>
-  if (hasValidLengthModifier(Ctx.getTargetInfo())) {<br>
-    const analyze_scanf::ArgType &AT = getArgType(Ctx);<br>
-    if (AT.isValid() && AT.matchesType(Ctx, QT))<br>
-      return true;<br>
-  }<br>
-<br>
-  // Figure out the conversion specifier.<br>
-  if (PT->isRealFloatingType())<br>
-    CS.setKind(ConversionSpecifier::fArg);<br>
-  else if (PT->isSignedIntegerType())<br>
-    CS.setKind(ConversionSpecifier::dArg);<br>
-  else if (PT->isUnsignedIntegerType())<br>
-    CS.setKind(ConversionSpecifier::uArg);<br>
-  else<br>
-    llvm_unreachable("Unexpected type");<br>
-<br>
-  return true;<br>
-}<br>
-<br>
-void ScanfSpecifier::toString(raw_ostream &os) const {<br>
-  os << "%";<br>
-<br>
-  if (usesPositionalArg())<br>
-    os << getPositionalArgIndex() << "$";<br>
-  if (SuppressAssignment)<br>
-    os << "*";<br>
-<br>
-  FieldWidth.toString(os);<br>
-  os << LM.toString();<br>
-  os << CS.toString();<br>
-}<br>
-<br>
-bool clang::analyze_format_string::ParseScanfString(FormatStringHandler &H,<br>
-                                                    const char *I,<br>
-                                                    const char *E,<br>
-                                                    const LangOptions &LO,<br>
-                                                    const TargetInfo &Target) {<br>
-<br>
-  unsigned argIndex = 0;<br>
-<br>
-  // Keep looking for a format specifier until we have exhausted the string.<br>
-  while (I != E) {<br>
-    const ScanfSpecifierResult &FSR = ParseScanfSpecifier(H, I, E, argIndex,<br>
-                                                          LO, Target);<br>
-    // Did a fail-stop error of any kind occur when parsing the specifier?<br>
-    // If so, don't do any more processing.<br>
-    if (FSR.shouldStop())<br>
-      return true;<br>
-      // Did we exhaust the string or encounter an error that<br>
-      // we can recover from?<br>
-    if (!FSR.hasValue())<br>
-      continue;<br>
-      // We have a format specifier.  Pass it to the callback.<br>
-    if (!H.HandleScanfSpecifier(FSR.getValue(), FSR.getStart(),<br>
-                                I - FSR.getStart())) {<br>
-      return true;<br>
-    }<br>
-  }<br>
-  assert(I == E && "Format string not exhausted");<br>
-  return false;<br>
-}<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=345971&r1=345970&r2=345971&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=345971&r1=345970&r2=345971&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Fri Nov  2 06:14:11 2018<br>
@@ -21,7 +21,7 @@<br>
 #include "TargetInfo.h"<br>
 #include "clang/AST/ASTContext.h"<br>
 #include "clang/AST/Decl.h"<br>
-#include "clang/Analysis/Analyses/OSLog.h"<br>
+#include "clang/AST/OSLog.h"<br>
 #include "clang/Basic/TargetBuiltins.h"<br>
 #include "clang/Basic/TargetInfo.h"<br>
 #include "clang/CodeGen/CGFunctionInfo.h"<br>
@@ -3606,13 +3606,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(<br>
   case Builtin::BI__builtin_os_log_format:<br>
     return emitBuiltinOSLogFormat(*E);<br>
<br>
-  case Builtin::BI__builtin_os_log_format_buffer_size: {<br>
-    analyze_os_log::OSLogBufferLayout Layout;<br>
-    analyze_os_log::computeOSLogBufferLayout(CGM.getContext(), E, Layout);<br>
-    return RValue::get(ConstantInt::get(ConvertType(E->getType()),<br>
-                                        Layout.size().getQuantity()));<br>
-  }<br>
-<br>
   case Builtin::BI__xray_customevent: {<br>
     if (!ShouldXRayInstrumentFunction())<br>
       return RValue::getIgnored();<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaChecking.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=345971&r1=345970&r2=345971&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=345971&r1=345970&r2=345971&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Fri Nov  2 06:14:11 2018<br>
@@ -27,6 +27,7 @@<br>
 #include "clang/AST/ExprCXX.h"<br>
 #include "clang/AST/ExprObjC.h"<br>
 #include "clang/AST/ExprOpenMP.h"<br>
+#include "clang/AST/FormatString.h"<br>
 #include "clang/AST/NSAPI.h"<br>
 #include "clang/AST/NonTrivialTypeVisitor.h"<br>
 #include "clang/AST/OperationKinds.h"<br>
@@ -35,7 +36,6 @@<br>
 #include "clang/AST/Type.h"<br>
 #include "clang/AST/TypeLoc.h"<br>
 #include "clang/AST/UnresolvedSet.h"<br>
-#include "clang/Analysis/Analyses/FormatString.h"<br>
 #include "clang/Basic/AddressSpaces.h"<br>
 #include "clang/Basic/CharInfo.h"<br>
 #include "clang/Basic/Diagnostic.h"<br>
<br>
Modified: cfe/trunk/test/CodeGen/builtins.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/builtins.c?rev=345971&r1=345970&r2=345971&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/builtins.c?rev=345971&r1=345970&r2=345971&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGen/builtins.c (original)<br>
+++ cfe/trunk/test/CodeGen/builtins.c Fri Nov  2 06:14:11 2018<br>
@@ -729,25 +729,28 @@ void test_builtin_os_log_merge_helper1(v<br>
<br>
 // CHECK-LABEL: define void @test_builtin_os_log_errno<br>
 void test_builtin_os_log_errno() {<br>
-  // CHECK: %[[VLA:.*]] = alloca i8, i64 4, align 16<br>
-  // CHECK: call void @__os_log_helper_16_2_1_0_96(i8* %[[VLA]])<br>
+  // CHECK-NOT: @stacksave<br>
+  // CHECK: %[[BUF:.*]] = alloca [4 x i8], align 1<br>
+  // CHECK: %[[DECAY:.*]] = getelementptr inbounds [4 x i8], [4 x i8]* %[[BUF]], i32 0, i32 0<br>
+  // CHECK: call void @__os_log_helper_1_2_1_0_96(i8* %[[DECAY]])<br>
+  // CHECK-NOT: @stackrestore<br>
<br>
   char buf[__builtin_os_log_format_buffer_size("%m")];<br>
   __builtin_os_log_format(buf, "%m");<br>
 }<br>
<br>
-// CHECK-LABEL: define linkonce_odr hidden void @__os_log_helper_16_2_1_0_96<br>
+// CHECK-LABEL: define linkonce_odr hidden void @__os_log_helper_1_2_1_0_96<br>
 // CHECK: (i8* %[[BUFFER:.*]])<br>
<br>
 // CHECK: %[[BUFFER_ADDR:.*]] = alloca i8*, align 8<br>
 // CHECK: store i8* %[[BUFFER]], i8** %[[BUFFER_ADDR]], align 8<br>
 // CHECK: %[[BUF:.*]] = load i8*, i8** %[[BUFFER_ADDR]], align 8<br>
 // CHECK: %[[SUMMARY:.*]] = getelementptr i8, i8* %[[BUF]], i64 0<br>
-// CHECK: store i8 2, i8* %[[SUMMARY]], align 16<br>
+// CHECK: store i8 2, i8* %[[SUMMARY]], align 1<br>
 // CHECK: %[[NUMARGS:.*]] = getelementptr i8, i8* %[[BUF]], i64 1<br>
 // CHECK: store i8 1, i8* %[[NUMARGS]], align 1<br>
 // CHECK: %[[ARGDESCRIPTOR:.*]] = getelementptr i8, i8* %[[BUF]], i64 2<br>
-// CHECK: store i8 96, i8* %[[ARGDESCRIPTOR]], align 2<br>
+// CHECK: store i8 96, i8* %[[ARGDESCRIPTOR]], align 1<br>
 // CHECK: %[[ARGSIZE:.*]] = getelementptr i8, i8* %[[BUF]], i64 3<br>
 // CHECK: store i8 0, i8* %[[ARGSIZE]], align 1<br>
 // CHECK-NEXT: ret void<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div>