Fix bug 25362 "cppcoreguidelines-pro-bounds-array-to-pointer-decay does not consider const"

Summary:
The current matcher is
  implicitCastExpr(unless(hasParent(explicitCastExpr())))
but the AST in the bug is
  `-CXXStaticCastExpr 0x2bb64f8 <col:21, col:55> 'void *const *'
static_cast<void *const *> <NoOp>
    `-ImplicitCastExpr 0x2bb64e0 <col:47> 'void *const *' <NoOp>
      `-ImplicitCastExpr 0x2bb64c8 <col:47> 'void **'
<ArrayToPointerDecay>
        `-DeclRefExpr 0x2bb6458 <col:47> 'void *[2]' lvalue Var
0x2bb59d0 'addrlist' 'void *[2]'
i.e. an ImplicitCastExpr (const cast) between decay and explicit cast.

Reviewers: alexfh, sbenza, bkramer, aaron.ballman

Subscribers: cfe-commits

Differential Revision: http://reviews.llvm.org/D14517

llvm-svn: 253399
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp
index 514289d..75093a0 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp
@@ -28,6 +28,22 @@
       .matches(Node, Finder, Builder);
 }
 
+AST_MATCHER_P(Expr, hasParentIgnoringImpCasts,
+              ast_matchers::internal::Matcher<Expr>, InnerMatcher) {
+  const Expr *E = &Node;
+  do {
+    ASTContext::DynTypedNodeList Parents =
+        Finder->getASTContext().getParents(*E);
+    if (Parents.size() != 1)
+      return false;
+    E = Parents[0].get<Expr>();
+    if (!E)
+      return false;
+  } while (isa<ImplicitCastExpr>(E));
+
+  return InnerMatcher.matches(*E, Finder, Builder);
+}
+
 void ProBoundsArrayToPointerDecayCheck::registerMatchers(MatchFinder *Finder) {
   if (!getLangOpts().CPlusPlus)
     return;
@@ -38,7 +54,7 @@
   // 3) if it converts a string literal to a pointer
   Finder->addMatcher(
       implicitCastExpr(unless(hasParent(arraySubscriptExpr())),
-                       unless(hasParent(explicitCastExpr())),
+                       unless(hasParentIgnoringImpCasts(explicitCastExpr())),
                        unless(isInsideOfRangeBeginEndStmt()),
                        unless(hasSourceExpression(stringLiteral())))
           .bind("cast"),