Enhance the array bounds checking to work for several other constructs,
especially C++ code, and generally expand the test coverage.

Logic adapted from a patch by Kaelyn Uhrain <rikka@google.com> and
another Googler.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125775 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index d00f092..6b1013d 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -3095,17 +3095,12 @@
 }
 
 void Sema::CheckArrayAccess(const clang::ArraySubscriptExpr *E) {
-  const DeclRefExpr *DRE =
-    dyn_cast<DeclRefExpr>(E->getBase()->IgnoreParenImpCasts());
-  if (!DRE)
-    return;
-  const VarDecl *Variable = dyn_cast<VarDecl>(DRE->getDecl());
-  if (!Variable)
-    return;
+  const Expr *BaseExpr = E->getBase()->IgnoreParenImpCasts();
   const ConstantArrayType *ArrayTy =
-    Context.getAsConstantArrayType(Variable->getType());
+    Context.getAsConstantArrayType(BaseExpr->getType());
   if (!ArrayTy)
     return;
+
   const Expr *IndexExpr = E->getIdx();
   if (IndexExpr->isValueDependent())
     return;
@@ -3115,6 +3110,8 @@
 
   if (!index.isNegative()) {
     const llvm::APInt &size = ArrayTy->getSize();
+    if (!size.isStrictlyPositive())
+      return;
     if (size.getBitWidth() > index.getBitWidth())
       index = index.sext(size.getBitWidth());
     if (index.slt(size))
@@ -3127,7 +3124,14 @@
     Diag(E->getBase()->getLocStart(), diag::warn_array_index_precedes_bounds)
       << index.toString(10, true) << IndexExpr->getSourceRange();
   }
-  Diag(Variable->getLocStart(), diag::note_array_index_out_of_bounds)
-    << Variable->getDeclName();
+
+  const NamedDecl *ND = NULL;
+  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
+    ND = dyn_cast<NamedDecl>(DRE->getDecl());
+  if (const MemberExpr *ME = dyn_cast<MemberExpr>(BaseExpr))
+    ND = dyn_cast<NamedDecl>(ME->getMemberDecl());
+  if (ND)
+    Diag(ND->getLocStart(), diag::note_array_index_out_of_bounds)
+      << ND->getDeclName();
 }