
The checks for the 'z' and 't' format specifiers added in the original PR #143653 had some issues and were overly strict, causing some build failures and were consequently reverted at4c85bf2fe8
. In the latest commit27c58629ec
, I relaxed the checks for the 'z' and 't' format specifiers, so warnings are now only issued when they are used with mismatched types. The original intent of these checks was to diagnose code that assumes the underlying type of `size_t` is `unsigned` or `unsigned long`, for example: ```c printf("%zu", 1ul); // Not portable, but not an error when size_t is unsigned long ``` However, it produced a significant number of false positives. This was partly because Clang does not treat the `typedef` `size_t` and `__size_t` as having a common "sugar" type, and partly because a large amount of existing code either assumes `unsigned` (or `unsigned long`) is `size_t`, or they define the equivalent of size_t in their own way (such as sanitizer_internal_defs.h).2e67dcfdcd/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h (L203)
84 lines
2.7 KiB
C++
84 lines
2.7 KiB
C++
// Test without serialization:
|
|
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ast-dump %s \
|
|
// RUN: | FileCheck --strict-whitespace %s
|
|
//
|
|
// Test with serialization:
|
|
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-pch -o %t %s
|
|
// RUN: %clang_cc1 -x c++ -triple x86_64-unknown-unknown -include-pch %t -ast-dump-all /dev/null \
|
|
// RUN: | sed -e "s/ <undeserialized declarations>//" -e "s/ imported//" \
|
|
// RUN: | FileCheck --strict-whitespace %s
|
|
|
|
void testArrayInitExpr()
|
|
{
|
|
int a[10];
|
|
auto l = [a]{
|
|
};
|
|
// CHECK: |-ArrayInitLoopExpr 0x{{[^ ]*}} <col:15> 'int[10]'
|
|
// CHECK: | `-ArrayInitIndexExpr 0x{{[^ ]*}} <<invalid sloc>> '__size_t':'unsigned long'
|
|
}
|
|
|
|
template<typename T, int Size>
|
|
class array {
|
|
T data[Size];
|
|
|
|
using array_T_size = T[Size];
|
|
// CHECK: `-DependentSizedArrayType 0x{{[^ ]*}} 'T[Size]' dependent
|
|
using const_array_T_size = const T[Size];
|
|
// CHECK: `-DependentSizedArrayType 0x{{[^ ]*}} 'const T[Size]' dependent
|
|
};
|
|
|
|
struct V {};
|
|
template <typename U, typename Idx, int N>
|
|
void testDependentSubscript() {
|
|
U* a;
|
|
U b[5];
|
|
Idx i{};
|
|
enum E { One = 1 };
|
|
|
|
// Can types of subscript expressions can be determined?
|
|
// LHS is a type-dependent array, RHS is a known integer type.
|
|
a[1];
|
|
// CHECK: ArraySubscriptExpr {{.*}}line:[[@LINE-1]]{{.*}} 'U'
|
|
b[1];
|
|
// CHECK: ArraySubscriptExpr {{.*}}line:[[@LINE-1]]{{.*}} 'U'
|
|
|
|
// Reverse case: RHS is a type-dependent array, LHS is an integer.
|
|
1[a];
|
|
// CHECK: ArraySubscriptExpr {{.*}}line:[[@LINE-1]]{{.*}} 'U'
|
|
1[b];
|
|
// CHECK: ArraySubscriptExpr {{.*}}line:[[@LINE-1]]{{.*}} 'U'
|
|
|
|
// LHS is a type-dependent array, RHS is type-dependent.
|
|
a[i];
|
|
// CHECK: ArraySubscriptExpr {{.*}}line:[[@LINE-1]]{{.*}} '<dependent type>'
|
|
b[i];
|
|
// CHECK: ArraySubscriptExpr {{.*}}line:[[@LINE-1]]{{.*}} '<dependent type>'
|
|
|
|
V *a2;
|
|
V b2[5];
|
|
|
|
// LHS is a known array, RHS is type-dependent.
|
|
a2[i];
|
|
// CHECK: ArraySubscriptExpr {{.*}}line:[[@LINE-1]]{{.*}} '<dependent type>'
|
|
b2[i];
|
|
// CHECK: ArraySubscriptExpr {{.*}}line:[[@LINE-1]]{{.*}} '<dependent type>'
|
|
|
|
// LHS is a known array, RHS is a type-dependent index.
|
|
// We know the element type is V, but insist on some dependent type.
|
|
a2[One];
|
|
// CHECK: ArraySubscriptExpr {{.*}}line:[[@LINE-1]]{{.*}} '<dependent type>'
|
|
b2[One];
|
|
// CHECK: ArraySubscriptExpr {{.*}}line:[[@LINE-1]]{{.*}} '<dependent type>'
|
|
|
|
V b3[N];
|
|
// LHS is an array with dependent bounds but known elements.
|
|
// We insist on a dependent type.
|
|
b3[0];
|
|
// CHECK: ArraySubscriptExpr {{.*}}line:[[@LINE-1]]{{.*}} '<dependent type>'
|
|
|
|
U b4[N];
|
|
// LHS is an array with dependent bounds and dependent elements.
|
|
b4[0];
|
|
// CHECK: ArraySubscriptExpr {{.*}}line:[[@LINE-1]]{{.*}} 'U'
|
|
}
|