<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">It is also possible that those tests need to be modified if Clang's behavior ends up being more desirable than what is reflected in those tests. I haven't looked at them, so I don't know off hand.<div><br><div><div>On Dec 12, 2011, at 11:01 AM, Peter Cooper wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div 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><a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br></div></blockquote></div><br></div></div>_______________________________________________<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></blockquote></div><br></div></body></html>