[cfe-commits] r108903 - in /cfe/trunk: include/clang/Analysis/Analyses/FormatString.h lib/Analysis/PrintfFormatString.cpp lib/Analysis/ScanfFormatString.cpp lib/Sema/SemaChecking.cpp

Ted Kremenek kremenek at apple.com
Tue Jul 20 13:04:27 PDT 2010


Author: kremenek
Date: Tue Jul 20 15:04:27 2010
New Revision: 108903

URL: http://llvm.org/viewvc/llvm-project?rev=108903&view=rev
Log:
Add 'ConversionSpecifier' root class in 'analyze_format_string' namespace and
derived 'PrintfConversionSpecifier' from this class.  We will do the same for
'ScanfConversionSpecifier'.

Modified:
    cfe/trunk/include/clang/Analysis/Analyses/FormatString.h
    cfe/trunk/lib/Analysis/PrintfFormatString.cpp
    cfe/trunk/lib/Analysis/ScanfFormatString.cpp
    cfe/trunk/lib/Sema/SemaChecking.cpp

Modified: cfe/trunk/include/clang/Analysis/Analyses/FormatString.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/FormatString.h?rev=108903&r1=108902&r2=108903&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/Analyses/FormatString.h (original)
+++ cfe/trunk/include/clang/Analysis/Analyses/FormatString.h Tue Jul 20 15:04:27 2010
@@ -104,6 +104,82 @@
   const char *Position;
   Kind kind;
 };
+  
+class ConversionSpecifier {
+public:
+  enum Kind {
+    InvalidSpecifier = 0,
+      // C99 conversion specifiers.
+    cArg,
+    dArg,
+    iArg,
+    IntArgBeg = cArg, IntArgEnd = iArg,    
+    
+    oArg,
+    uArg,
+    xArg,
+    XArg,
+    UIntArgBeg = oArg, UIntArgEnd = XArg,
+    
+    fArg,
+    FArg,
+    eArg,
+    EArg,
+    gArg,
+    GArg,
+    aArg,
+    AArg,
+    DoubleArgBeg = fArg, DoubleArgEnd = AArg,
+    
+    sArg,
+    pArg,
+    nArg,
+    PercentArg,
+    CArg,
+    SArg,
+    
+    // ** Printf-specific **
+  
+    // Objective-C specific specifiers.
+    ObjCObjArg,  // '@'
+    ObjCBeg = ObjCObjArg, ObjCEnd = ObjCObjArg,
+    
+    // GlibC specific specifiers.
+    PrintErrno,   // 'm'
+    
+    PrintfConvBeg = ObjCObjArg, PrintfConvEnd = PrintErrno
+  };
+  
+  ConversionSpecifier(bool isPrintf)
+    : IsPrintf(isPrintf), Position(0), kind(InvalidSpecifier) {}
+  
+  ConversionSpecifier(bool isPrintf, const char *pos, Kind k)
+    : IsPrintf(isPrintf), Position(pos), kind(k) {}
+  
+  const char *getStart() const {
+    return Position;
+  }
+  
+  llvm::StringRef getCharacters() const {
+    return llvm::StringRef(getStart(), getLength());
+  }
+  
+  Kind getKind() const { return kind; }
+  void setKind(Kind k) { kind = k; }
+  unsigned getLength() const {
+      // Conversion specifiers currently only are represented by
+      // single characters, but we be flexible.
+    return 1;
+  }
+  const char *toString() const;
+  
+  bool isPrintfKind() const { return IsPrintf; }
+
+protected:
+  bool IsPrintf;
+  const char *Position;
+  Kind kind;
+};
 
 class ArgTypeResult {
 public:
@@ -253,64 +329,14 @@
 
 namespace analyze_printf {
 
-class ConversionSpecifier {
+class PrintfConversionSpecifier : 
+  public analyze_format_string::ConversionSpecifier  {
 public:
-  enum Kind {
-    InvalidSpecifier = 0,
-    // C99 conversion specifiers.
-    cArg,
-    dArg,
-    iArg,
-    IntArgBeg = cArg, IntArgEnd = iArg,    
-
-    oArg,
-    uArg,
-    xArg,
-    XArg,
-    UIntArgBeg = oArg, UIntArgEnd = XArg,
-
-    fArg,
-    FArg,
-    eArg,
-    EArg,
-    gArg,
-    GArg,
-    aArg,
-    AArg,
-    DoubleArgBeg = fArg, DoubleArgEnd = AArg,
-
-    sArg,
-    pArg,
-    nArg,
-    PercentArg,
-    CArg,
-    SArg,
+  PrintfConversionSpecifier()
+    : ConversionSpecifier(true, 0, InvalidSpecifier) {}
 
-    // ** Printf-specific **
-    
-    // Objective-C specific specifiers.
-    ObjCObjArg,  // '@'
-    ObjCBeg = ObjCObjArg, ObjCEnd = ObjCObjArg,
-    
-    // GlibC specific specifiers.
-    PrintErrno,   // 'm'
-    
-    PrintfConvBeg = ObjCObjArg, PrintfConvEnd = PrintErrno
-  };
-
-  ConversionSpecifier()
-  : Position(0), kind(InvalidSpecifier) {}
-
-  ConversionSpecifier(const char *pos, Kind k)
-  : Position(pos), kind(k) {}
-
-  const char *getStart() const {
-    return Position;
-  }
-
-  llvm::StringRef getCharacters() const {
-    return llvm::StringRef(getStart(), getLength());
-  }
+  PrintfConversionSpecifier(const char *pos, Kind k)
+    : ConversionSpecifier(true, pos, k) {}
 
   bool consumesDataArgument() const {
     switch (kind) {
@@ -323,21 +349,19 @@
   }
 
   bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; }
-  bool isIntArg() const { return kind >= dArg && kind <= iArg; }
-  bool isUIntArg() const { return kind >= oArg && kind <= XArg; }
-  bool isDoubleArg() const { return kind >= fArg && kind <= AArg; }
-  Kind getKind() const { return kind; }
-  void setKind(Kind k) { kind = k; }
+  bool isIntArg() const { return kind >= IntArgBeg && kind <= IntArgEnd; }
+  bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; }
+  bool isDoubleArg() const { return kind >= DoubleArgBeg && 
+                                    kind <= DoubleArgBeg; }
   unsigned getLength() const {
       // Conversion specifiers currently only are represented by
       // single characters, but we be flexible.
     return 1;
   }
-  const char *toString() const;
 
-private:
-  const char *Position;
-  Kind kind;
+  static bool classof(const analyze_format_string::ConversionSpecifier *CS) {
+    return CS->isPrintfKind();
+  }
 };
 
 using analyze_format_string::ArgTypeResult;
@@ -351,17 +375,17 @@
   OptionalFlag HasSpacePrefix; // ' '
   OptionalFlag HasAlternativeForm; // '#'
   OptionalFlag HasLeadingZeroes; // '0'
-  ConversionSpecifier CS;
+  analyze_format_string::ConversionSpecifier CS;
   OptionalAmount Precision;
 public:
   PrintfSpecifier() :
-  IsLeftJustified("-"), HasPlusPrefix("+"), HasSpacePrefix(" "),
-  HasAlternativeForm("#"), HasLeadingZeroes("0") {}
+    IsLeftJustified("-"), HasPlusPrefix("+"), HasSpacePrefix(" "),
+    HasAlternativeForm("#"), HasLeadingZeroes("0"), CS(/* isPrintf = */ true) {}
 
   static PrintfSpecifier Parse(const char *beg, const char *end);
 
     // Methods for incrementally constructing the PrintfSpecifier.
-  void setConversionSpecifier(const ConversionSpecifier &cs) {
+  void setConversionSpecifier(const PrintfConversionSpecifier &cs) {
     CS = cs;
   }
   void setIsLeftJustified(const char *position) {
@@ -388,8 +412,8 @@
 
     // Methods for querying the format specifier.
 
-  const ConversionSpecifier &getConversionSpecifier() const {
-    return CS;
+  const PrintfConversionSpecifier &getConversionSpecifier() const {
+    return cast<PrintfConversionSpecifier>(CS);
   }
 
   void setPrecision(const OptionalAmount &Amt) {
@@ -402,7 +426,7 @@
   }
   
   bool consumesDataArgument() const {
-    return CS.consumesDataArgument();
+    return getConversionSpecifier().consumesDataArgument();
   }
 
   /// \brief Returns the builtin type that a data argument
@@ -444,7 +468,7 @@
 
 namespace analyze_scanf {
 
-class ConversionSpecifier {
+class ScanfConversionSpecifier {
 public:
   enum Kind {
     InvalidSpecifier = 0,
@@ -481,10 +505,10 @@
     DoubleArgEnd = AArg
   };
 
-  ConversionSpecifier()
+  ScanfConversionSpecifier()
   : Position(0), EndScanList(0), kind(InvalidSpecifier) {}
 
-  ConversionSpecifier(const char *pos, Kind k)
+  ScanfConversionSpecifier(const char *pos, Kind k)
   : Position(pos), EndScanList(0), kind(k) {}
 
   const char *getStart() const {
@@ -525,7 +549,7 @@
 
 class ScanfSpecifier : public analyze_format_string::FormatSpecifier {
   OptionalFlag SuppressAssignment; // '*'
-  ConversionSpecifier CS;
+  ScanfConversionSpecifier CS;
 public:
   ScanfSpecifier() : SuppressAssignment("*") {}
 
@@ -538,11 +562,11 @@
     return SuppressAssignment;
   }
 
-  void setConversionSpecifier(const ConversionSpecifier &cs) {
+  void setConversionSpecifier(const ScanfConversionSpecifier &cs) {
     CS = cs;
   }
 
-  const ConversionSpecifier &getConversionSpecifier() const {
+  const ScanfConversionSpecifier &getConversionSpecifier() const {
     return CS;
   }
   

Modified: cfe/trunk/lib/Analysis/PrintfFormatString.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/PrintfFormatString.cpp?rev=108903&r1=108902&r2=108903&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/PrintfFormatString.cpp (original)
+++ cfe/trunk/lib/Analysis/PrintfFormatString.cpp Tue Jul 20 15:04:27 2010
@@ -19,7 +19,7 @@
 using clang::analyze_format_string::FormatStringHandler;
 using clang::analyze_format_string::LengthModifier;
 using clang::analyze_format_string::OptionalAmount;
-using clang::analyze_printf::ConversionSpecifier;
+using clang::analyze_format_string::ConversionSpecifier;
 using clang::analyze_printf::PrintfSpecifier;
 
 using namespace clang;
@@ -54,6 +54,7 @@
                                                   const char *E,
                                                   unsigned &argIndex) {
 
+  using namespace clang::analyze_format_string;
   using namespace clang::analyze_printf;
 
   const char *I = Beg;
@@ -192,7 +193,7 @@
     // Glibc specific.
     case 'm': k = ConversionSpecifier::PrintErrno; break;
   }
-  ConversionSpecifier CS(conversionPosition, k);
+  PrintfConversionSpecifier CS(conversionPosition, k);
   FS.setConversionSpecifier(CS);
   if (CS.consumesDataArgument() && !FS.usesPositionalArg())
     FS.setArgIndex(argIndex++);
@@ -274,6 +275,8 @@
 //===----------------------------------------------------------------------===//
 
 ArgTypeResult PrintfSpecifier::getArgType(ASTContext &Ctx) const {
+  const PrintfConversionSpecifier &CS = getConversionSpecifier();
+  
   if (!CS.consumesDataArgument())
     return ArgTypeResult::Invalid();
 

Modified: cfe/trunk/lib/Analysis/ScanfFormatString.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ScanfFormatString.cpp?rev=108903&r1=108902&r2=108903&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/ScanfFormatString.cpp (original)
+++ cfe/trunk/lib/Analysis/ScanfFormatString.cpp Tue Jul 20 15:04:27 2010
@@ -19,14 +19,14 @@
 using clang::analyze_format_string::FormatStringHandler;
 using clang::analyze_format_string::LengthModifier;
 using clang::analyze_format_string::OptionalAmount;
-using clang::analyze_scanf::ConversionSpecifier;
+using clang::analyze_scanf::ScanfConversionSpecifier;
 using clang::analyze_scanf::ScanfSpecifier;
 
 typedef clang::analyze_format_string::SpecifierResult<ScanfSpecifier>
         ScanfSpecifierResult;
 
 static bool ParseScanList(FormatStringHandler &H,
-                          ConversionSpecifier &CS,
+                          ScanfConversionSpecifier &CS,
                           const char *&Beg, const char *E) {
   const char *I = Beg;
   const char *start = I - 1;
@@ -142,34 +142,34 @@
   
   // Finally, look for the conversion specifier.
   const char *conversionPosition = I++;
-  ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier;
+  ScanfConversionSpecifier::Kind k = ScanfConversionSpecifier::InvalidSpecifier;
   switch (*conversionPosition) {
     default:
       break;
-    case '%': k = ConversionSpecifier::PercentArg;   break;
-    case 'A': k = ConversionSpecifier::AArg; break;
-    case 'E': k = ConversionSpecifier::EArg; break;
-    case 'F': k = ConversionSpecifier::FArg; break;
-    case 'G': k = ConversionSpecifier::GArg; break;
-    case 'X': k = ConversionSpecifier::XArg; break;
-    case 'a': k = ConversionSpecifier::aArg; break;
-    case 'd': k = ConversionSpecifier::dArg; break;
-    case 'e': k = ConversionSpecifier::eArg; break;
-    case 'f': k = ConversionSpecifier::fArg; break;
-    case 'g': k = ConversionSpecifier::gArg; break;
-    case 'i': k = ConversionSpecifier::iArg; break;
-    case 'n': k = ConversionSpecifier::nArg; break;
-    case 'c': k = ConversionSpecifier::cArg; break;
-    case 'C': k = ConversionSpecifier::CArg; break;
-    case 'S': k = ConversionSpecifier::SArg; break;
-    case '[': k = ConversionSpecifier::ScanListArg; break;
-    case 'u': k = ConversionSpecifier::uArg; break;
-    case 'x': k = ConversionSpecifier::xArg; break;
-    case 'o': k = ConversionSpecifier::oArg; break;
-    case 's': k = ConversionSpecifier::sArg; break;
+    case '%': k = ScanfConversionSpecifier::PercentArg;   break;
+    case 'A': k = ScanfConversionSpecifier::AArg; break;
+    case 'E': k = ScanfConversionSpecifier::EArg; break;
+    case 'F': k = ScanfConversionSpecifier::FArg; break;
+    case 'G': k = ScanfConversionSpecifier::GArg; break;
+    case 'X': k = ScanfConversionSpecifier::XArg; break;
+    case 'a': k = ScanfConversionSpecifier::aArg; break;
+    case 'd': k = ScanfConversionSpecifier::dArg; break;
+    case 'e': k = ScanfConversionSpecifier::eArg; break;
+    case 'f': k = ScanfConversionSpecifier::fArg; break;
+    case 'g': k = ScanfConversionSpecifier::gArg; break;
+    case 'i': k = ScanfConversionSpecifier::iArg; break;
+    case 'n': k = ScanfConversionSpecifier::nArg; break;
+    case 'c': k = ScanfConversionSpecifier::cArg; break;
+    case 'C': k = ScanfConversionSpecifier::CArg; break;
+    case 'S': k = ScanfConversionSpecifier::SArg; break;
+    case '[': k = ScanfConversionSpecifier::ScanListArg; break;
+    case 'u': k = ScanfConversionSpecifier::uArg; break;
+    case 'x': k = ScanfConversionSpecifier::xArg; break;
+    case 'o': k = ScanfConversionSpecifier::oArg; break;
+    case 's': k = ScanfConversionSpecifier::sArg; break;
   }
-  ConversionSpecifier CS(conversionPosition, k);
-  if (k == ConversionSpecifier::ScanListArg) {
+  ScanfConversionSpecifier CS(conversionPosition, k);
+  if (k == ScanfConversionSpecifier::ScanListArg) {
     if (!ParseScanList(H, CS, I, E))
       return true;
   }
@@ -181,7 +181,7 @@
   // FIXME: '%' and '*' doesn't make sense.  Issue a warning.
   // FIXME: 'ConsumedSoFar' and '*' doesn't make sense.
   
-  if (k == ConversionSpecifier::InvalidSpecifier) {
+  if (k == ScanfConversionSpecifier::InvalidSpecifier) {
     // Assume the conversion takes one argument.
     return !H.HandleInvalidScanfConversionSpecifier(FS, Beg, I - Beg);
   }

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=108903&r1=108902&r2=108903&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Tue Jul 20 15:04:27 2010
@@ -1316,7 +1316,7 @@
                                       const analyze_printf::PrintfSpecifier &FS,
                                       const char *startSpecifier,
                                       unsigned specifierLen) {
-  const analyze_printf::ConversionSpecifier &CS =
+  const analyze_printf::PrintfConversionSpecifier &CS =
     FS.getConversionSpecifier();
   
   return HandleInvalidConversionSpecifier(FS.getArgIndex(),
@@ -1375,7 +1375,8 @@
                                       unsigned type,
                                       const char *startSpecifier,
                                       unsigned specifierLen) {
-  const analyze_printf::ConversionSpecifier &CS = FS.getConversionSpecifier();
+  const analyze_printf::PrintfConversionSpecifier &CS =
+    FS.getConversionSpecifier();
   switch (Amt.getHowSpecified()) {
   case analyze_printf::OptionalAmount::Constant:
     S.Diag(getLocationOfByte(Amt.getStart()),
@@ -1402,7 +1403,8 @@
                                     const char *startSpecifier,
                                     unsigned specifierLen) {
   // Warn about pointless flag with a fixit removal.
-  const analyze_printf::ConversionSpecifier &CS = FS.getConversionSpecifier();
+  const analyze_printf::PrintfConversionSpecifier &CS =
+    FS.getConversionSpecifier();
   S.Diag(getLocationOfByte(flag.getPosition()),
       diag::warn_printf_nonsensical_flag)
     << flag.toString() << CS.toString()
@@ -1431,8 +1433,9 @@
                                           const char *startSpecifier,
                                           unsigned specifierLen) {
 
+  using namespace analyze_format_string;
   using namespace analyze_printf;  
-  const ConversionSpecifier &CS = FS.getConversionSpecifier();
+  const PrintfConversionSpecifier &CS = FS.getConversionSpecifier();
 
   if (FS.consumesDataArgument()) {
     if (atFirstArg) {
@@ -1636,7 +1639,7 @@
                                         const char *startSpecifier,
                                         unsigned specifierLen) {
 
-  const analyze_scanf::ConversionSpecifier &CS =
+  const analyze_scanf::ScanfConversionSpecifier &CS =
     FS.getConversionSpecifier();
 
   return HandleInvalidConversionSpecifier(FS.getArgIndex(),
@@ -1653,7 +1656,7 @@
   using namespace analyze_scanf;
   using namespace analyze_format_string;  
 
-  const ConversionSpecifier &CS = FS.getConversionSpecifier();
+  const ScanfConversionSpecifier &CS = FS.getConversionSpecifier();
 
   // Handle case where '%' and '*' don't consume an argument.  These shouldn't
   // be used to decide if we are using positional arguments consistently.





More information about the cfe-commits mailing list