[cfe-commits] r94851 - in /cfe/trunk: include/clang/Analysis/Analyses/PrintfFormatString.h lib/Analysis/PrintfFormatString.cpp

Ted Kremenek kremenek at apple.com
Fri Jan 29 14:59:33 PST 2010


Author: kremenek
Date: Fri Jan 29 16:59:32 2010
New Revision: 94851

URL: http://llvm.org/viewvc/llvm-project?rev=94851&view=rev
Log:
Per a suggestion from Cristian Draghici, add a method to FormatSpecifier that returns the expected type of the matching data argument.  It isn't complete, but should handle several of the important cases.

Modified:
    cfe/trunk/include/clang/Analysis/Analyses/PrintfFormatString.h
    cfe/trunk/lib/Analysis/PrintfFormatString.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=94851&r1=94850&r2=94851&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/Analyses/PrintfFormatString.h (original)
+++ cfe/trunk/include/clang/Analysis/Analyses/PrintfFormatString.h Fri Jan 29 16:59:32 2010
@@ -15,9 +15,12 @@
 #ifndef LLVM_CLANG_FPRINTF_FORMAT_H
 #define LLVM_CLANG_FPRINTF_FORMAT_H
 
-#include <cassert>
+#include "clang/AST/CanonicalType.h"
 
 namespace clang {
+    
+class ASTContext;
+  
 namespace analyze_printf {
 
 class ConversionSpecifier {
@@ -147,24 +150,45 @@
   HowSpecified hs;
   unsigned amt;
 };
+  
+class ArgTypeResult {
+  enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy };
+  const Kind K;
+  QualType T;
+  ArgTypeResult(bool) : K(InvalidTy) {}  
+public:
+  ArgTypeResult() : K(UnknownTy) {}
+  ArgTypeResult(QualType t) : K(SpecificTy), T(t) {}
+  ArgTypeResult(CanQualType t) : K(SpecificTy), T(t) {}
+  
+  static ArgTypeResult Invalid() { return ArgTypeResult(true); }
+  
+  bool isValid() const { return K != InvalidTy; }
+  
+  const QualType *getSpecificType() const { 
+    return K == SpecificTy ? &T : 0;
+  }
+    
+  bool matchesAnyObjCObjectRef() const { return K == ObjCPointerTy; };
+};    
 
 class FormatSpecifier {
-  unsigned lengthModifier : 5;
+  LengthModifier LM;
   unsigned flags : 5;
-  ConversionSpecifier conversionSpecifier;
+  ConversionSpecifier CS;
   OptionalAmount FieldWidth;
   OptionalAmount Precision;
 public:
-  FormatSpecifier() : lengthModifier(0), flags(0) {}
+  FormatSpecifier() : LM(None), flags(0) {}
   
   static FormatSpecifier Parse(const char *beg, const char *end);
 
   // Methods for incrementally constructing the FormatSpecifier.
-  void setConversionSpecifier(const ConversionSpecifier &CS) {
-    conversionSpecifier = CS;    
+  void setConversionSpecifier(const ConversionSpecifier &cs) {
+    CS = cs;
   }
   void setLengthModifier(LengthModifier lm) {
-    lengthModifier = (unsigned) lm;
+    LM = lm;
   }
   void setIsLeftJustified() { flags |= LeftJustified; }
   void setHasPlusPrefix() { flags |= PlusPrefix; }
@@ -175,11 +199,11 @@
   // Methods for querying the format specifier.
 
   const ConversionSpecifier &getConversionSpecifier() const {
-    return conversionSpecifier;
+    return CS;
   }
 
   LengthModifier getLengthModifier() const {
-    return (LengthModifier) lengthModifier;
+    return LM;
   }
   
   const OptionalAmount &getFieldWidth() const {
@@ -197,6 +221,13 @@
   const OptionalAmount &getPrecision() const {
     return Precision;
   }
+	
+  /// \brief Returns the builtin type that a data argument
+  /// paired with this format specifier should have.  This method
+  /// 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;
 
   bool isLeftJustified() const { return flags & LeftJustified; }
   bool hasPlusPrefix() const { return flags & PlusPrefix; }

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

==============================================================================
--- cfe/trunk/lib/Analysis/PrintfFormatString.cpp (original)
+++ cfe/trunk/lib/Analysis/PrintfFormatString.cpp Fri Jan 29 16:59:32 2010
@@ -13,9 +13,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Analysis/Analyses/PrintfFormatString.h"
+#include "clang/AST/ASTContext.h"
 
 using clang::analyze_printf::FormatSpecifier;
 using clang::analyze_printf::OptionalAmount;
+using clang::analyze_printf::ArgTypeResult;
 using namespace clang;
 
 namespace {
@@ -261,3 +263,54 @@
 }
 
 FormatStringHandler::~FormatStringHandler() {}
+
+//===----------------------------------------------------------------------===//
+// Methods on FormatSpecifier.
+//===----------------------------------------------------------------------===//
+
+ArgTypeResult FormatSpecifier::getArgType(ASTContext &Ctx) const {
+  if (!CS.consumesDataArgument())
+    return ArgTypeResult::Invalid();
+  
+  if (CS.isIntArg())
+    switch (LM) {
+      case AsLongDouble: 
+        return ArgTypeResult::Invalid();
+      case None: return Ctx.IntTy;
+      case AsChar: return Ctx.SignedCharTy;
+      case AsShort: return Ctx.ShortTy;
+      case AsLong: return Ctx.LongTy;
+      case AsLongLong: return Ctx.LongLongTy;
+      case AsIntMax:
+        // FIXME: Return unknown for now.
+        return ArgTypeResult();
+      case AsSizeT: return Ctx.getSizeType();
+      case AsPtrDiff: return Ctx.getPointerDiffType();
+    }
+
+  if (CS.isUIntArg())
+    switch (LM) {
+      case AsLongDouble: 
+        return ArgTypeResult::Invalid();
+      case None: return Ctx.UnsignedIntTy;
+      case AsChar: return Ctx.UnsignedCharTy;
+      case AsShort: return Ctx.UnsignedShortTy;
+      case AsLong: return Ctx.UnsignedLongTy;
+      case AsLongLong: return Ctx.UnsignedLongLongTy;
+      case AsIntMax:
+        // FIXME: Return unknown for now.
+        return ArgTypeResult();
+      case AsSizeT: 
+        // FIXME: How to get the corresponding unsigned
+        // version of size_t?
+        return ArgTypeResult();
+      case AsPtrDiff:
+        // FIXME: How to get the corresponding unsigned
+        // version of ptrdiff_t?
+        return ArgTypeResult();
+    }
+
+  // FIXME: Handle other cases.
+	return ArgTypeResult();
+}
+





More information about the cfe-commits mailing list