commit 17e869027243216a21ba2997e09fef72328461cb
Author: Jonathan Schleifer <js@webkeks.org>
Date:   Sat Nov 23 11:19:14 2013 +0100

    Accept %k format specifier in format strings.

diff --git a/include/clang/Analysis/Analyses/FormatString.h b/include/clang/Analysis/Analyses/FormatString.h
index c9516b5..6e7d715 100644
--- a/include/clang/Analysis/Analyses/FormatString.h
+++ b/include/clang/Analysis/Analyses/FormatString.h
@@ -161,7 +161,10 @@ public:
     // GlibC specific specifiers.
     PrintErrno,   // 'm'
 
-    PrintfConvBeg = ObjCObjArg, PrintfConvEnd = PrintErrno,
+    // ObjFW specific specifiers.
+    kArg,         // 'k'
+
+    PrintfConvBeg = ObjCObjArg, PrintfConvEnd = kArg,
 
     // ** Scanf-specific **
     ScanListArg, // '['
diff --git a/lib/Analysis/FormatString.cpp b/lib/Analysis/FormatString.cpp
index 43ecc66..7a44e4c 100644
--- a/lib/Analysis/FormatString.cpp
+++ b/lib/Analysis/FormatString.cpp
@@ -550,6 +550,9 @@ const char *ConversionSpecifier::toString() const {
 
   // GlibC specific specifiers.
   case PrintErrno: return "m";
+
+  // ObjFW specific specifiers.
+  case kArg: return "k";
   }
   return NULL;
 }
@@ -775,6 +778,7 @@ bool FormatSpecifier::hasStandardConversionSpecifier(const LangOptions &LangOpt)
       return LangOpt.ObjC1 || LangOpt.ObjC2;
     case ConversionSpecifier::InvalidSpecifier:
     case ConversionSpecifier::PrintErrno:
+    case ConversionSpecifier::kArg:
     case ConversionSpecifier::DArg:
     case ConversionSpecifier::OArg:
     case ConversionSpecifier::UArg:
diff --git a/lib/Analysis/PrintfFormatString.cpp b/lib/Analysis/PrintfFormatString.cpp
index f21b407..32d28ed 100644
--- a/lib/Analysis/PrintfFormatString.cpp
+++ b/lib/Analysis/PrintfFormatString.cpp
@@ -211,6 +211,8 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
       if (Target.getTriple().isOSDarwin())
         k = ConversionSpecifier::UArg;
       break;
+    // ObjFW specific.
+    case 'k': k = ConversionSpecifier::kArg; break;
   }
   PrintfConversionSpecifier CS(conversionPosition, k);
   FS.setConversionSpecifier(CS);
@@ -398,6 +400,8 @@ ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
       return ArgType::CPointerTy;
     case ConversionSpecifier::ObjCObjArg:
       return ArgType::ObjCPointerTy;
+    case ConversionSpecifier::kArg:
+      return ArgType(Ctx.Char32Ty, "of_unichar_t");
     default:
       break;
   }
diff --git a/lib/Analysis/ScanfFormatString.cpp b/lib/Analysis/ScanfFormatString.cpp
index f5ce84f..60c3248 100644
--- a/lib/Analysis/ScanfFormatString.cpp
+++ b/lib/Analysis/ScanfFormatString.cpp
@@ -188,6 +188,8 @@ static ScanfSpecifierResult ParseScanfSpecifier(FormatStringHandler &H,
       if (Target.getTriple().isOSDarwin())
         k = ConversionSpecifier::UArg;
       break;
+    // ObjFW extensions
+    case 'k': k = ConversionSpecifier::kArg; break;
   }
   ScanfConversionSpecifier CS(conversionPosition, k);
   if (k == ScanfConversionSpecifier::ScanListArg) {
@@ -336,6 +338,8 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {
         default:
           return ArgType::Invalid();
       }
+    case ConversionSpecifier::kArg:
+      return ArgType(Ctx.Char32Ty, "of_unichar_t");
 
     // Pointer.
     case ConversionSpecifier::pArg:
