[clang] 9083d0a - Revert "[Sema] Fix -Warray-bounds false negative when casting an out-of-bounds array item"

via cfe-commits cfe-commits at lists.llvm.org
Mon Feb 8 04:41:02 PST 2021


Author: einvbri
Date: 2021-02-08T06:38:31-06:00
New Revision: 9083d0a40d980928f2f45236a4616528a7ab19ce

URL: https://github.com/llvm/llvm-project/commit/9083d0a40d980928f2f45236a4616528a7ab19ce
DIFF: https://github.com/llvm/llvm-project/commit/9083d0a40d980928f2f45236a4616528a7ab19ce.diff

LOG: Revert "[Sema] Fix -Warray-bounds false negative when casting an out-of-bounds array item"

This reverts commit e48f444751cf781c42934b242b81f549da77bad0.

thakis noticed false reports, so reverting this change for now until
those can be sorted out.

See https://reviews.llvm.org/D71714

Added: 
    

Modified: 
    clang/include/clang/Sema/Sema.h
    clang/lib/Sema/SemaChecking.cpp
    clang/test/Parser/cxx-ambig-decl-expr.cpp
    clang/test/SemaCXX/array-bounds.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 68420fcbb85f..8b5619945865 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -12313,7 +12313,7 @@ class Sema final {
   void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
                         const ArraySubscriptExpr *ASE=nullptr,
                         bool AllowOnePastEnd=true, bool IndexNegated=false);
-  void CheckArrayAccess(const Expr *E, int AllowOnePastEnd = 0);
+  void CheckArrayAccess(const Expr *E);
   // Used to grab the relevant information from a FormatAttr and a
   // FunctionDeclaration.
   struct FormatStringInfo {

diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 17dd5c9e8d99..2d3d36f4adad 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -14387,63 +14387,62 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
                         PDiag(diag::note_array_declared_here) << ND);
 }
 
-void Sema::CheckArrayAccess(const Expr *expr, int AllowOnePastEnd) {
-  if (!expr)
-    return;
-
-  expr = expr->IgnoreParenCasts();
-  switch (expr->getStmtClass()) {
-  case Stmt::ArraySubscriptExprClass: {
-    const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(expr);
-    CheckArrayAccess(ASE->getBase(), ASE->getIdx(), ASE, AllowOnePastEnd > 0);
-    CheckArrayAccess(ASE->getBase(), AllowOnePastEnd);
-    return;
-  }
-  case Stmt::MemberExprClass: {
-    expr = cast<MemberExpr>(expr)->getBase();
-    CheckArrayAccess(expr, /*AllowOnePastEnd=*/0);
-    return;
-  }
-  case Stmt::OMPArraySectionExprClass: {
-    const OMPArraySectionExpr *ASE = cast<OMPArraySectionExpr>(expr);
-    if (ASE->getLowerBound())
-      CheckArrayAccess(ASE->getBase(), ASE->getLowerBound(),
-                       /*ASE=*/nullptr, AllowOnePastEnd > 0);
-    return;
-  }
-  case Stmt::UnaryOperatorClass: {
-    // Only unwrap the * and & unary operators
-    const UnaryOperator *UO = cast<UnaryOperator>(expr);
-    expr = UO->getSubExpr();
-    switch (UO->getOpcode()) {
-    case UO_AddrOf:
-      AllowOnePastEnd++;
-      break;
-    case UO_Deref:
-      AllowOnePastEnd--;
-      break;
-    default:
-      return;
+void Sema::CheckArrayAccess(const Expr *expr) {
+  int AllowOnePastEnd = 0;
+  while (expr) {
+    expr = expr->IgnoreParenImpCasts();
+    switch (expr->getStmtClass()) {
+      case Stmt::ArraySubscriptExprClass: {
+        const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(expr);
+        CheckArrayAccess(ASE->getBase(), ASE->getIdx(), ASE,
+                         AllowOnePastEnd > 0);
+        expr = ASE->getBase();
+        break;
+      }
+      case Stmt::MemberExprClass: {
+        expr = cast<MemberExpr>(expr)->getBase();
+        break;
+      }
+      case Stmt::OMPArraySectionExprClass: {
+        const OMPArraySectionExpr *ASE = cast<OMPArraySectionExpr>(expr);
+        if (ASE->getLowerBound())
+          CheckArrayAccess(ASE->getBase(), ASE->getLowerBound(),
+                           /*ASE=*/nullptr, AllowOnePastEnd > 0);
+        return;
+      }
+      case Stmt::UnaryOperatorClass: {
+        // Only unwrap the * and & unary operators
+        const UnaryOperator *UO = cast<UnaryOperator>(expr);
+        expr = UO->getSubExpr();
+        switch (UO->getOpcode()) {
+          case UO_AddrOf:
+            AllowOnePastEnd++;
+            break;
+          case UO_Deref:
+            AllowOnePastEnd--;
+            break;
+          default:
+            return;
+        }
+        break;
+      }
+      case Stmt::ConditionalOperatorClass: {
+        const ConditionalOperator *cond = cast<ConditionalOperator>(expr);
+        if (const Expr *lhs = cond->getLHS())
+          CheckArrayAccess(lhs);
+        if (const Expr *rhs = cond->getRHS())
+          CheckArrayAccess(rhs);
+        return;
+      }
+      case Stmt::CXXOperatorCallExprClass: {
+        const auto *OCE = cast<CXXOperatorCallExpr>(expr);
+        for (const auto *Arg : OCE->arguments())
+          CheckArrayAccess(Arg);
+        return;
+      }
+      default:
+        return;
     }
-    CheckArrayAccess(expr, AllowOnePastEnd);
-    return;
-  }
-  case Stmt::ConditionalOperatorClass: {
-    const ConditionalOperator *cond = cast<ConditionalOperator>(expr);
-    if (const Expr *lhs = cond->getLHS())
-      CheckArrayAccess(lhs, AllowOnePastEnd);
-    if (const Expr *rhs = cond->getRHS())
-      CheckArrayAccess(rhs, AllowOnePastEnd);
-    return;
-  }
-  case Stmt::CXXOperatorCallExprClass: {
-    const auto *OCE = cast<CXXOperatorCallExpr>(expr);
-    for (const auto *Arg : OCE->arguments())
-      CheckArrayAccess(Arg);
-    return;
-  }
-  default:
-    return;
   }
 }
 

diff  --git a/clang/test/Parser/cxx-ambig-decl-expr.cpp b/clang/test/Parser/cxx-ambig-decl-expr.cpp
index 373fe250c6b5..6203db2fbd22 100644
--- a/clang/test/Parser/cxx-ambig-decl-expr.cpp
+++ b/clang/test/Parser/cxx-ambig-decl-expr.cpp
@@ -24,7 +24,7 @@ void arr() {
 
   // This is array indexing not an array declarator because a comma expression
   // is not syntactically a constant-expression.
-  int(x[1,0]); // expected-warning 2{{unused}}
+  int(x[1,1]); // expected-warning 2{{unused}}
 
   // This is array indexing not an array declaration because a braced-init-list
   // is not syntactically a constant-expression.

diff  --git a/clang/test/SemaCXX/array-bounds.cpp b/clang/test/SemaCXX/array-bounds.cpp
index 837175014fe5..47be6c2423dc 100644
--- a/clang/test/SemaCXX/array-bounds.cpp
+++ b/clang/test/SemaCXX/array-bounds.cpp
@@ -27,7 +27,7 @@ template <char *sz> class Qux {
 };
 
 void f1(int a[1]) {
-  int val = a[3]; // no warning for function argument
+  int val = a[3]; // no warning for function argumnet
 }
 
 void f2(const int (&a)[2]) { // expected-note {{declared here}}
@@ -133,7 +133,7 @@ int test_pr9296() {
 
 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 @@ void test_pr10771() {
 }
 
 int test_pr11007_aux(const char * restrict, ...);
-
+  
 // Test checking with varargs.
 void test_pr11007() {
   double a[5]; // expected-note {{array 'a' declared here}}
@@ -320,33 +320,3 @@ void test() {
   arr<float>[1] = 0; // expected-warning {{array index 1 is past the end of the array (which contains 1 element)}}
 }
 } // namespace var_template_array
-
-namespace PR44343 {
-  const unsigned int array[2] = {0, 1}; // expected-note 5{{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)}}
-  int i5 = int(array[2]); // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}}
-  const unsigned int *i6 = &(1 > 0 ? array[2] : array[1]); // no warning for one-past-end element's address retrieval
-
-  // Test dynamic cast
-  struct Base {
-    virtual ~Base();
-  };
-  struct Derived : Base {
-  };
-  Base baseArr[2]; // expected-note {{array 'baseArr' declared here}}
-  Derived *d1 = dynamic_cast<Derived *>(&baseArr[2]); // FIXME: Should actually warn because dynamic_cast accesses the vptr
-  Derived &d2 = dynamic_cast<Derived &>(baseArr[2]); // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}}
-
-  // Test operator `&` in combination with operators `.` and `->`
-  struct A {
-    int n;
-  };
-  A a[2]; // expected-note {{array 'a' declared here}}
-  int *n = &a[2].n; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}}
-  A *aPtr[2]; // expected-note {{array 'aPtr' declared here}}
-  int *n2 = &aPtr[2]->n; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}}
-}


        


More information about the cfe-commits mailing list