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