]> granicus.if.org Git - clang/commitdiff
Tweak printf format string parsing to accept 'hh' conversion specifier to accept...
authorTed Kremenek <kremenek@apple.com>
Tue, 25 Oct 2011 04:20:41 +0000 (04:20 +0000)
committerTed Kremenek <kremenek@apple.com>
Tue, 25 Oct 2011 04:20:41 +0000 (04:20 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142908 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Analysis/Analyses/FormatString.h
lib/Analysis/FormatString.cpp
lib/Analysis/PrintfFormatString.cpp
test/Sema/format-strings.c

index a2bd19c22833fa00aa6141ccab97d4e3766a1990..ac15cfc64deedd2a5768280791023a1cc7e1bf6d 100644 (file)
@@ -199,7 +199,7 @@ protected:
 class ArgTypeResult {
 public:
   enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy,
-    CStrTy, WCStrTy, WIntTy };
+              AnyCharTy, CStrTy, WCStrTy, WIntTy };
 private:
   const Kind K;
   QualType T;
index 0f807e21e7fc0e3be7554a46065cfd3202771676..6498ded4e374df02b8b10b35ff9fd8eefefc15ed 100644 (file)
@@ -183,13 +183,13 @@ clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS,
       return false;
     case 'h':
       ++I;
-      lmKind = (I != E && *I == 'h') ?
-      ++I, LengthModifier::AsChar : LengthModifier::AsShort;
+      lmKind = (I != E && *I == 'h') ? (++I, LengthModifier::AsChar)
+                                     : LengthModifier::AsShort;
       break;
     case 'l':
       ++I;
-      lmKind = (I != E && *I == 'l') ?
-      ++I, LengthModifier::AsLongLong : LengthModifier::AsLong;
+      lmKind = (I != E && *I == 'l') ? (++I, LengthModifier::AsLongLong)
+                                     : LengthModifier::AsLong;
       break;
     case 'j': lmKind = LengthModifier::AsIntMax;     ++I; break;
     case 'z': lmKind = LengthModifier::AsSizeT;      ++I; break;
@@ -213,7 +213,21 @@ bool ArgTypeResult::matchesType(ASTContext &C, QualType argTy) const {
 
     case UnknownTy:
       return true;
-
+      
+    case AnyCharTy: {
+      if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
+        switch (BT->getKind()) {
+          default:
+            break;
+          case BuiltinType::Char_S:
+          case BuiltinType::SChar:
+          case BuiltinType::UChar:
+          case BuiltinType::Char_U:
+            return true;            
+        }
+      return false;
+    }
+      
     case SpecificTy: {
       argTy = C.getCanonicalType(argTy).getUnqualifiedType();
       if (T == argTy)
@@ -314,6 +328,8 @@ QualType ArgTypeResult::getRepresentativeType(ASTContext &C) const {
       llvm_unreachable("No representative type for Invalid ArgTypeResult");
     case UnknownTy:
       return QualType();
+    case AnyCharTy:
+      return C.CharTy;
     case SpecificTy:
       return T;
     case CStrTy:
index affc83e7efb8f64aa8bf20150312384d2a1982b6..7347dca3c21e3024ba56a764a945e07d86fb1e7e 100644 (file)
@@ -297,7 +297,7 @@ ArgTypeResult PrintfSpecifier::getArgType(ASTContext &Ctx) const {
       case LengthModifier::AsLongDouble:
         return ArgTypeResult::Invalid();
       case LengthModifier::None: return Ctx.IntTy;
-      case LengthModifier::AsChar: return Ctx.SignedCharTy;
+      case LengthModifier::AsChar: return ArgTypeResult::AnyCharTy;
       case LengthModifier::AsShort: return Ctx.ShortTy;
       case LengthModifier::AsLong: return Ctx.LongTy;
       case LengthModifier::AsLongLong: return Ctx.LongLongTy;
index 6b5f7e2c26623deb904815b42d5d44291c442c5b..4f2ad99a5727c4083e50727471c984d74e817989 100644 (file)
@@ -212,6 +212,12 @@ void test12(char *b) {
   asprintf(&b, "%d", "asprintf"); // expected-warning{{conversion specifies type 'int' but the argument has type 'char *'}}
 }
 
+void test13(short x) {
+  char bel = 007;
+  printf("bel: '0%hhd'\n", bel); // no-warning
+  printf("x: '0%hhd'\n", x); // expected-warning {{conversion specifies type 'char' but the argument has type 'short'}}
+}
+
 typedef struct __aslclient *aslclient;
 typedef struct __aslmsg *aslmsg;
 int asl_log(aslclient asl, aslmsg msg, int level, const char *format, ...) __attribute__((__format__ (__printf__, 4, 5)));