From 8338c0deafecd70c68d85881ac90d77e994c9b03 Mon Sep 17 00:00:00 2001
From: Piotr Padlewski <piotr.padlewski@gmail.com>
Date: Tue, 31 May 2016 15:25:05 +0000
Subject: [PATCH] [ASTMatchers] Breaking change of `has` matcher

has matcher can now match to implicit and paren casts

http://reviews.llvm.org/D20801

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@271288 91177308-0d34-0410-b5e6-96231b3b80d8
---
 docs/ReleaseNotes.rst                         | 12 +++++-----
 include/clang/ASTMatchers/ASTMatchers.h       |  4 ++++
 .../clang/ASTMatchers/ASTMatchersInternal.h   |  9 +++-----
 include/clang/CMakeLists.txt                  |  1 +
 unittests/AST/ASTImporterTest.cpp             | 22 +++++++------------
 .../ASTMatchers/ASTMatchersTraversalTest.cpp  |  4 ++--
 6 files changed, 25 insertions(+), 27 deletions(-)

diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst
index dcd39e23c94..bcf67ec4944 100644
--- a/docs/ReleaseNotes.rst
+++ b/docs/ReleaseNotes.rst
@@ -185,11 +185,13 @@ this section should help get you past the largest hurdles of upgrading.
 AST Matchers
 ------------
 
-- hasAnyArgument: Matcher no longer ignores parentheses and implicit casts on
-  the argument before applying the inner matcher. The fix was done to allow for
-  greater control by the user. In all existing checkers that use this matcher
-  all instances of code ``hasAnyArgument(<inner matcher>)`` must be changed to
-  ``hasAnyArgument(ignoringParenImpCasts(<inner matcher>))``.
+- has and hasAnyArgument: Matchers no longer ignores parentheses and implicit
+  casts on the argument before applying the inner matcher. The fix was done to
+  allow for greater control by the user. In all existing checkers that use this
+  matcher all instances of code ``hasAnyArgument(<inner matcher>)`` or
+  ``has(<inner matcher>)`` must be changed to
+  ``hasAnyArgument(ignoringParenImpCasts(<inner matcher>))`` or
+  ``has(ignoringParenImpCasts(<inner matcher>))``.
 
 ...
 
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index c445152c7c4..91a7f694721 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -2169,6 +2169,10 @@ AST_MATCHER_P(CXXRecordDecl, hasMethod, internal::Matcher<CXXMethodDecl>,
 /// ChildT must be an AST base type.
 ///
 /// Usable as: Any Matcher
+/// Note that has is direct matcher, so it also matches things like implicit
+/// casts and paren casts. If you are matching with expr then you should
+/// probably consider using ignoringParenImpCasts like:
+/// has(ignoringParenImpCasts(expr())).
 const internal::ArgumentAdaptingMatcherFunc<internal::HasMatcher>
 LLVM_ATTRIBUTE_UNUSED has = {};
 
diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h
index af8d737ad9e..86c8e6cfec7 100644
--- a/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -1165,8 +1165,6 @@ public:
 /// ChildT must be an AST base type.
 template <typename T, typename ChildT>
 class HasMatcher : public WrapperMatcherInterface<T> {
-  static_assert(IsBaseType<ChildT>::value,
-                "has only accepts base type matcher");
 
 public:
   explicit HasMatcher(const Matcher<ChildT> &ChildMatcher)
@@ -1174,10 +1172,9 @@ public:
 
   bool matches(const T &Node, ASTMatchFinder *Finder,
                BoundNodesTreeBuilder *Builder) const override {
-    return Finder->matchesChildOf(
-        Node, this->InnerMatcher, Builder,
-        ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses,
-        ASTMatchFinder::BK_First);
+    return Finder->matchesChildOf(Node, this->InnerMatcher, Builder,
+                                  ASTMatchFinder::TK_AsIs,
+                                  ASTMatchFinder::BK_First);
   }
 };
 
diff --git a/include/clang/CMakeLists.txt b/include/clang/CMakeLists.txt
index feb81f0686c..96905c97289 100644
--- a/include/clang/CMakeLists.txt
+++ b/include/clang/CMakeLists.txt
@@ -5,3 +5,4 @@ add_subdirectory(Parse)
 add_subdirectory(Sema)
 add_subdirectory(Serialization)
 add_subdirectory(StaticAnalyzer/Checkers)
+add_subdirectory(ASTMatchers)
diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp
index f5dee659e0e..c8a5ddffce9 100644
--- a/unittests/AST/ASTImporterTest.cpp
+++ b/unittests/AST/ASTImporterTest.cpp
@@ -225,20 +225,14 @@ TEST(ImportExpr, ImportCXXThisExpr) {
 
 TEST(ImportExpr, ImportAtomicExpr) {
   MatchVerifier<Decl> Verifier;
-  EXPECT_TRUE(
-        testImport(
-          "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
-          Lang_CXX, "", Lang_CXX, Verifier,
-          functionDecl(
-            hasBody(
-              compoundStmt(
-                has(
-                  atomicExpr(
-                    has(declRefExpr(
-                          hasDeclaration(varDecl(hasName("ptr"))),
-                          hasType(asString("int *")))),
-                    has(integerLiteral(equals(1), hasType(asString("int"))))
-                    )))))));
+  EXPECT_TRUE(testImport(
+      "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }", Lang_CXX,
+      "", Lang_CXX, Verifier,
+      functionDecl(hasBody(compoundStmt(has(atomicExpr(
+          has(ignoringParenImpCasts(
+              declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
+                          hasType(asString("int *"))))),
+          has(integerLiteral(equals(1), hasType(asString("int")))))))))));
 }
 
 TEST(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
diff --git a/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
index 481b7e3041d..cc5cf715a70 100644
--- a/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -122,8 +122,8 @@ TEST(Has, MatchesChildTypes) {
 
 TEST(StatementMatcher, Has) {
   StatementMatcher HasVariableI =
-    expr(hasType(pointsTo(recordDecl(hasName("X")))),
-         has(declRefExpr(to(varDecl(hasName("i"))))));
+      expr(hasType(pointsTo(recordDecl(hasName("X")))),
+           has(ignoringParenImpCasts(declRefExpr(to(varDecl(hasName("i")))))));
 
   EXPECT_TRUE(matches(
     "class X; X *x(int); void c() { int i; x(i); }", HasVariableI));
-- 
GitLab