[cfe-commits] r94794 - in /cfe/trunk: include/clang/Analysis/Analyses/PrintfFormatString.h include/clang/Basic/DiagnosticSemaKinds.td lib/Analysis/PrintfFormatString.cpp lib/Sema/SemaChecking.cpp

Ted Kremenek kremenek at apple.com
Thu Jan 28 19:16:21 PST 2010


Author: kremenek
Date: Thu Jan 28 21:16:21 2010
New Revision: 94794

URL: http://llvm.org/viewvc/llvm-project?rev=94794&view=rev
Log:
Alternate format string checking: issue warnings for incomplete format specifiers.

In addition, move ParseFormatString() and FormatStringHandler() from
the clang::analyze_printf to the clang namespace.  Hopefully this will
resolve some link errors on Linux.

Modified:
    cfe/trunk/include/clang/Analysis/Analyses/PrintfFormatString.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Analysis/PrintfFormatString.cpp
    cfe/trunk/lib/Sema/SemaChecking.cpp

Modified: cfe/trunk/include/clang/Analysis/Analyses/PrintfFormatString.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/PrintfFormatString.h?rev=94794&r1=94793&r2=94794&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/Analyses/PrintfFormatString.h (original)
+++ cfe/trunk/include/clang/Analysis/Analyses/PrintfFormatString.h Thu Jan 28 21:16:21 2010
@@ -74,6 +74,11 @@
   bool isUIntArg() const { return kind >= oArg && kind <= XArg; }
   bool isDoubleArg() const { return kind >= fArg && kind <= AArg; }
   Kind getKind() const { return kind; }
+  unsigned getLength() const {
+    // Conversion specifiers currently only are represented by
+    // single characters, but we be flexible.
+    return 1;
+  }
   
 private:
   const char *Position;
@@ -187,24 +192,24 @@
   bool hasLeadingZeros() const { return flags & LeadingZeroes; }  
 };
 
-  
+} // end printf namespace
+
 class FormatStringHandler {
 public:
   FormatStringHandler() {}
   virtual ~FormatStringHandler();
   
   virtual void HandleIncompleteFormatSpecifier(const char *startSpecifier,
-                                               const char *endSpecifier) {}
+                                               unsigned specifierLen) {}
 
   virtual void HandleNullChar(const char *nullCharacter) {}
+    
+  virtual void 
+    HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS,
+                                     const char *startSpecifier,
+                                     unsigned specifierLen) {}
   
-  virtual void HandleIncompletePrecision(const char *periodChar) {}
-  
-  virtual void HandleInvalidConversionSpecifier(const FormatSpecifier &FS,
-                                                const char *startSpecifier,
-                                                unsigned specifierLen) {}
-  
-  virtual bool HandleFormatSpecifier(const FormatSpecifier &FS,
+  virtual bool HandleFormatSpecifier(const analyze_printf::FormatSpecifier &FS,
                                      const char *startSpecifier,
                                      unsigned specifierLen) {
     return true;
@@ -215,6 +220,5 @@
                        const char *beg, const char *end);
 
 
-} // end printf namespace
 } // end clang namespace
 #endif

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=94794&r1=94793&r2=94794&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Jan 28 21:16:21 2010
@@ -2445,6 +2445,8 @@
   "more data arguments than '%%' conversions">, InGroup<FormatExtraArgs>;
 def warn_printf_invalid_conversion : Warning<
   "invalid conversion '%0'">, InGroup<Format>;
+def warn_printf_incomplete_specifier : Warning<
+  "incomplete format specifier '%0'">, InGroup<Format>;
 def warn_printf_missing_format_string : Warning<
   "format string missing">, InGroup<Format>;
 def warn_null_arg : Warning<

Modified: cfe/trunk/lib/Analysis/PrintfFormatString.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/PrintfFormatString.cpp?rev=94794&r1=94793&r2=94794&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/PrintfFormatString.cpp (original)
+++ cfe/trunk/lib/Analysis/PrintfFormatString.cpp Thu Jan 28 21:16:21 2010
@@ -16,6 +16,7 @@
 
 using clang::analyze_printf::FormatSpecifier;
 using clang::analyze_printf::OptionalAmount;
+using namespace clang;
 
 namespace {
 class FormatSpecifierResult {
@@ -83,9 +84,8 @@
   return OptionalAmount();  
 }
 
-static FormatSpecifierResult
-ParseFormatSpecifier(clang::analyze_printf::FormatStringHandler &H,
-                     const char *&Beg, const char *E) {
+static FormatSpecifierResult ParseFormatSpecifier(FormatStringHandler &H,
+                                                  const char *&Beg, const char *E) {
   
   using namespace clang::analyze_printf;
   
@@ -113,7 +113,7 @@
   
   if (I == E) {
     // No more characters left?
-    H.HandleIncompleteFormatSpecifier(Start, E);
+    H.HandleIncompleteFormatSpecifier(Start, E - Start);
     return true;
   }
       
@@ -136,7 +136,7 @@
 
   if (I == E) {
     // No more characters left?
-    H.HandleIncompleteFormatSpecifier(Start, E);
+    H.HandleIncompleteFormatSpecifier(Start, E - Start);
     return true;
   }
   
@@ -145,15 +145,15 @@
       
   if (I == E) {
     // No more characters left?
-    H.HandleIncompleteFormatSpecifier(Start, E);
+    H.HandleIncompleteFormatSpecifier(Start, E - Start);
     return true;
   }  
   
   // Look for the precision (if any).  
   if (*I == '.') {
-    const char *startPrecision = I++;
+    ++I;
     if (I == E) {
-      H.HandleIncompletePrecision(I - 1);
+      H.HandleIncompleteFormatSpecifier(Start, E - Start);
       return true;
     }
     
@@ -161,7 +161,7 @@
 
     if (I == E) {
       // No more characters left?
-      H.HandleIncompletePrecision(startPrecision);
+      H.HandleIncompleteFormatSpecifier(Start, E - Start);
       return true;
     }
   }
@@ -188,7 +188,7 @@
   
   if (I == E) {
     // No more characters left?
-    H.HandleIncompleteFormatSpecifier(Start, E);
+    H.HandleIncompleteFormatSpecifier(Start, E - Start);
     return true;
   }
   
@@ -230,8 +230,7 @@
   return FormatSpecifierResult(Start, FS);
 }
 
-namespace clang { namespace analyze_printf {
-bool ParseFormatString(FormatStringHandler &H,
+bool clang::ParseFormatString(FormatStringHandler &H,
                        const char *I, const char *E) {
   // Keep looking for a format specifier until we have exhausted the string.
   while (I != E) {
@@ -254,4 +253,3 @@
 }
 
 FormatStringHandler::~FormatStringHandler() {}
-}} // end namespace clang::analyze_printf

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Thu Jan 28 21:16:21 2010
@@ -1282,7 +1282,7 @@
 
 
 namespace {
-class CheckPrintfHandler : public analyze_printf::FormatStringHandler {
+class CheckPrintfHandler : public FormatStringHandler {
   Sema &S;
   const StringLiteral *FExpr;
   const Expr *OrigFormatExpr;
@@ -1306,11 +1306,9 @@
       TheCall(theCall), FormatIdx(formatIdx) {}
   
   void DoneProcessing();
-   
-//  void HandleIncompleteFormatSpecifier(const char *startSpecifier,
-//                                       const char *endSpecifier);
-  
-//  void HandleIncompletePrecision(const char *periodChar);
+     
+  void HandleIncompleteFormatSpecifier(const char *startSpecifier,
+                                       unsigned specifierLen);
   
   void HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS,
                                         const char *startSpecifier,
@@ -1341,16 +1339,25 @@
 }
 
 void CheckPrintfHandler::
+HandleIncompleteFormatSpecifier(const char *startSpecifier,
+                                unsigned specifierLen) {  
+  SourceLocation Loc = getLocationOfByte(startSpecifier);
+  S.Diag(Loc, diag::warn_printf_incomplete_specifier)
+    << llvm::StringRef(startSpecifier, specifierLen)
+    << getFormatRange();
+}
+
+void CheckPrintfHandler::
 HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS,
                                  const char *startSpecifier,
                                  unsigned specifierLen) {
   
   ++NumConversions;
-  
-  SourceLocation Loc =
-    getLocationOfByte(FS.getConversionSpecifier().getStart());
+  const analyze_printf::ConversionSpecifier &CS =
+    FS.getConversionSpecifier();  
+  SourceLocation Loc = getLocationOfByte(CS.getStart());
   S.Diag(Loc, diag::warn_printf_invalid_conversion)
-      << llvm::StringRef(startSpecifier, specifierLen)
+      << llvm::StringRef(CS.getStart(), CS.getLength())
       << getFormatRange();  
 }
 
@@ -1495,8 +1502,8 @@
                        isa<ObjCStringLiteral>(OrigFormatExpr), Str,
                        HasVAListArg, TheCall, format_idx);
 
-  analyze_printf::ParseFormatString(H, Str, Str + StrLen);
-  H.DoneProcessing();
+  if (!ParseFormatString(H, Str, Str + StrLen))
+    H.DoneProcessing();
 }
 
 //===--- CHECK: Return Address of Stack Variable --------------------------===//





More information about the cfe-commits mailing list