<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Hi Hans<div><br></div><div>We're getting some buildbot errors after this change when running some gcc tests.</div><div><br></div><div>The tests in question are:</div><div><br></div><div><span class="Apple-style-span" style="font-family: Times; "><pre style="font-family: 'Courier New', courier, monotype; "><span class="stdout" style="font-family: 'Courier New', courier, monotype; color: black; ">gcc.dg/format/c90-scanf-3.c   (test for excess errors)
gcc.dg/format/c90-scanf-3.c  -DWIDE  (test for excess errors)
gcc.dg/format/ext-4.c   (test for excess errors)
gcc.dg/format/ext-4.c  -DWIDE  (test for excess errors)</span></pre></span><div>Can you please take a look at how you want your fix to interact with the -pedantic warnings on those tests?</div><div><br></div><div>Oh, and shouldn't make much difference as those are front-end tests but this is on x86-64 darwin.</div><div><br></div><div>Thanks,</div><div>Pete</div><div><br></div><div><div>On Dec 10, 2011, at 5:20 AM, Hans Wennborg wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div>Author: hans<br>Date: Sat Dec 10 07:20:11 2011<br>New Revision: 146326<br><br>URL: <a href="http://llvm.org/viewvc/llvm-project?rev=146326&view=rev">http://llvm.org/viewvc/llvm-project?rev=146326&view=rev</a><br>Log:<br>Check that arguments to a scanf call match the format specifier,<br>and offer fixits when there is a mismatch.<br><br>Modified:<br>    cfe/trunk/include/clang/Analysis/Analyses/FormatString.h<br>    cfe/trunk/lib/Analysis/ScanfFormatString.cpp<br>    cfe/trunk/lib/Sema/SemaChecking.cpp<br>    cfe/trunk/test/Analysis/taint-generic.c<br>    cfe/trunk/test/Analysis/taint-tester.c<br>    cfe/trunk/test/Sema/format-strings-fixit.c<br>    cfe/trunk/test/Sema/format-strings-int-typedefs.c<br>    cfe/trunk/test/Sema/format-strings-scanf.c<br><br>Modified: cfe/trunk/include/clang/Analysis/Analyses/FormatString.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/FormatString.h?rev=146326&r1=146325&r2=146326&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/FormatString.h?rev=146326&r1=146325&r2=146326&view=diff</a><br>==============================================================================<br>--- cfe/trunk/include/clang/Analysis/Analyses/FormatString.h (original)<br>+++ cfe/trunk/include/clang/Analysis/Analyses/FormatString.h Sat Dec 10 07:20:11 2011<br>@@ -185,6 +185,7 @@<br>     return EndScanList ? EndScanList - Position : 1;<br>   }<br><br>+  bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; }<br>   const char *toString() const;<br><br>   bool isPrintfKind() const { return IsPrintf; }<br>@@ -364,7 +365,6 @@<br><br>   bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; }<br>   bool isIntArg() const { return kind >= IntArgBeg && kind <= IntArgEnd; }<br>-  bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; }<br>   bool isDoubleArg() const { return kind >= DoubleArgBeg &&<br>                                     kind <= DoubleArgBeg; }<br>   unsigned getLength() const {<br>@@ -506,10 +506,35 @@<br>   }<br> };<br><br>+using analyze_format_string::ArgTypeResult;<br> using analyze_format_string::LengthModifier;<br> using analyze_format_string::OptionalAmount;<br> using analyze_format_string::OptionalFlag;<br><br>+class ScanfArgTypeResult : public ArgTypeResult {<br>+public:<br>+  enum Kind { UnknownTy, InvalidTy, CStrTy, WCStrTy, PtrToArgTypeResultTy };<br>+private:<br>+  Kind K;<br>+  ArgTypeResult A;<br>+  const char *Name;<br>+  QualType getRepresentativeType(ASTContext &C) const;<br>+public:<br>+  ScanfArgTypeResult(Kind k = UnknownTy, const char* n = 0) : K(k), Name(n) {}<br>+  ScanfArgTypeResult(ArgTypeResult a, const char *n = 0)<br>+      : K(PtrToArgTypeResultTy), A(a), Name(n) {<br>+    assert(A.isValid());<br>+  }<br>+<br>+  static ScanfArgTypeResult Invalid() { return ScanfArgTypeResult(InvalidTy); }<br>+<br>+  bool isValid() const { return K != InvalidTy; }<br>+<br>+  bool matchesType(ASTContext& C, QualType argTy) const;<br>+<br>+  std::string getRepresentativeTypeName(ASTContext& C) const;<br>+};<br>+<br> class ScanfSpecifier : public analyze_format_string::FormatSpecifier {<br>   OptionalFlag SuppressAssignment; // '*'<br> public:<br>@@ -538,6 +563,12 @@<br>     return CS.consumesDataArgument() && !SuppressAssignment;<br>   }<br><br>+  ScanfArgTypeResult getArgType(ASTContext &Ctx) const;<br>+<br>+  bool fixType(QualType QT, const LangOptions &LangOpt);<br>+<br>+  void toString(raw_ostream &os) const;<br>+<br>   static ScanfSpecifier Parse(const char *beg, const char *end);<br> };<br><br><br>Modified: cfe/trunk/lib/Analysis/ScanfFormatString.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ScanfFormatString.cpp?rev=146326&r1=146325&r2=146326&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ScanfFormatString.cpp?rev=146326&r1=146325&r2=146326&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Analysis/ScanfFormatString.cpp (original)<br>+++ cfe/trunk/lib/Analysis/ScanfFormatString.cpp Sat Dec 10 07:20:11 2011<br>@@ -20,9 +20,11 @@<br> using clang::analyze_format_string::LengthModifier;<br> using clang::analyze_format_string::OptionalAmount;<br> using clang::analyze_format_string::ConversionSpecifier;<br>+using clang::analyze_scanf::ScanfArgTypeResult;<br> using clang::analyze_scanf::ScanfConversionSpecifier;<br> using clang::analyze_scanf::ScanfSpecifier;<br> using clang::UpdateOnReturn;<br>+using namespace clang;<br><br> typedef clang::analyze_format_string::SpecifierResult<ScanfSpecifier><br>         ScanfSpecifierResult;<br>@@ -190,7 +192,213 @@<br>   }<br>   return ScanfSpecifierResult(Start, FS);<br> }<br>-  <br>+<br>+ScanfArgTypeResult ScanfSpecifier::getArgType(ASTContext &Ctx) const {<br>+  const ScanfConversionSpecifier &CS = getConversionSpecifier();<br>+<br>+  if (!CS.consumesDataArgument())<br>+    return ScanfArgTypeResult::Invalid();<br>+<br>+  switch(CS.getKind()) {<br>+    // Signed int.<br>+    case ConversionSpecifier::dArg:<br>+    case ConversionSpecifier::iArg:<br>+      switch (LM.getKind()) {<br>+        case LengthModifier::None: return ArgTypeResult(Ctx.IntTy);<br>+        case LengthModifier::AsChar:<br>+          return ArgTypeResult(ArgTypeResult::AnyCharTy);<br>+        case LengthModifier::AsShort: return ArgTypeResult(Ctx.ShortTy);<br>+        case LengthModifier::AsLong: return ArgTypeResult(Ctx.LongTy);<br>+        case LengthModifier::AsLongLong: return ArgTypeResult(Ctx.LongLongTy);<br>+        case LengthModifier::AsIntMax:<br>+          return ScanfArgTypeResult(Ctx.getIntMaxType(), "intmax_t *");<br>+        case LengthModifier::AsSizeT:<br>+          // FIXME: ssize_t.<br>+          return ScanfArgTypeResult();<br>+        case LengthModifier::AsPtrDiff:<br>+          return ScanfArgTypeResult(Ctx.getPointerDiffType(), "ptrdiff_t *");<br>+        case LengthModifier::AsLongDouble: return ScanfArgTypeResult::Invalid();<br>+      }<br>+<br>+    // Unsigned int.<br>+    case ConversionSpecifier::oArg:<br>+    case ConversionSpecifier::uArg:<br>+    case ConversionSpecifier::xArg:<br>+    case ConversionSpecifier::XArg:<br>+      switch (LM.getKind()) {<br>+        case LengthModifier::None: return ArgTypeResult(Ctx.UnsignedIntTy);<br>+        case LengthModifier::AsChar: return ArgTypeResult(Ctx.UnsignedCharTy);<br>+        case LengthModifier::AsShort: return ArgTypeResult(Ctx.UnsignedShortTy);<br>+        case LengthModifier::AsLong: return ArgTypeResult(Ctx.UnsignedLongTy);<br>+        case LengthModifier::AsLongLong:<br>+          return ArgTypeResult(Ctx.UnsignedLongLongTy);<br>+        case LengthModifier::AsIntMax:<br>+          return ScanfArgTypeResult(Ctx.getUIntMaxType(), "uintmax_t *");<br>+        case LengthModifier::AsSizeT:<br>+          return ScanfArgTypeResult(Ctx.getSizeType(), "size_t *");<br>+        case LengthModifier::AsPtrDiff:<br>+          // FIXME: Unsigned version of ptrdiff_t?<br>+          return ScanfArgTypeResult();<br>+        case LengthModifier::AsLongDouble: return ScanfArgTypeResult::Invalid();<br>+      }<br>+<br>+    // Float.<br>+    case ConversionSpecifier::aArg:<br>+    case ConversionSpecifier::AArg:<br>+    case ConversionSpecifier::eArg:<br>+    case ConversionSpecifier::EArg:<br>+    case ConversionSpecifier::fArg:<br>+    case ConversionSpecifier::FArg:<br>+    case ConversionSpecifier::gArg:<br>+    case ConversionSpecifier::GArg:<br>+      switch (LM.getKind()) {<br>+        case LengthModifier::None: return ArgTypeResult(Ctx.FloatTy);<br>+        case LengthModifier::AsLong: return ArgTypeResult(Ctx.DoubleTy);<br>+        case LengthModifier::AsLongDouble:<br>+          return ArgTypeResult(Ctx.LongDoubleTy);<br>+        default:<br>+          return ScanfArgTypeResult::Invalid();<br>+      }<br>+<br>+    // Char, string and scanlist.<br>+    case ConversionSpecifier::cArg:<br>+    case ConversionSpecifier::sArg:<br>+    case ConversionSpecifier::ScanListArg:<br>+      switch (LM.getKind()) {<br>+        case LengthModifier::None: return ScanfArgTypeResult::CStrTy;<br>+        case LengthModifier::AsLong:<br>+          return ScanfArgTypeResult(ScanfArgTypeResult::WCStrTy, "wchar_t *");<br>+        default:<br>+          return ScanfArgTypeResult::Invalid();<br>+      }<br>+    case ConversionSpecifier::CArg:<br>+    case ConversionSpecifier::SArg:<br>+      // FIXME: Mac OS X specific?<br>+      return ScanfArgTypeResult(ScanfArgTypeResult::WCStrTy, "wchar_t *");<br>+<br>+    // Pointer.<br>+    case ConversionSpecifier::pArg:<br>+      return ScanfArgTypeResult(ArgTypeResult(ArgTypeResult::CPointerTy));<br>+<br>+    default:<br>+      break;<br>+  }<br>+<br>+  return ScanfArgTypeResult();<br>+}<br>+<br>+bool ScanfSpecifier::fixType(QualType QT, const LangOptions &LangOpt)<br>+{<br>+  if (!QT->isPointerType())<br>+    return false;<br>+<br>+  QualType PT = QT->getPointeeType();<br>+  const BuiltinType *BT = PT->getAs<BuiltinType>();<br>+  if (!BT)<br>+    return false;<br>+<br>+  // Pointer to a character.<br>+  if (PT->isAnyCharacterType()) {<br>+    CS.setKind(ConversionSpecifier::sArg);<br>+    if (PT->isWideCharType())<br>+      LM.setKind(LengthModifier::AsWideChar);<br>+    else<br>+      LM.setKind(LengthModifier::None);<br>+    return true;<br>+  }<br>+<br>+  // Figure out the length modifier.<br>+  switch (BT->getKind()) {<br>+    // no modifier<br>+    case BuiltinType::UInt:<br>+    case BuiltinType::Int:<br>+    case BuiltinType::Float:<br>+      LM.setKind(LengthModifier::None);<br>+      break;<br>+<br>+    // hh<br>+    case BuiltinType::Char_U:<br>+    case BuiltinType::UChar:<br>+    case BuiltinType::Char_S:<br>+    case BuiltinType::SChar:<br>+      LM.setKind(LengthModifier::AsChar);<br>+      break;<br>+<br>+    // h<br>+    case BuiltinType::Short:<br>+    case BuiltinType::UShort:<br>+      LM.setKind(LengthModifier::AsShort);<br>+      break;<br>+<br>+    // l<br>+    case BuiltinType::Long:<br>+    case BuiltinType::ULong:<br>+    case BuiltinType::Double:<br>+      LM.setKind(LengthModifier::AsLong);<br>+      break;<br>+<br>+    // ll<br>+    case BuiltinType::LongLong:<br>+    case BuiltinType::ULongLong:<br>+      LM.setKind(LengthModifier::AsLongLong);<br>+      break;<br>+<br>+    // L<br>+    case BuiltinType::LongDouble:<br>+      LM.setKind(LengthModifier::AsLongDouble);<br>+      break;<br>+<br>+    // Don't know.<br>+    default:<br>+      return false;<br>+  }<br>+<br>+  // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.<br>+  if (isa<TypedefType>(PT) && (LangOpt.C99 || LangOpt.CPlusPlus0x)) {<br>+    const IdentifierInfo *Identifier = QT.getBaseTypeIdentifier();<br>+    if (Identifier->getName() == "size_t") {<br>+      LM.setKind(LengthModifier::AsSizeT);<br>+    } else if (Identifier->getName() == "ssize_t") {<br>+      // Not C99, but common in Unix.<br>+      LM.setKind(LengthModifier::AsSizeT);<br>+    } else if (Identifier->getName() == "intmax_t") {<br>+      LM.setKind(LengthModifier::AsIntMax);<br>+    } else if (Identifier->getName() == "uintmax_t") {<br>+      LM.setKind(LengthModifier::AsIntMax);<br>+    } else if (Identifier->getName() == "ptrdiff_t") {<br>+      LM.setKind(LengthModifier::AsPtrDiff);<br>+    }<br>+  }<br>+<br>+  // Figure out the conversion specifier.<br>+  if (PT->isRealFloatingType())<br>+    CS.setKind(ConversionSpecifier::fArg);<br>+  else if (PT->isSignedIntegerType())<br>+    CS.setKind(ConversionSpecifier::dArg);<br>+  else if (PT->isUnsignedIntegerType()) {<br>+    // Preserve the original formatting, e.g. 'X', 'o'.<br>+    if (!CS.isUIntArg()) {<br>+      CS.setKind(ConversionSpecifier::uArg);<br>+    }<br>+  } else<br>+    llvm_unreachable("Unexpected type");<br>+<br>+  return true;<br>+}<br>+<br>+void ScanfSpecifier::toString(raw_ostream &os) const {<br>+  os << "%";<br>+<br>+  if (usesPositionalArg())<br>+    os << getPositionalArgIndex() << "$";<br>+  if (SuppressAssignment)<br>+    os << "*";<br>+<br>+  FieldWidth.toString(os);<br>+  os << LM.toString();<br>+  os << CS.toString();<br>+}<br>+<br> bool clang::analyze_format_string::ParseScanfString(FormatStringHandler &H,<br>                                                     const char *I,<br>                                                     const char *E) {<br>@@ -218,4 +426,47 @@<br>   return false;<br> }<br><br>+bool ScanfArgTypeResult::matchesType(ASTContext& C, QualType argTy) const {<br>+  switch (K) {<br>+    case InvalidTy:<br>+      llvm_unreachable("ArgTypeResult must be valid");<br>+    case UnknownTy:<br>+      return true;<br>+    case CStrTy:<br>+      return ArgTypeResult(ArgTypeResult::CStrTy).matchesType(C, argTy);<br>+    case WCStrTy:<br>+      return ArgTypeResult(ArgTypeResult::WCStrTy).matchesType(C, argTy);<br>+    case PtrToArgTypeResultTy: {<br>+      const PointerType *PT = argTy->getAs<PointerType>();<br>+      if (!PT)<br>+        return false;<br>+      return A.matchesType(C, PT->getPointeeType());<br>+    }<br>+  }<br><br>+  return false; // Unreachable, but we still get a warning.<br>+}<br>+<br>+QualType ScanfArgTypeResult::getRepresentativeType(ASTContext &C) const {<br>+  switch (K) {<br>+    case InvalidTy:<br>+      llvm_unreachable("No representative type for Invalid ArgTypeResult");<br>+    case UnknownTy:<br>+      return QualType();<br>+    case CStrTy:<br>+      return C.getPointerType(C.CharTy);<br>+    case WCStrTy:<br>+      return C.getPointerType(C.getWCharType());<br>+    case PtrToArgTypeResultTy:<br>+      return C.getPointerType(A.getRepresentativeType(C));<br>+  }<br>+<br>+  return QualType(); // Not reachable.<br>+}<br>+<br>+std::string ScanfArgTypeResult::getRepresentativeTypeName(ASTContext& C) const {<br>+  std::string S = getRepresentativeType(C).getAsString();<br>+  if (!Name)<br>+    return std::string("'") + S + "'";<br>+  return std::string("'") + Name + "' (aka '" + S + "')";<br>+}<br><br>Modified: cfe/trunk/lib/Sema/SemaChecking.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=146326&r1=146325&r2=146326&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=146326&r1=146325&r2=146326&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)<br>+++ cfe/trunk/lib/Sema/SemaChecking.cpp Sat Dec 10 07:20:11 2011<br>@@ -2371,8 +2371,38 @@<br>   if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex))<br>     return false;<br><br>-  // FIXME: Check that the argument type matches the format specifier.<br>-  <br>+  // Check that the argument type matches the format specifier.<br>+  const Expr *Ex = getDataArg(argIndex);<br>+  const analyze_scanf::ScanfArgTypeResult &ATR = FS.getArgType(S.Context);<br>+  if (ATR.isValid() && !ATR.matchesType(S.Context, Ex->getType())) {<br>+    ScanfSpecifier fixedFS = FS;<br>+    bool success = fixedFS.fixType(Ex->getType(), S.getLangOptions());<br>+<br>+    if (success) {<br>+      // Get the fix string from the fixed format specifier.<br>+      llvm::SmallString<128> buf;<br>+      llvm::raw_svector_ostream os(buf);<br>+      fixedFS.toString(os);<br>+<br>+      EmitFormatDiagnostic(<br>+        S.PDiag(diag::warn_printf_conversion_argument_type_mismatch)<br>+          << ATR.getRepresentativeTypeName(S.Context) << Ex->getType()<br>+          << Ex->getSourceRange(),<br>+        getLocationOfByte(CS.getStart()),<br>+        /*IsStringLocation*/true,<br>+        getSpecifierRange(startSpecifier, specifierLen),<br>+        FixItHint::CreateReplacement(<br>+          getSpecifierRange(startSpecifier, specifierLen),<br>+          os.str()));<br>+    } else {<br>+      S.Diag(getLocationOfByte(CS.getStart()),<br>+             diag::warn_printf_conversion_argument_type_mismatch)<br>+          << ATR.getRepresentativeTypeName(S.Context) << Ex->getType()<br>+          << getSpecifierRange(startSpecifier, specifierLen)<br>+          << Ex->getSourceRange();<br>+    }<br>+  }<br>+<br>   return true;<br> }<br><br><br>Modified: cfe/trunk/test/Analysis/taint-generic.c<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/taint-generic.c?rev=146326&r1=146325&r2=146326&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/taint-generic.c?rev=146326&r1=146325&r2=146326&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/Analysis/taint-generic.c (original)<br>+++ cfe/trunk/test/Analysis/taint-generic.c Sat Dec 10 07:20:11 2011<br>@@ -39,7 +39,8 @@<br><br> void scanfArg() {<br>   int t;<br>-  scanf("%d", t); // expected-warning {{Pointer argument is expected}}<br>+  scanf("%d", t); // expected-warning {{Pointer argument is expected}} \<br>+                  // expected-warning {{conversion specifies type 'int *' but the argument has type 'int'}}<br> }<br><br> void bufferGetchar(int x) {<br><br>Modified: cfe/trunk/test/Analysis/taint-tester.c<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/taint-tester.c?rev=146326&r1=146325&r2=146326&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/taint-tester.c?rev=146326&r1=146325&r2=146326&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/Analysis/taint-tester.c (original)<br>+++ cfe/trunk/test/Analysis/taint-tester.c Sat Dec 10 07:20:11 2011<br>@@ -49,8 +49,8 @@<br><br>   // Taint on fields of a struct.<br>   struct XYStruct xy = {2, 3, 11};<br>-  scanf("%f", &xy.y);<br>-  scanf("%f", &xy.x);<br>+  scanf("%d", &xy.y);<br>+  scanf("%d", &xy.x);<br>   int tx = xy.x; // expected-warning {{tainted}}<br>   int ty = xy.y; // FIXME: This should be tainted as well.<br>   char ntz = xy.z;// no warning<br><br>Modified: cfe/trunk/test/Sema/format-strings-fixit.c<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/format-strings-fixit.c?rev=146326&r1=146325&r2=146326&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/format-strings-fixit.c?rev=146326&r1=146325&r2=146326&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/Sema/format-strings-fixit.c (original)<br>+++ cfe/trunk/test/Sema/format-strings-fixit.c Sat Dec 10 07:20:11 2011<br>@@ -10,6 +10,11 @@<br><br> int printf(char const *, ...);<br><br>+typedef __SIZE_TYPE__ size_t;<br>+typedef __INTMAX_TYPE__ intmax_t;<br>+typedef __UINTMAX_TYPE__ uintmax_t;<br>+typedef __PTRDIFF_TYPE__ ptrdiff_t;<br>+<br> void test() {<br>   // Basic types<br>   printf("%s", (int) 123);<br>@@ -47,11 +52,6 @@<br>   unsigned long val = 42;<br>   printf("%X", val);<br><br>-  typedef __SIZE_TYPE__ size_t;<br>-  typedef __INTMAX_TYPE__ intmax_t;<br>-  typedef __UINTMAX_TYPE__ uintmax_t;<br>-  typedef __PTRDIFF_TYPE__ ptrdiff_t;<br>-<br>   // size_t, etc.<br>   printf("%f", (size_t) 42);<br>   printf("%f", (intmax_t) 42);<br>@@ -62,6 +62,51 @@<br>   printf("%ld", "foo");<br> }<br><br>+int scanf(char const *, ...);<br>+<br>+void test2() {<br>+  char str[100];<br>+  short shortVar;<br>+  unsigned short uShortVar;<br>+  int intVar;<br>+  unsigned uIntVar;<br>+  float floatVar;<br>+  double doubleVar;<br>+  long double longDoubleVar;<br>+  long longVar;<br>+  unsigned long uLongVar;<br>+  long long longLongVar;<br>+  unsigned long long uLongLongVar;<br>+  size_t sizeVar;<br>+  intmax_t intmaxVar;<br>+  uintmax_t uIntmaxVar;<br>+  ptrdiff_t ptrdiffVar;<br>+<br>+  scanf("%lf", str);<br>+  scanf("%f", &shortVar);<br>+  scanf("%f", &uShortVar);<br>+  scanf("%p", &intVar);<br>+  scanf("%Lf", &uIntVar);<br>+  scanf("%ld", &floatVar);<br>+  scanf("%f", &doubleVar);<br>+  scanf("%d", &longDoubleVar);<br>+  scanf("%f", &longVar);<br>+  scanf("%f", &uLongVar);<br>+  scanf("%f", &longLongVar);<br>+  scanf("%f", &uLongLongVar);<br>+<br>+  // Some named ints.<br>+  scanf("%f", &sizeVar);<br>+  scanf("%f", &intmaxVar);<br>+  scanf("%f", &uIntmaxVar);<br>+  scanf("%f", &ptrdiffVar);<br>+<br>+  // Perserve the original formatting for unsigned integers.<br>+  scanf("%o", &uLongVar);<br>+  scanf("%x", &uLongVar);<br>+  scanf("%X", &uLongVar);<br>+}<br>+<br> // Validate the fixes...<br> // CHECK: printf("%d", (int) 123);<br> // CHECK: printf("abc%s", "testing testing 123");<br>@@ -87,3 +132,23 @@<br> // CHECK: printf("%ju", (uintmax_t) 42);<br> // CHECK: printf("%td", (ptrdiff_t) 42);<br> // CHECK: printf("%s", "foo");<br>+<br>+// CHECK: scanf("%s", str);<br>+// CHECK: scanf("%hd", &shortVar);<br>+// CHECK: scanf("%hu", &uShortVar);<br>+// CHECK: scanf("%d", &intVar);<br>+// CHECK: scanf("%u", &uIntVar);<br>+// CHECK: scanf("%f", &floatVar);<br>+// CHECK: scanf("%lf", &doubleVar);<br>+// CHECK: scanf("%Lf", &longDoubleVar);<br>+// CHECK: scanf("%ld", &longVar);<br>+// CHECK: scanf("%lu", &uLongVar);<br>+// CHECK: scanf("%lld", &longLongVar);<br>+// CHECK: scanf("%llu", &uLongLongVar);<br>+// CHECK: scanf("%zu", &sizeVar);<br>+// CHECK: scanf("%jd", &intmaxVar);<br>+// CHECK: scanf("%ju", &uIntmaxVar);<br>+// CHECK: scanf("%td", &ptrdiffVar);<br>+// CHECK: scanf("%lo", &uLongVar);<br>+// CHECK: scanf("%lx", &uLongVar);<br>+// CHECK: scanf("%lX", &uLongVar);<br><br>Modified: cfe/trunk/test/Sema/format-strings-int-typedefs.c<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/format-strings-int-typedefs.c?rev=146326&r1=146325&r2=146326&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/format-strings-int-typedefs.c?rev=146326&r1=146325&r2=146326&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/Sema/format-strings-int-typedefs.c (original)<br>+++ cfe/trunk/test/Sema/format-strings-int-typedefs.c Sat Dec 10 07:20:11 2011<br>@@ -1,6 +1,7 @@<br> // RUN: %clang_cc1 -triple i386-apple-darwin9 -fsyntax-only -verify %s<br><br> int printf(char const *, ...);<br>+int scanf(char const *, ...);<br><br> void test(void) {<br>   printf("%jd", 42.0); // expected-warning {{conversion specifies type 'intmax_t' (aka 'long long')}}<br>@@ -12,6 +13,15 @@<br>   printf("%S", 42.0);  // expected-warning {{conversion specifies type 'wchar_t *' (aka 'int *')}}<br>   printf("%C", 42.0);  // expected-warning {{conversion specifies type 'wchar_t' (aka 'int')}}<br><br>+  scanf("%jd", 0); // expected-warning {{conversion specifies type 'intmax_t *' (aka 'long long *')}}<br>+  scanf("%ju", 0); // expected-warning {{conversion specifies type 'uintmax_t *' (aka 'unsigned long long *')}}<br>+  scanf("%zu", 0); // expected-warning {{conversion specifies type 'size_t *' (aka 'unsigned long *')}}<br>+  scanf("%td", 0); // expected-warning {{conversion specifies type 'ptrdiff_t *' (aka 'int *')}}<br>+  scanf("%lc", 0); // expected-warning {{conversion specifies type 'wchar_t *' (aka 'int *')}}<br>+  scanf("%ls", 0); // expected-warning {{conversion specifies type 'wchar_t *' (aka 'int *')}}<br>+  scanf("%S",  0);  // expected-warning {{conversion specifies type 'wchar_t *' (aka 'int *')}}<br>+  scanf("%C",  0);  // expected-warning {{conversion specifies type 'wchar_t *' (aka 'int *')}}<br>+<br><br>   // typedef size_t et al. to something crazy.<br>   typedef void *size_t;<br><br>Modified: cfe/trunk/test/Sema/format-strings-scanf.c<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/format-strings-scanf.c?rev=146326&r1=146325&r2=146326&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/format-strings-scanf.c?rev=146326&r1=146325&r2=146326&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/Sema/format-strings-scanf.c (original)<br>+++ cfe/trunk/test/Sema/format-strings-scanf.c Sat Dec 10 07:20:11 2011<br>@@ -28,7 +28,7 @@<br><br> void bad_length_modifiers(char *s, void *p, wchar_t *ws, long double *ld) {<br>   scanf("%hhs", "foo"); // expected-warning{{length modifier 'hh' results in undefined behavior or no effect with 's' conversion specifier}}<br>-  scanf("%1$zp", p); // expected-warning{{length modifier 'z' results in undefined behavior or no effect with 'p' conversion specifier}}<br>+  scanf("%1$zp", &p); // expected-warning{{length modifier 'z' results in undefined behavior or no effect with 'p' conversion specifier}}<br>   scanf("%ls", ws); // no-warning<br>   scanf("%#.2Lf", ld); // expected-warning{{invalid conversion specifier '#'}}<br> }<br>@@ -37,10 +37,11 @@<br> // format string is somewhere else, point to it in a note.<br> void pr9751() {<br>   int *i;<br>+  char str[100];<br>   const char kFormat1[] = "%00d"; // expected-note{{format string is defined here}}}<br>   scanf(kFormat1, i); // expected-warning{{zero field width in scanf format string is unused}}<br>   scanf("%00d", i); // expected-warning{{zero field width in scanf format string is unused}}<br>   const char kFormat2[] = "%["; // expected-note{{format string is defined here}}}<br>-  scanf(kFormat2, &i); // expected-warning{{no closing ']' for '%[' in scanf format string}}<br>-  scanf("%[", &i); // expected-warning{{no closing ']' for '%[' in scanf format string}}<br>+  scanf(kFormat2, str); // expected-warning{{no closing ']' for '%[' in scanf format string}}<br>+  scanf("%[", str); // expected-warning{{no closing ']' for '%[' in scanf format string}}<br> }<br><br><br>_______________________________________________<br>cfe-commits mailing list<br><a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits<br></div></blockquote></div><br></div></body></html>