зеркало из https://github.com/microsoft/clang-1.git
-Wformat: better handling of qualifiers on pointer arguments
Warn about using pointers to const-qualified types as arguments to scanf. Ignore the volatile qualifier when checking if types match. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161052 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
6b4be2ef4c
Коммит
5deddafd3e
|
@ -262,6 +262,13 @@ bool ArgTypeResult::matchesType(ASTContext &C, QualType argTy) const {
|
|||
argTy = ETy->getDecl()->getIntegerType();
|
||||
argTy = C.getCanonicalType(argTy).getUnqualifiedType();
|
||||
|
||||
if (const PointerType *PTy = argTy->getAs<PointerType>()) {
|
||||
// Strip volatile qualifier from pointee type.
|
||||
QualType Pointee = PTy->getPointeeType();
|
||||
Pointee.removeLocalVolatile();
|
||||
argTy = C.getPointerType(Pointee);
|
||||
}
|
||||
|
||||
if (T == argTy)
|
||||
return true;
|
||||
// Check for "compatible types".
|
||||
|
|
|
@ -453,6 +453,15 @@ bool clang::analyze_format_string::ParseScanfString(FormatStringHandler &H,
|
|||
}
|
||||
|
||||
bool ScanfArgTypeResult::matchesType(ASTContext& C, QualType argTy) const {
|
||||
// It has to be a pointer type.
|
||||
const PointerType *PT = argTy->getAs<PointerType>();
|
||||
if (!PT)
|
||||
return false;
|
||||
|
||||
// We cannot write through a const qualified pointer.
|
||||
if (PT->getPointeeType().isConstQualified())
|
||||
return false;
|
||||
|
||||
switch (K) {
|
||||
case InvalidTy:
|
||||
llvm_unreachable("ArgTypeResult must be valid");
|
||||
|
@ -463,9 +472,6 @@ bool ScanfArgTypeResult::matchesType(ASTContext& C, QualType argTy) const {
|
|||
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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,3 +126,21 @@ void test_writeback(int *x) {
|
|||
scanf("%n", (void*)0); // expected-warning{{format specifies type 'int *' but the argument has type 'void *'}}
|
||||
scanf("%n %c", x, x); // expected-warning{{format specifies type 'char *' but the argument has type 'int *'}}
|
||||
}
|
||||
|
||||
void test_qualifiers(const int *cip, volatile int* vip,
|
||||
const char *ccp, volatile char* vcp,
|
||||
const volatile int *cvip) {
|
||||
scanf("%d", cip); // expected-warning{{format specifies type 'int *' but the argument has type 'const int *'}}
|
||||
scanf("%n", cip); // expected-warning{{format specifies type 'int *' but the argument has type 'const int *'}}
|
||||
scanf("%s", ccp); // expected-warning{{format specifies type 'char *' but the argument has type 'const char *'}}
|
||||
scanf("%d", cvip); // expected-warning{{format specifies type 'int *' but the argument has type 'const volatile int *'}}
|
||||
|
||||
scanf("%d", vip); // No warning.
|
||||
scanf("%n", vip); // No warning.
|
||||
scanf("%c", vcp); // No warning.
|
||||
|
||||
typedef int* ip_t;
|
||||
typedef const int* cip_t;
|
||||
scanf("%d", (ip_t)0); // No warning.
|
||||
scanf("%d", (cip_t)0); // expected-warning{{format specifies type 'int *' but the argument has type 'cip_t' (aka 'const int *')}}
|
||||
}
|
||||
|
|
|
@ -555,3 +555,19 @@ void test14_zed(int *p) {
|
|||
test14_foo("%", "%d", p); // expected-warning{{incomplete format specifier}}
|
||||
test14_bar("%", "%d", p); // expected-warning{{incomplete format specifier}}
|
||||
}
|
||||
|
||||
void test_qualifiers(volatile int *vip, const int *cip,
|
||||
const volatile int *cvip) {
|
||||
printf("%n", cip); // expected-warning{{format specifies type 'int *' but the argument has type 'const int *'}}
|
||||
printf("%n", cvip); // expected-warning{{format specifies type 'int *' but the argument has type 'const volatile int *'}}
|
||||
|
||||
printf("%n", vip); // No warning.
|
||||
printf("%p", cip); // No warning.
|
||||
printf("%p", cvip); // No warning.
|
||||
|
||||
|
||||
typedef int* ip_t;
|
||||
typedef const int* cip_t;
|
||||
printf("%n", (ip_t)0); // No warning.
|
||||
printf("%n", (cip_t)0); // expected-warning{{format specifies type 'int *' but the argument has type 'cip_t' (aka 'const int *')}}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче