diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9399,15 +9399,15 @@ "the pointer decremented by %0 refers before the beginning of the array">, InGroup, DefaultIgnore; def warn_ptr_arith_exceeds_bounds : Warning< - "the pointer incremented by %0 refers past the end of the array (that " - "contains %1 element%s2)">, + "the pointer incremented by %0 refers %1 byte%s2 past the end of the array " + "(that has type %3)">, InGroup, DefaultIgnore; def warn_array_index_precedes_bounds : Warning< "array index %0 is before the beginning of the array">, InGroup; def warn_array_index_exceeds_bounds : Warning< - "array index %0 is past the end of the array (which contains %1 " - "element%s2)">, InGroup; + "array index %0 is %1 byte%s2 past the end of the array (that has type %3)">, + InGroup; def warn_ptr_arith_exceeds_max_addressable_bounds : Warning< "the pointer incremented by %0 refers past the last possible element for an array in %1-bit " "address space containing %2-bit (%3-byte) elements (max possible %4 element%s5)">, diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -16070,10 +16070,16 @@ unsigned DiagID = ASE ? diag::warn_array_index_exceeds_bounds : diag::warn_ptr_arith_exceeds_bounds; + CharUnits ArrayTySize = Context.getTypeSizeInChars(ArrayTy); + CharUnits EffectiveTySize = Context.getTypeSizeInChars(EffectiveType); + llvm::APInt ArrayOverrun = index * EffectiveTySize.getQuantity() - + ArrayTySize.getQuantity(); + DiagRuntimeBehavior(BaseExpr->getBeginLoc(), BaseExpr, PDiag(DiagID) << toString(index, 10, true) - << toString(size, 10, true) - << (unsigned)size.getLimitedValue(~0U) + << toString(ArrayOverrun, 10, true) + << ArrayOverrun.getZExtValue() + << ArrayTy->desugar() << IndexExpr->getSourceRange()); } else { unsigned DiagID = diag::warn_array_index_precedes_bounds; diff --git a/clang/test/Sema/array-bounds-ptr-arith.c b/clang/test/Sema/array-bounds-ptr-arith.c --- a/clang/test/Sema/array-bounds-ptr-arith.c +++ b/clang/test/Sema/array-bounds-ptr-arith.c @@ -11,7 +11,7 @@ return (void *)es->s_uuid + sizeof(int); // no-warning } void* broken (struct ext2_super_block *es,int a) { - return (void *)es->s_uuid + 9; // expected-warning {{the pointer incremented by 9 refers past the end of the array}} + return (void *)es->s_uuid + 9; // expected-warning {{the pointer incremented by 9 refers -8 bytes past the end of the array (that has type 'unsigned char[8]')}} } // Test case reduced from PR11594 @@ -40,7 +40,7 @@ void radar11387038(void) { RDar11387038_B *pRDar11387038_B; - struct RDar11387038 *y = &(*pRDar11387038_B->x)->z[4]; // strict-warning {{array index 4 is past the end of the array (which contains 1 element)}} + struct RDar11387038 *y = &(*pRDar11387038_B->x)->z[4]; // strict-warning {{array index 4 is 0 bytes past the end of the array (that has type 'struct RDar11387038[1]')}} } void pr51682(void) { diff --git a/clang/test/Sema/integer-overflow.c b/clang/test/Sema/integer-overflow.c --- a/clang/test/Sema/integer-overflow.c +++ b/clang/test/Sema/integer-overflow.c @@ -142,7 +142,7 @@ (__imag__ x) = 4608 * 1024 * 1024; // expected-warning@+4 {{overflow in expression; result is 536870912 with type 'int'}} -// expected-warning@+3 {{array index 536870912 is past the end of the array (which contains 10 elements)}} +// expected-warning@+3 {{array index 536870912 is 4294967216 bytes past the end of the array (that has type 'uint64_t[10]' (aka 'unsigned long long[10]'))}} // expected-note@+1 {{array 'a' declared here}} uint64_t a[10]; a[4608 * 1024 * 1024] = 1i; diff --git a/clang/test/SemaCXX/array-bounds-ptr-arith.cpp b/clang/test/SemaCXX/array-bounds-ptr-arith.cpp --- a/clang/test/SemaCXX/array-bounds-ptr-arith.cpp +++ b/clang/test/SemaCXX/array-bounds-ptr-arith.cpp @@ -6,13 +6,13 @@ const char *helloptr = hello; swallow("Hello world!" + 6); // no-warning - swallow("Hello world!" - 6); // expected-warning {{refers before the beginning of the array}} - swallow("Hello world!" + 14); // expected-warning {{refers past the end of the array}} + swallow("Hello world!" - 6); // expected-warning {{the pointer decremented by 6 refers before the beginning of the array}} + swallow("Hello world!" + 14); // expected-warning {{the pointer incremented by 14 refers 1 byte past the end of the array (that has type 'const char[13]')}} swallow("Hello world!" + 13); // no-warning swallow(hello + 6); // no-warning - swallow(hello - 6); // expected-warning {{refers before the beginning of the array}} - swallow(hello + 14); // expected-warning {{refers past the end of the array}} + swallow(hello - 6); // expected-warning {{the pointer decremented by 6 refers before the beginning of the array}} + swallow(hello + 14); // expected-warning {{the pointer incremented by 14 refers 1 byte past the end of the array (that has type 'const char[13]')}} swallow(hello + 13); // no-warning swallow(helloptr + 6); // no-warning @@ -22,12 +22,12 @@ double numbers[2]; // expected-note {{declared here}} swallow((char*)numbers + sizeof(double)); // no-warning - swallow((char*)numbers + 60); // expected-warning {{refers past the end of the array}} + swallow((char*)numbers + 60); // expected-warning {{the pointer incremented by 60 refers 44 bytes past the end of the array (that has type 'double[2]')}} char buffer[5]; // expected-note 2 {{declared here}} // TODO: Add FixIt notes for adding parens around non-ptr part of arith expr - swallow(buffer + sizeof("Hello")-1); // expected-warning {{refers past the end of the array}} + swallow(buffer + sizeof("Hello")-1); // expected-warning {{the pointer incremented by 6 refers 1 byte past the end of the array (that has type 'char[5]')}} swallow(buffer + (sizeof("Hello")-1)); // no-warning - if (n > 0 && n <= 6) swallow(buffer + 6 - n); // expected-warning {{refers past the end of the array}} + if (n > 0 && n <= 6) swallow(buffer + 6 - n); // expected-warning {{the pointer incremented by 6 refers 1 byte past the end of the array (that has type 'char[5]')}} if (n > 0 && n <= 6) swallow(buffer + (6 - n)); // no-warning } diff --git a/clang/test/SemaCXX/array-bounds-strict-flex-arrays.cpp b/clang/test/SemaCXX/array-bounds-strict-flex-arrays.cpp --- a/clang/test/SemaCXX/array-bounds-strict-flex-arrays.cpp +++ b/clang/test/SemaCXX/array-bounds-strict-flex-arrays.cpp @@ -16,7 +16,7 @@ int a[10]; // relaxed-note {{array 'a' declared here}} }; void test0(t0 *s2) { - s2->a[12] = 0; // relaxed-warning {{array index 12 is past the end of the array (which contains 10 elements)}} + s2->a[12] = 0; // relaxed-warning {{array index 12 is 8 bytes past the end of the array (that has type 'int[10]')}} } @@ -26,7 +26,7 @@ int a[1]; // strict-note {{array 'a' declared here}} }; void test1(t1 *s2) { - s2->a[2] = 0; // strict-warning {{array index 2 is past the end of the array (which contains 1 element)}} + s2->a[2] = 0; // strict-warning {{array index 2 is 4 bytes past the end of the array (that has type 'int[1]')}} } // Under -fstrict-flex-arrays={1,2} `a` is a flexible array. diff --git a/clang/test/SemaCXX/array-bounds.cpp b/clang/test/SemaCXX/array-bounds.cpp --- a/clang/test/SemaCXX/array-bounds.cpp +++ b/clang/test/SemaCXX/array-bounds.cpp @@ -8,16 +8,16 @@ int v[1][1][1]; // expected-note {{array 'v' declared here}} int *p = &y[2]; // no-warning (void) sizeof(x[2]); // no-warning - y[2] = 2; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} - z[1] = 'x'; // expected-warning {{array index 1 is past the end of the array (which contains 1 element)}} - w[0][2] = 0; // expected-warning {{array index 2 is past the end of the array (which contains 1 element)}} - v[0][0][2] = 0; // expected-warning {{array index 2 is past the end of the array (which contains 1 element)}} - return x[2] + // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} + y[2] = 2; // expected-warning {{array index 2 is 0 bytes past the end of the array (that has type 'int[2]')}} + z[1] = 'x'; // expected-warning {{array index 1 is 0 bytes past the end of the array (that has type 'int[1]')}} + w[0][2] = 0; // expected-warning {{array index 2 is 4 bytes past the end of the array (that has type 'int[1]')}} + v[0][0][2] = 0; // expected-warning {{array index 2 is 4 bytes past the end of the array (that has type 'int[1]')}} + return x[2] + // expected-warning {{array index 2 is 0 bytes past the end of the array (that has type 'int[2]')}} y[-1] + // expected-warning {{array index -1 is before the beginning of the array}} - x[sizeof(x)] + // expected-warning {{array index 8 is past the end of the array (which contains 2 elements)}} - x[sizeof(x) / sizeof(x[0])] + // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} + x[sizeof(x)] + // expected-warning {{array index 8 is 24 bytes past the end of the array (that has type 'int[2]')}} + x[sizeof(x) / sizeof(x[0])] + // expected-warning {{array index 2 is 0 bytes past the end of the array (that has type 'int[2]')}} x[sizeof(x) / sizeof(x[0]) - 1] + // no-warning - x[sizeof(x[2])]; // expected-warning {{array index 4 is past the end of the array (which contains 2 elements)}} + x[sizeof(x[2])]; // expected-warning {{array index 4 is 8 bytes past the end of the array (that has type 'int[2]')}} } // This code example tests that -Warray-bounds works with arrays that @@ -31,7 +31,7 @@ } void f2(const int (&a)[2]) { // expected-note {{declared here}} - int val = a[3]; // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}} + int val = a[3]; // expected-warning {{array index 3 is 4 bytes past the end of the array (that has type 'const int[2]')}} } void test() { @@ -44,33 +44,33 @@ short a[2]; // expected-note 4 {{declared here}} char c[4]; } u; - u.a[3] = 1; // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}} + u.a[3] = 1; // expected-warning {{array index 3 is 2 bytes past the end of the array (that has type 'short[2]')}} u.c[3] = 1; // no warning short *p = &u.a[2]; // no warning - p = &u.a[3]; // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}} - *(&u.a[2]) = 1; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} - *(&u.a[3]) = 1; // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}} + p = &u.a[3]; // expected-warning {{array index 3 is 2 bytes past the end of the array (that has type 'short[2]')}} + *(&u.a[2]) = 1; // expected-warning {{array index 2 is 0 bytes past the end of the array (that has type 'short[2]')}} + *(&u.a[3]) = 1; // expected-warning {{array index 3 is 2 bytes past the end of the array (that has type 'short[2]')}} *(&u.c[3]) = 1; // no warning const int const_subscript = 3; int array[2]; // expected-note {{declared here}} - array[const_subscript] = 0; // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}} + array[const_subscript] = 0; // expected-warning {{array index 3 is 4 bytes past the end of the array (that has type 'int[2]')}} int *ptr; ptr[3] = 0; // no warning for pointer references int array2[] = { 0, 1, 2 }; // expected-note 2 {{declared here}} - array2[3] = 0; // expected-warning {{array index 3 is past the end of the array (which contains 3 elements)}} - array2[2+2] = 0; // expected-warning {{array index 4 is past the end of the array (which contains 3 elements)}} + array2[3] = 0; // expected-warning {{array index 3 is 0 bytes past the end of the array (that has type 'int[3]')}} + array2[2+2] = 0; // expected-warning {{array index 4 is 4 bytes past the end of the array (that has type 'int[3]')}} const char *str1 = "foo"; char c1 = str1[5]; // no warning for pointers const char str2[] = "foo"; // expected-note {{declared here}} - char c2 = str2[5]; // expected-warning {{array index 5 is past the end of the array (which contains 4 elements)}} + char c2 = str2[5]; // expected-warning {{array index 5 is 1 byte past the end of the array (that has type 'const char[4]')}} int (*array_ptr)[2]; - (*array_ptr)[3] = 1; // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}} + (*array_ptr)[3] = 1; // expected-warning {{array index 3 is 4 bytes past the end of the array (that has type 'int[2]')}} } template struct S { @@ -78,8 +78,8 @@ }; template void f() { S<3> s; - s.arr[4] = 0; // expected-warning 2 {{array index 4 is past the end of the array (which contains 3 elements)}} - s.arr[I] = 0; // expected-warning {{array index 5 is past the end of the array (which contains 3 elements)}} + s.arr[4] = 0; // expected-warning 2 {{array index 4 is 1 byte past the end of the array (that has type 'char[3]')}} + s.arr[I] = 0; // expected-warning {{array index 5 is 2 bytes past the end of the array (that has type 'char[3]')}} } void test_templates() { @@ -92,13 +92,13 @@ int test_no_warn_macro_unreachable() { int arr[SIZE]; // expected-note {{array 'arr' declared here}} return ARR_IN_MACRO(0, arr, SIZE) + // no-warning - ARR_IN_MACRO(1, arr, SIZE); // expected-warning{{array index 10 is past the end of the array (which contains 10 elements)}} + ARR_IN_MACRO(1, arr, SIZE); // expected-warning{{array index 10 is 0 bytes past the end of the array (that has type 'int[10]')}} } // This exhibited an assertion failure for a 32-bit build of Clang. int test_pr9240() { short array[100]; // expected-note {{array 'array' declared here}} - return array[(unsigned long long) 100]; // expected-warning {{array index 100 is past the end of the array (which contains 100 elements)}} + return array[(unsigned long long) 100]; // expected-warning {{array index 100 is 0 bytes past the end of the array (that has type 'short[100]')}} } // PR 9284 - a template parameter can cause an array bounds access to be @@ -116,7 +116,7 @@ int arr[3 + (extendArray ? 1 : 0)]; // expected-note {{array 'arr' declared here}} if (!extendArray) - arr[3] = 42; // expected-warning{{array index 3 is past the end of the array (which contains 3 elements)}} + arr[3] = 42; // expected-warning{{array index 3 is 0 bytes past the end of the array (that has type 'int[3]')}} } void test_pr9284() { @@ -135,7 +135,7 @@ int arr[2] = { 0, 0 }; // expected-note {{array 'arr' declared here}} if (flag) return sizeof(char) != sizeof(char) ? arr[2] : arr[1]; - return sizeof(char) == sizeof(char) ? arr[2] : arr[1]; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} + return sizeof(char) == sizeof(char) ? arr[2] : arr[1]; // expected-warning {{array index 2 is 0 bytes past the end of the array (that has type 'int[2]')}} } void test_switch() { @@ -147,7 +147,7 @@ } case 4: { int arr[2]; // expected-note {{array 'arr' declared here}} - arr[2] = 1; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} + arr[2] = 1; // expected-warning {{array index 2 is 0 bytes past the end of the array (that has type 'int[2]')}} break; } default: { @@ -199,9 +199,9 @@ }; char bar(struct foo *F, baz *B) { - return F->c1[3] + // expected-warning {{array index 3 is past the end of the array (which contains 1 element)}} + return F->c1[3] + // expected-warning {{array index 3 is 2 bytes past the end of the array (that has type 'char[1]')}} F->c2[3] + // no warning, foo could have tail padding allocated. - B->c1[3] + // expected-warning {{array index 3 is past the end of the array (which contains 1 element)}} + B->c1[3] + // expected-warning {{array index 3 is 2 bytes past the end of the array (that has type 'char[1]')}} B->c2[3]; // no warning, baz could have tail padding allocated. } } @@ -215,20 +215,20 @@ template struct bar { char c[N]; }; // expected-note {{declared here}} char test(foo *F, bar<1> *B) { - return F->c[3] + // expected-warning {{array index 3 is past the end of the array (which contains 1 element)}} - B->c[3]; // expected-warning {{array index 3 is past the end of the array (which contains 1 element)}} + return F->c[3] + // expected-warning {{array index 3 is 2 bytes past the end of the array (that has type 'char[1]')}} + B->c[3]; // expected-warning {{array index 3 is 2 bytes past the end of the array (that has type 'char[1]')}} } } void bar(int x) {} int test_more() { int foo[5]; // expected-note 5 {{array 'foo' declared here}} - bar(foo[5]); // expected-warning {{array index 5 is past the end of the array (which contains 5 elements)}} - ++foo[5]; // expected-warning {{array index 5 is past the end of the array (which contains 5 elements)}} - if (foo[6]) // expected-warning {{array index 6 is past the end of the array (which contains 5 elements)}} - return --foo[6]; // expected-warning {{array index 6 is past the end of the array (which contains 5 elements)}} + bar(foo[5]); // expected-warning {{array index 5 is 0 bytes past the end of the array (that has type 'int[5]')}} + ++foo[5]; // expected-warning {{array index 5 is 0 bytes past the end of the array (that has type 'int[5]')}} + if (foo[6]) // expected-warning {{array index 6 is 4 bytes past the end of the array (that has type 'int[5]')}} + return --foo[6]; // expected-warning {{array index 6 is 4 bytes past the end of the array (that has type 'int[5]')}} else - return foo[5]; // expected-warning {{array index 5 is past the end of the array (which contains 5 elements)}} + return foo[5]; // expected-warning {{array index 5 is 0 bytes past the end of the array (that has type 'int[5]')}} } void test_pr10771() { @@ -237,7 +237,7 @@ ((char*)foo)[sizeof(foo) - 1] = '\0'; // no-warning *(((char*)foo) + sizeof(foo) - 1) = '\0'; // no-warning - ((char*)foo)[sizeof(foo)] = '\0'; // expected-warning {{array index 32768 is past the end of the array (which contains 32768 elements)}} + ((char*)foo)[sizeof(foo)] = '\0'; // expected-warning {{array index 32768 is 0 bytes past the end of the array (that has type 'double[4096]')}} // TODO: This should probably warn, too. *(((char*)foo) + sizeof(foo)) = '\0'; // no-warning @@ -248,13 +248,13 @@ // Test checking with varargs. void test_pr11007() { double a[5]; // expected-note {{array 'a' declared here}} - test_pr11007_aux("foo", a[1000]); // expected-warning {{array index 1000 is past the end of the array}} + test_pr11007_aux("foo", a[1000]); // expected-warning {{array index 1000 is 7960 bytes past the end of the array (that has type 'double[5]')}} } void test_rdar10916006(void) { int a[128]; // expected-note {{array 'a' declared here}} - a[(unsigned char)'\xA1'] = 1; // expected-warning {{array index 161 is past the end of the array}} + a[(unsigned char)'\xA1'] = 1; // expected-warning {{array index 161 is 132 bytes past the end of the array (that has type 'int[128]')}} } struct P { @@ -264,20 +264,20 @@ void test_struct_array_index() { struct P p[10]; // expected-note {{array 'p' declared here}} - p[11] = {0, 1}; // expected-warning {{array index 11 is past the end of the array (which contains 10 elements)}} + p[11] = {0, 1}; // expected-warning {{array index 11 is 8 bytes past the end of the array (that has type 'struct P[10]')}} } int operator+(const struct P &s1, const struct P &s2); int test_operator_overload_struct_array_index() { struct P x[10] = {0}; // expected-note {{array 'x' declared here}} - return x[1] + x[11]; // expected-warning {{array index 11 is past the end of the array (which contains 10 elements)}} + return x[1] + x[11]; // expected-warning {{array index 11 is 8 bytes past the end of the array (that has type 'struct P[10]')}} } int multi[2][2][2]; // expected-note 3 {{array 'multi' declared here}} int test_multiarray() { - return multi[2][0][0] + // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} - multi[0][2][0] + // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} - multi[0][0][2]; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} + return multi[2][0][0] + // expected-warning {{array index 2 is 0 bytes past the end of the array (that has type 'int[2][2][2]')}} + multi[0][2][0] + // expected-warning {{array index 2 is 0 bytes past the end of the array (that has type 'int[2][2]')}} + multi[0][0][2]; // expected-warning {{array index 2 is 0 bytes past the end of the array (that has type 'int[2]')}} } struct multi_s { @@ -285,7 +285,7 @@ }; struct multi_s multi2[4]; // expected-note {{array 'multi2' declared here}} int test_struct_multiarray() { - return multi2[4].arr[0]; // expected-warning {{array index 4 is past the end of the array (which contains 4 elements)}} + return multi2[4].arr[0]; // expected-warning {{array index 4 is 0 bytes past the end of the array (that has type 'struct multi_s[4]')}} } namespace PR39746 { @@ -303,7 +303,7 @@ namespace PR41087 { template void foo() { Ty buffer[2]; // expected-note 3{{array 'buffer' declared here}} - ((char *)buffer)[2] = 'A'; // expected-warning 1{{array index 2 is past the end of the array (which contains 2 elements)}} + ((char *)buffer)[2] = 'A'; // expected-warning 1{{array index 2 is 0 bytes past the end of the array (that has type 'char[2]')}} ((char *)buffer)[-1] = 'A'; // expected-warning 2{{array index -1 is before the beginning of the array}} } @@ -319,7 +319,7 @@ void test() { arr[1] = 0; // ok - arr[2] = 0; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} - arr[1] = 0; // expected-warning {{array index 1 is past the end of the array (which contains 1 element)}} + arr[2] = 0; // expected-warning {{array index 2 is 0 bytes past the end of the array (that has type 'int[2]')}} + arr[1] = 0; // expected-warning {{array index 1 is 0 bytes past the end of the array (that has type 'int[1]')}} } } // namespace var_template_array diff --git a/clang/test/SemaCXX/integer-overflow.cpp b/clang/test/SemaCXX/integer-overflow.cpp --- a/clang/test/SemaCXX/integer-overflow.cpp +++ b/clang/test/SemaCXX/integer-overflow.cpp @@ -167,7 +167,7 @@ uint64_t a[10]; a[4608 * 1024 * 1024] = 1; #if __cplusplus < 201103L -// expected-warning@-2 {{array index 536870912 is past the end of the array (which contains 10 elements)}} +// expected-warning@-2 {{array index 536870912 is 4294967216 bytes past the end of the array (that has type 'uint64_t[10]' (aka 'unsigned long long[10]'))}} // expected-note@-4 {{array 'a' declared here}} #endif diff --git a/clang/test/SemaObjC/flexible-array-bounds.m b/clang/test/SemaObjC/flexible-array-bounds.m --- a/clang/test/SemaObjC/flexible-array-bounds.m +++ b/clang/test/SemaObjC/flexible-array-bounds.m @@ -23,5 +23,4 @@ char readit(Flexible *p) { return p->flexible[2]; } char readit0(Flexible0 *p) { return p->flexible[2]; } -char readit1(Flexible1 *p) { return p->flexible[2]; } // warn-warning {{array index 2 is past the end of the array (which contains 1 element)}} - +char readit1(Flexible1 *p) { return p->flexible[2]; } // warn-warning {{array index 2 is 1 byte past the end of the array (that has type 'char[1]')}}