зеркало из https://github.com/microsoft/clang-1.git
Teach scanf/printf checking about '%Ld' and friends (a GNU extension). Fixes PR 9466.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148859 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
32d4abf2d1
Коммит
9d24c2cbd9
|
@ -548,6 +548,14 @@ bool FormatSpecifier::hasValidLengthModifier() const {
|
|||
case ConversionSpecifier::gArg:
|
||||
case ConversionSpecifier::GArg:
|
||||
return true;
|
||||
// GNU extension.
|
||||
case ConversionSpecifier::dArg:
|
||||
case ConversionSpecifier::iArg:
|
||||
case ConversionSpecifier::oArg:
|
||||
case ConversionSpecifier::uArg:
|
||||
case ConversionSpecifier::xArg:
|
||||
case ConversionSpecifier::XArg:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -259,7 +259,8 @@ ArgTypeResult PrintfSpecifier::getArgType(ASTContext &Ctx) const {
|
|||
if (CS.isIntArg())
|
||||
switch (LM.getKind()) {
|
||||
case LengthModifier::AsLongDouble:
|
||||
return ArgTypeResult::Invalid();
|
||||
// GNU extension.
|
||||
return Ctx.LongLongTy;
|
||||
case LengthModifier::None: return Ctx.IntTy;
|
||||
case LengthModifier::AsChar: return ArgTypeResult::AnyCharTy;
|
||||
case LengthModifier::AsShort: return Ctx.ShortTy;
|
||||
|
@ -280,7 +281,8 @@ ArgTypeResult PrintfSpecifier::getArgType(ASTContext &Ctx) const {
|
|||
if (CS.isUIntArg())
|
||||
switch (LM.getKind()) {
|
||||
case LengthModifier::AsLongDouble:
|
||||
return ArgTypeResult::Invalid();
|
||||
// GNU extension.
|
||||
return Ctx.UnsignedLongLongTy;
|
||||
case LengthModifier::None: return Ctx.UnsignedIntTy;
|
||||
case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
|
||||
case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
|
||||
|
|
|
@ -218,7 +218,9 @@ ScanfArgTypeResult ScanfSpecifier::getArgType(ASTContext &Ctx) const {
|
|||
return ScanfArgTypeResult();
|
||||
case LengthModifier::AsPtrDiff:
|
||||
return ScanfArgTypeResult(Ctx.getPointerDiffType(), "ptrdiff_t *");
|
||||
case LengthModifier::AsLongDouble: return ScanfArgTypeResult::Invalid();
|
||||
case LengthModifier::AsLongDouble:
|
||||
// GNU extension.
|
||||
return ArgTypeResult(Ctx.LongLongTy);
|
||||
case LengthModifier::AsAllocate: return ScanfArgTypeResult::Invalid();
|
||||
case LengthModifier::AsMAllocate: return ScanfArgTypeResult::Invalid();
|
||||
}
|
||||
|
@ -242,7 +244,9 @@ ScanfArgTypeResult ScanfSpecifier::getArgType(ASTContext &Ctx) const {
|
|||
case LengthModifier::AsPtrDiff:
|
||||
// FIXME: Unsigned version of ptrdiff_t?
|
||||
return ScanfArgTypeResult();
|
||||
case LengthModifier::AsLongDouble: return ScanfArgTypeResult::Invalid();
|
||||
case LengthModifier::AsLongDouble:
|
||||
// GNU extension.
|
||||
return ArgTypeResult(Ctx.UnsignedLongLongTy);
|
||||
case LengthModifier::AsAllocate: return ScanfArgTypeResult::Invalid();
|
||||
case LengthModifier::AsMAllocate: return ScanfArgTypeResult::Invalid();
|
||||
}
|
||||
|
|
|
@ -103,3 +103,13 @@ void test_alloc_extension(char **sp, wchar_t **lsp, float *fp) {
|
|||
scanf("%m[abc]", fp); // expected-warning{{format specifies type 'char **' but the argument has type 'float *'}}
|
||||
}
|
||||
|
||||
void test_longlong(long long *x, unsigned long long *y) {
|
||||
scanf("%Ld", y); // no-warning
|
||||
scanf("%Lu", y); // no-warning
|
||||
scanf("%Lx", y); // no-warning
|
||||
scanf("%Ld", x); // no-warning
|
||||
scanf("%Lu", x); // no-warning
|
||||
scanf("%Lx", x); // no-warning
|
||||
scanf("%Ls", "hello"); // expected-warning {{length modifier 'L' results in undefined behavior or no effect with 's' conversion specifier}}
|
||||
}
|
||||
|
||||
|
|
|
@ -469,3 +469,14 @@ void pr9751() {
|
|||
// when the original string is within the argument expression.
|
||||
printf(1 ? "yes %d" : "no %d"); // expected-warning 2{{more '%' conversions than data arguments}}
|
||||
}
|
||||
|
||||
// PR 9466: clang: doesn't know about %Lu, %Ld, and %Lx
|
||||
void printf_longlong(long long x, unsigned long long y) {
|
||||
printf("%Ld", y); // no-warning
|
||||
printf("%Lu", y); // no-warning
|
||||
printf("%Lx", y); // no-warning
|
||||
printf("%Ld", x); // no-warning
|
||||
printf("%Lu", x); // no-warning
|
||||
printf("%Lx", x); // no-warning
|
||||
printf("%Ls", "hello"); // expected-warning {{length modifier 'L' results in undefined behavior or no effect with 's' conversion specifier}}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче