ilya created this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
[Sema] Fix -Warray-bounds false negative when casting an out-of-bounds array item Fixes: http://llvm.org/PR44343 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D71714 Files: clang/lib/Sema/SemaChecking.cpp clang/test/SemaCXX/array-bounds.cpp Index: clang/test/SemaCXX/array-bounds.cpp =================================================================== --- clang/test/SemaCXX/array-bounds.cpp +++ clang/test/SemaCXX/array-bounds.cpp @@ -27,7 +27,7 @@ }; void f1(int a[1]) { - int val = a[3]; // no warning for function argumnet + int val = a[3]; // no warning for function argument } void f2(const int (&a)[2]) { // expected-note {{declared here}} @@ -133,7 +133,7 @@ int test_sizeof_as_condition(int flag) { int arr[2] = { 0, 0 }; // expected-note {{array 'arr' declared here}} - if (flag) + 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)}} } @@ -241,7 +241,7 @@ } int test_pr11007_aux(const char * restrict, ...); - + // Test checking with varargs. void test_pr11007() { double a[5]; // expected-note {{array 'a' declared here}} @@ -309,3 +309,23 @@ foo<int>(); // expected-note 1{{in instantiation of function template specialization}} }; } + +namespace PR44343 { + const unsigned int array[2] = {0, 1}; // expected-note 4{{array 'array' declared here}} + + const int i1 = (const int)array[2]; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} + const int i2 = static_cast<const int>(array[2]); // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} + const int &i3 = reinterpret_cast<const int&>(array[2]); // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} + unsigned int &i4 = const_cast<unsigned int&>(array[2]); // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} + + struct Base { + virtual ~Base(); + }; + + struct Derived : Base { + }; + + Base baseArr[2]; // expected-note {{array 'baseArr' declared here}} + Derived *d1 = dynamic_cast<Derived *>(&baseArr[2]); // no warning for one-past-end element's address retrieval + Derived &d2 = dynamic_cast<Derived &>(baseArr[2]); // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} +} Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ clang/lib/Sema/SemaChecking.cpp @@ -13421,6 +13421,15 @@ CheckArrayAccess(Arg); return; } + case Stmt::CStyleCastExprClass: + case Stmt::CXXStaticCastExprClass: + case Stmt::CXXDynamicCastExprClass: + case Stmt::CXXReinterpretCastExprClass: + case Stmt::CXXConstCastExprClass: { + const auto *ECE = cast<ExplicitCastExpr>(expr); + expr = ECE->getSubExpr(); + break; + } default: return; }
Index: clang/test/SemaCXX/array-bounds.cpp =================================================================== --- clang/test/SemaCXX/array-bounds.cpp +++ clang/test/SemaCXX/array-bounds.cpp @@ -27,7 +27,7 @@ }; void f1(int a[1]) { - int val = a[3]; // no warning for function argumnet + int val = a[3]; // no warning for function argument } void f2(const int (&a)[2]) { // expected-note {{declared here}} @@ -133,7 +133,7 @@ int test_sizeof_as_condition(int flag) { int arr[2] = { 0, 0 }; // expected-note {{array 'arr' declared here}} - if (flag) + 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)}} } @@ -241,7 +241,7 @@ } int test_pr11007_aux(const char * restrict, ...); - + // Test checking with varargs. void test_pr11007() { double a[5]; // expected-note {{array 'a' declared here}} @@ -309,3 +309,23 @@ foo<int>(); // expected-note 1{{in instantiation of function template specialization}} }; } + +namespace PR44343 { + const unsigned int array[2] = {0, 1}; // expected-note 4{{array 'array' declared here}} + + const int i1 = (const int)array[2]; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} + const int i2 = static_cast<const int>(array[2]); // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} + const int &i3 = reinterpret_cast<const int&>(array[2]); // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} + unsigned int &i4 = const_cast<unsigned int&>(array[2]); // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} + + struct Base { + virtual ~Base(); + }; + + struct Derived : Base { + }; + + Base baseArr[2]; // expected-note {{array 'baseArr' declared here}} + Derived *d1 = dynamic_cast<Derived *>(&baseArr[2]); // no warning for one-past-end element's address retrieval + Derived &d2 = dynamic_cast<Derived &>(baseArr[2]); // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} +} Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ clang/lib/Sema/SemaChecking.cpp @@ -13421,6 +13421,15 @@ CheckArrayAccess(Arg); return; } + case Stmt::CStyleCastExprClass: + case Stmt::CXXStaticCastExprClass: + case Stmt::CXXDynamicCastExprClass: + case Stmt::CXXReinterpretCastExprClass: + case Stmt::CXXConstCastExprClass: { + const auto *ECE = cast<ExplicitCastExpr>(expr); + expr = ECE->getSubExpr(); + break; + } default: return; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits