[cfe-commits] r149325 - in /cfe/trunk: include/clang/Analysis/Analyses/FormatString.h lib/Analysis/PrintfFormatString.cpp lib/Sema/SemaChecking.cpp test/SemaObjC/format-strings-objc.m

Nico Weber nicolasweber at gmx.de
Mon Jan 30 17:43:25 PST 2012


Author: nico
Date: Mon Jan 30 19:43:25 2012
New Revision: 149325

URL: http://llvm.org/viewvc/llvm-project?rev=149325&view=rev
Log:
Let %S, %ls, %C match 16bit types in NSStrings.

As discussed at http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20120130/052200.html


Modified:
    cfe/trunk/include/clang/Analysis/Analyses/FormatString.h
    cfe/trunk/lib/Analysis/PrintfFormatString.cpp
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/test/SemaObjC/format-strings-objc.m

Modified: cfe/trunk/include/clang/Analysis/Analyses/FormatString.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/FormatString.h?rev=149325&r1=149324&r2=149325&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/Analyses/FormatString.h (original)
+++ cfe/trunk/include/clang/Analysis/Analyses/FormatString.h Mon Jan 30 19:43:25 2012
@@ -455,7 +455,7 @@
   /// will return null if the format specifier does not have
   /// a matching data argument or the matching argument matches
   /// more than one type.
-  ArgTypeResult getArgType(ASTContext &Ctx) const;
+  ArgTypeResult getArgType(ASTContext &Ctx, bool IsObjCLiteral) const;
 
   const OptionalFlag &hasThousandsGrouping() const {
       return HasThousandsGrouping;

Modified: cfe/trunk/lib/Analysis/PrintfFormatString.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/PrintfFormatString.cpp?rev=149325&r1=149324&r2=149325&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/PrintfFormatString.cpp (original)
+++ cfe/trunk/lib/Analysis/PrintfFormatString.cpp Mon Jan 30 19:43:25 2012
@@ -241,7 +241,8 @@
 // Methods on PrintfSpecifier.
 //===----------------------------------------------------------------------===//
 
-ArgTypeResult PrintfSpecifier::getArgType(ASTContext &Ctx) const {
+ArgTypeResult PrintfSpecifier::getArgType(ASTContext &Ctx,
+                                          bool IsObjCLiteral) const {
   const PrintfConversionSpecifier &CS = getConversionSpecifier();
 
   if (!CS.consumesDataArgument())
@@ -309,13 +310,19 @@
 
   switch (CS.getKind()) {
     case ConversionSpecifier::sArg:
-      if (LM.getKind() == LengthModifier::AsWideChar)
+      if (LM.getKind() == LengthModifier::AsWideChar) {
+        if (IsObjCLiteral)
+          return Ctx.getPointerType(Ctx.UnsignedShortTy.withConst());
         return ArgTypeResult(ArgTypeResult::WCStrTy, "wchar_t *");
+      }
       return ArgTypeResult::CStrTy;
     case ConversionSpecifier::SArg:
-      // FIXME: This appears to be Mac OS X specific.
+      if (IsObjCLiteral)
+        return Ctx.getPointerType(Ctx.UnsignedShortTy.withConst());
       return ArgTypeResult(ArgTypeResult::WCStrTy, "wchar_t *");
     case ConversionSpecifier::CArg:
+      if (IsObjCLiteral)
+        return Ctx.UnsignedShortTy;
       return ArgTypeResult(Ctx.WCharTy, "wchar_t");
     case ConversionSpecifier::pArg:
       return ArgTypeResult::CPointerTy;

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=149325&r1=149324&r2=149325&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Mon Jan 30 19:43:25 2012
@@ -2162,7 +2162,8 @@
   // Now type check the data expression that matches the
   // format specifier.
   const Expr *Ex = getDataArg(argIndex);
-  const analyze_printf::ArgTypeResult &ATR = FS.getArgType(S.Context);
+  const analyze_printf::ArgTypeResult &ATR = FS.getArgType(S.Context,
+                                                           IsObjCLiteral);
   if (ATR.isValid() && !ATR.matchesType(S.Context, Ex->getType())) {
     // Check if we didn't match because of an implicit cast from a 'char'
     // or 'short' to an 'int'.  This is done because printf is a varargs

Modified: cfe/trunk/test/SemaObjC/format-strings-objc.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/format-strings-objc.m?rev=149325&r1=149324&r2=149325&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/format-strings-objc.m (original)
+++ cfe/trunk/test/SemaObjC/format-strings-objc.m Mon Jan 30 19:43:25 2012
@@ -115,3 +115,35 @@
 void check_NSLocalizedString() {
   [Foo fooWithFormat:NSLocalizedString(@"format"), @"arg"]; // no-warning
 }
+
+typedef __WCHAR_TYPE__ wchar_t;
+
+
+// Test that %S, %C, %ls check for 16 bit types in ObjC strings, as described at
+// http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html#//apple_ref/doc/uid/TP40004265
+
+void test_percent_S() {
+  const unsigned short data[] = { 'a', 'b', 0 };
+  const unsigned short* ptr = data;
+  NSLog(@"%S", ptr);  // no-warning
+
+  const wchar_t* wchar_ptr = L"ab";
+  NSLog(@"%S", wchar_ptr);  // expected-warning{{format specifies type 'const unsigned short *' but the argument has type 'const wchar_t *'}}
+}
+
+void test_percent_ls() {
+  const unsigned short data[] = { 'a', 'b', 0 };
+  const unsigned short* ptr = data;
+  NSLog(@"%ls", ptr);  // no-warning
+
+  const wchar_t* wchar_ptr = L"ab";
+  NSLog(@"%ls", wchar_ptr);  // expected-warning{{format specifies type 'const unsigned short *' but the argument has type 'const wchar_t *'}}
+}
+
+void test_percent_C() {
+  const unsigned short data = 'a';
+  NSLog(@"%C", data);  // no-warning
+
+  const wchar_t wchar_data = L'a';
+  NSLog(@"%C", wchar_data);  // expected-warning{{format specifies type 'unsigned short' but the argument has type 'wchar_t'}}
+}





More information about the cfe-commits mailing list