[cfe-commits] r94992 - in /cfe/trunk: lib/Sema/SemaChecking.cpp test/Sema/format-strings.c

Ted Kremenek kremenek at apple.com
Mon Feb 1 11:28:17 PST 2010


Author: kremenek
Date: Mon Feb  1 13:28:15 2010
New Revision: 94992

URL: http://llvm.org/viewvc/llvm-project?rev=94992&view=rev
Log:
Format string checking: selectively ignore implicit casts to 'int'
when checking if the format specifier matches the type of the data
argument and the length modifier indicates the data type is 'char' or
'short'.

Modified:
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/test/Sema/format-strings.c

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=94992&r1=94991&r2=94992&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Mon Feb  1 13:28:15 2010
@@ -1280,14 +1280,25 @@
   // format specifier.
   const Expr *Ex = getDataArg(NumConversions);
   const analyze_printf::ArgTypeResult &ATR = FS.getArgType(S.Context);
-    
+  
   if (const QualType *T = ATR.getSpecificType()) {
     if (!MatchType(*T, Ex->getType(), true)) {
-      S.Diag(getLocationOfByte(CS.getStart()),
-             diag::warn_printf_conversion_argument_type_mismatch)
-        << *T << Ex->getType()
-        << getFormatSpecifierRange(startSpecifier, specifierLen)
-        << Ex->getSourceRange();
+      // 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
+      // function.
+      bool hasError = true;      
+      if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Ex))
+        if (ICE->getType() == S.Context.IntTy) {
+          Ex = ICE->getSubExpr();
+          hasError = !MatchType(*T, Ex->getType(), true);
+        }
+      
+      if (hasError)            
+        S.Diag(getLocationOfByte(CS.getStart()),
+               diag::warn_printf_conversion_argument_type_mismatch)
+          << *T << Ex->getType()
+          << getFormatSpecifierRange(startSpecifier, specifierLen)
+          << Ex->getSourceRange();
     }
     return true;
   }

Modified: cfe/trunk/test/Sema/format-strings.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/format-strings.c?rev=94992&r1=94991&r2=94992&view=diff

==============================================================================
--- cfe/trunk/test/Sema/format-strings.c (original)
+++ cfe/trunk/test/Sema/format-strings.c Mon Feb  1 13:28:15 2010
@@ -162,6 +162,11 @@
   printf("%.", x);  // expected-warning{{incomplete format specifier}}
   printf("%f", 4); // expected-warning{{conversion specifies type 'double' but the argument has type 'int'}}
   printf("%qd", lli);
+  printf("hhX %hhX", (unsigned char)10); // no-warning
+  printf("llX %llX", (long long) 10); // no-warning
+  // This is fine, because there is an implicit conversion to an int.
+  printf("%d", (unsigned char) 10); // no-warning
+  printf("%d", (long long) 10); // expected-warning{{conversion specifies type 'int' but the argument has type 'long long'}}
 } 
 
 typedef struct __aslclient *aslclient;





More information about the cfe-commits mailing list