]> granicus.if.org Git - clang/commitdiff
Add semantic checking that the "thousands grouping"
authorTed Kremenek <kremenek@apple.com>
Sat, 8 Jan 2011 05:28:46 +0000 (05:28 +0000)
committerTed Kremenek <kremenek@apple.com>
Sat, 8 Jan 2011 05:28:46 +0000 (05:28 +0000)
prefix in a printf format string is matched
with the appropriate conversion specifier.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123055 91177308-0d34-0410-b5e6-96231b3b80d8

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

index cc1d3427e77c8a42448422611e62669a9f84c549..7cc76a8d471bd8eb9a6bda4e4d17c94e38a30e57 100644 (file)
@@ -450,6 +450,9 @@ public:
   /// more than one type.
   ArgTypeResult getArgType(ASTContext &Ctx) const;
 
+  const OptionalFlag &hasThousandsGrouping() const { 
+      return HasThousandsGrouping;
+  }
   const OptionalFlag &isLeftJustified() const { return IsLeftJustified; }
   const OptionalFlag &hasPlusPrefix() const { return HasPlusPrefix; }
   const OptionalFlag &hasAlternativeForm() const { return HasAlternativeForm; }
@@ -470,6 +473,7 @@ public:
   bool hasValidLeadingZeros() const;
   bool hasValidSpacePrefix() const;
   bool hasValidLeftJustified() const;
+  bool hasValidThousandsGroupingPrefix() const;
 
   bool hasValidPrecision() const;
   bool hasValidFieldWidth() const;
index d99de2215dcf72e9ef9a3f82b3ef6a3d31d1dff8..82ab14dbed6ec3c1f438bac30e08cd0b0bc86715 100644 (file)
@@ -590,6 +590,24 @@ bool PrintfSpecifier::hasValidLeftJustified() const {
   }
 }
 
+bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
+  if (!HasThousandsGrouping)
+    return true;
+  
+  switch (CS.getKind()) {
+    case ConversionSpecifier::dArg:
+    case ConversionSpecifier::iArg:
+    case ConversionSpecifier::uArg:
+    case ConversionSpecifier::fArg:
+    case ConversionSpecifier::FArg:
+    case ConversionSpecifier::gArg:
+    case ConversionSpecifier::GArg:
+      return true;
+    default:
+      return false;
+  }
+}
+
 bool PrintfSpecifier::hasValidPrecision() const {
   if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
     return true;
index 75b30fcb769950da2912744a63245ee0e3b8e550..0ca1ce52ab17e489b2ef7d1b0fb0d1d1457c1aed 100644 (file)
@@ -1491,6 +1491,8 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier
   }
 
   // Check each flag does not conflict with any other component.
+  if (!FS.hasValidThousandsGroupingPrefix())
+    HandleFlag(FS, FS.hasThousandsGrouping(), startSpecifier, specifierLen);
   if (!FS.hasValidLeadingZeros())
     HandleFlag(FS, FS.hasLeadingZeros(), startSpecifier, specifierLen);
   if (!FS.hasValidPlusPrefix())
index 93b6eb52b2f3ff1595544ec46f987a4c8daa71ea..be506d7c6b191e0a0f206580ed0f524bdeac0a5d 100644 (file)
@@ -336,4 +336,7 @@ void posix_extensions() {
   // Test %'d, "thousands grouping".
   // <rdar://problem/8816343>
   printf("%'d\n", 123456789); // no-warning
+  printf("%'i\n", 123456789); // no-warning
+  printf("%'f\n", (float) 1.0); // no-warning
+  printf("%'p\n", (void*) 0); // expected-warning{{results in undefined behavior with 'p' conversion specifier}}
 }