<div dir="ltr">This has broken Windows build bots all day. Here are some recent examples:<div><a href="http://lab.llvm.org:8011/builders/clang-x86-win2008-selfhost/builds/8506/steps/ninja%20check%201/logs/stdio">http://lab.llvm.org:8011/builders/clang-x86-win2008-selfhost/builds/8506/steps/ninja%20check%201/logs/stdio</a><br><div><a href="http://lab.llvm.org:8011/builders/clang-x64-ninja-win7/builds/12981/steps/ninja%20check%201/logs/stdio">http://lab.llvm.org:8011/builders/clang-x64-ninja-win7/builds/12981/steps/ninja%20check%201/logs/stdio</a><br></div><div><br></div><div>Please pay attention to the bots when you are committing changes. I've reverted it in r272453.</div></div><br><div class="gmail_quote"><div dir="ltr">On Fri, Jun 10, 2016 at 5:01 AM Clement Courbet via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: courbet<br>
Date: Fri Jun 10 06:54:43 2016<br>
New Revision: 272386<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=272386&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=272386&view=rev</a><br>
Log:<br>
[ASTMatchers] New forEachOverriden matcher.<br>
<br>
Matches methods overridden by the given method.<br>
<br>
Modified:<br>
    cfe/trunk/docs/LibASTMatchersReference.html<br>
    cfe/trunk/include/clang/AST/ASTContext.h<br>
    cfe/trunk/include/clang/AST/DeclCXX.h<br>
    cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h<br>
    cfe/trunk/lib/AST/ASTContext.cpp<br>
    cfe/trunk/lib/AST/DeclCXX.cpp<br>
    cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp<br>
<br>
Modified: cfe/trunk/docs/LibASTMatchersReference.html<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LibASTMatchersReference.html?rev=272386&r1=272385&r2=272386&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LibASTMatchersReference.html?rev=272386&r1=272385&r2=272386&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/docs/LibASTMatchersReference.html (original)<br>
+++ cfe/trunk/docs/LibASTMatchersReference.html Fri Jun 10 06:54:43 2016<br>
@@ -3968,6 +3968,30 @@ matcher, or is a pointer to a type that<br>
 </pre></td></tr><br>
<br>
<br>
+<tr><td>Matcher&lt;<a href="<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html" rel="noreferrer" target="_blank">http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html</a>">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('forEachOverridden0')"><a name="forEachOverridden0Anchor">forEachOverridden</a></td><td>Matcher&lt;<a href="<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html" rel="noreferrer" target="_blank">http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html</a>">CXXMethodDecl</a>&gt; InnerMatcher</td></tr><br>
+<tr><td colspan="4" class="doc" id="forEachOverridden0"><pre>Matches each method overriden by the given method. This matcher may<br>
+produce multiple matches.<br>
+<br>
+Given<br>
+  class A { virtual void f(); };<br>
+  class B : public A { void f(); };<br>
+  class C : public B { void f(); };<br>
+cxxMethodDecl(ofClass(hasName("C")),<br>
+              forEachOverridden(cxxMethodDecl().bind("b"))).bind("d")<br>
+  matches once, with "b" binding "A::f" and "d" binding "C::f" (Note<br>
+  that B::f is not overridden by C::f).<br>
+<br>
+The check can produce multiple matches in case of multiple inheritance, e.g.<br>
+  class A1 { virtual void f(); };<br>
+  class A2 { virtual void f(); };<br>
+  class C : public A1, public A2 { void f(); };<br>
+cxxMethodDecl(ofClass(hasName("C")),<br>
+              forEachOverridden(cxxMethodDecl().bind("b"))).bind("d")<br>
+  matches twice, once with "b" binding "A1::f" and "d" binding "C::f", and<br>
+  once with "b" binding "A2::f" and "d" binding "C::f".<br>
+</pre></td></tr><br>
+<br>
+<br>
 <tr><td>Matcher&lt;<a href="<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html" rel="noreferrer" target="_blank">http://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html</a>">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('ofClass0')"><a name="ofClass0Anchor">ofClass</a></td><td>Matcher&lt;<a href="<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html" rel="noreferrer" target="_blank">http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html</a>">CXXRecordDecl</a>&gt; InnerMatcher</td></tr><br>
 <tr><td colspan="4" class="doc" id="ofClass0"><pre>Matches the class declaration that the given method declaration<br>
 belongs to.<br>
<br>
Modified: cfe/trunk/include/clang/AST/ASTContext.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=272386&r1=272385&r2=272386&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=272386&r1=272385&r2=272386&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/ASTContext.h (original)<br>
+++ cfe/trunk/include/clang/AST/ASTContext.h Fri Jun 10 06:54:43 2016<br>
@@ -821,6 +821,9 @@ public:<br>
   overridden_methods_end(const CXXMethodDecl *Method) const;<br>
<br>
   unsigned overridden_methods_size(const CXXMethodDecl *Method) const;<br>
+  typedef llvm::iterator_range<overridden_cxx_method_iterator><br>
+      overridden_method_range;<br>
+  overridden_method_range overridden_methods(const CXXMethodDecl *Method) const;<br>
<br>
   /// \brief Note that the given C++ \p Method overrides the given \p<br>
   /// Overridden method.<br>
<br>
Modified: cfe/trunk/include/clang/AST/DeclCXX.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=272386&r1=272385&r2=272386&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=272386&r1=272385&r2=272386&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)<br>
+++ cfe/trunk/include/clang/AST/DeclCXX.h Fri Jun 10 06:54:43 2016<br>
@@ -16,6 +16,7 @@<br>
 #ifndef LLVM_CLANG_AST_DECLCXX_H<br>
 #define LLVM_CLANG_AST_DECLCXX_H<br>
<br>
+#include "clang/AST/ASTContext.h"<br>
 #include "clang/AST/ASTUnresolvedSet.h"<br>
 #include "clang/AST/Attr.h"<br>
 #include "clang/AST/Decl.h"<br>
@@ -1828,6 +1829,8 @@ public:<br>
   method_iterator begin_overridden_methods() const;<br>
   method_iterator end_overridden_methods() const;<br>
   unsigned size_overridden_methods() const;<br>
+  typedef ASTContext::overridden_method_range overridden_method_range;<br>
+  overridden_method_range overridden_methods() const;<br>
<br>
   /// Returns the parent of this method declaration, which<br>
   /// is the class in which this method is defined.<br>
<br>
Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=272386&r1=272385&r2=272386&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=272386&r1=272385&r2=272386&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original)<br>
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Fri Jun 10 06:54:43 2016<br>
@@ -3770,6 +3770,47 @@ AST_MATCHER_P(CXXMethodDecl, ofClass,<br>
           InnerMatcher.matches(*Parent, Finder, Builder));<br>
 }<br>
<br>
+/// \brief Matches each method overriden by the given method. This matcher may<br>
+/// produce multiple matches.<br>
+///<br>
+/// Given<br>
+/// \code<br>
+///   class A { virtual void f(); };<br>
+///   class B : public A { void f(); };<br>
+///   class C : public B { void f(); };<br>
+/// \endcode<br>
+/// cxxMethodDecl(ofClass(hasName("C")),<br>
+///               forEachOverridden(cxxMethodDecl().bind("b"))).bind("d")<br>
+///   matches once, with "b" binding "A::f" and "d" binding "C::f" (Note<br>
+///   that B::f is not overridden by C::f).<br>
+///<br>
+/// The check can produce multiple matches in case of multiple inheritance, e.g.<br>
+/// \code<br>
+///   class A1 { virtual void f(); };<br>
+///   class A2 { virtual void f(); };<br>
+///   class C : public A1, public A2 { void f(); };<br>
+/// \endcode<br>
+/// cxxMethodDecl(ofClass(hasName("C")),<br>
+///               forEachOverridden(cxxMethodDecl().bind("b"))).bind("d")<br>
+///   matches twice, once with "b" binding "A1::f" and "d" binding "C::f", and<br>
+///   once with "b" binding "A2::f" and "d" binding "C::f".<br>
+AST_MATCHER_P(CXXMethodDecl, forEachOverridden,<br>
+              internal::Matcher<CXXMethodDecl>, InnerMatcher) {<br>
+  BoundNodesTreeBuilder Result;<br>
+  bool Matched = false;<br>
+  for (const auto *Overridden : Node.overridden_methods()) {<br>
+    BoundNodesTreeBuilder OverriddenBuilder(*Builder);<br>
+    const bool OverriddenMatched =<br>
+        InnerMatcher.matches(*Overridden, Finder, &OverriddenBuilder);<br>
+    if (OverriddenMatched) {<br>
+      Matched = true;<br>
+      Result.addMatch(OverriddenBuilder);<br>
+    }<br>
+  }<br>
+  *Builder = std::move(Result);<br>
+  return Matched;<br>
+}<br>
+<br>
 /// \brief Matches if the given method declaration is virtual.<br>
 ///<br>
 /// Given<br>
<br>
Modified: cfe/trunk/lib/AST/ASTContext.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=272386&r1=272385&r2=272386&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=272386&r1=272385&r2=272386&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/ASTContext.cpp (original)<br>
+++ cfe/trunk/lib/AST/ASTContext.cpp Fri Jun 10 06:54:43 2016<br>
@@ -1254,34 +1254,37 @@ void ASTContext::setInstantiatedFromUnna<br>
<br>
 ASTContext::overridden_cxx_method_iterator<br>
 ASTContext::overridden_methods_begin(const CXXMethodDecl *Method) const {<br>
-  llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos<br>
-    = OverriddenMethods.find(Method->getCanonicalDecl());<br>
+  llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos =<br>
+      OverriddenMethods.find(Method->getCanonicalDecl());<br>
   if (Pos == OverriddenMethods.end())<br>
     return nullptr;<br>
-<br>
   return Pos->second.begin();<br>
 }<br>
<br>
 ASTContext::overridden_cxx_method_iterator<br>
 ASTContext::overridden_methods_end(const CXXMethodDecl *Method) const {<br>
-  llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos<br>
-    = OverriddenMethods.find(Method->getCanonicalDecl());<br>
+  llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos =<br>
+      OverriddenMethods.find(Method->getCanonicalDecl());<br>
   if (Pos == OverriddenMethods.end())<br>
     return nullptr;<br>
-<br>
   return Pos->second.end();<br>
 }<br>
<br>
 unsigned<br>
 ASTContext::overridden_methods_size(const CXXMethodDecl *Method) const {<br>
-  llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos<br>
-    = OverriddenMethods.find(Method->getCanonicalDecl());<br>
+  llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos =<br>
+      OverriddenMethods.find(Method->getCanonicalDecl());<br>
   if (Pos == OverriddenMethods.end())<br>
     return 0;<br>
-<br>
   return Pos->second.size();<br>
 }<br>
<br>
+ASTContext::overridden_method_range<br>
+ASTContext::overridden_methods(const CXXMethodDecl *Method) const {<br>
+  return overridden_method_range(overridden_methods_begin(Method),<br>
+                                 overridden_methods_end(Method));<br>
+}<br>
+<br>
 void ASTContext::addOverriddenMethod(const CXXMethodDecl *Method,<br>
                                      const CXXMethodDecl *Overridden) {<br>
   assert(Method->isCanonicalDecl() && Overridden->isCanonicalDecl());<br>
<br>
Modified: cfe/trunk/lib/AST/DeclCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=272386&r1=272385&r2=272386&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=272386&r1=272385&r2=272386&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)<br>
+++ cfe/trunk/lib/AST/DeclCXX.cpp Fri Jun 10 06:54:43 2016<br>
@@ -1635,6 +1635,13 @@ unsigned CXXMethodDecl::size_overridden_<br>
   return getASTContext().overridden_methods_size(this);<br>
 }<br>
<br>
+CXXMethodDecl::overridden_method_range<br>
+CXXMethodDecl::overridden_methods() const {<br>
+  if (isa<CXXConstructorDecl>(this))<br>
+    return overridden_method_range(nullptr, nullptr);<br>
+  return getASTContext().overridden_methods(this);<br>
+}<br>
+<br>
 QualType CXXMethodDecl::getThisType(ASTContext &C) const {<br>
   // C++ 9.3.2p1: The type of this in a member function of a class X is X*.<br>
   // If the member function is declared const, the type of this is const X*,<br>
<br>
Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp?rev=272386&r1=272385&r2=272386&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp?rev=272386&r1=272385&r2=272386&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp (original)<br>
+++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp Fri Jun 10 06:54:43 2016<br>
@@ -1997,5 +1997,49 @@ TEST(StatementMatcher, ForFunction) {<br>
   EXPECT_TRUE(notMatches(CppString2, returnStmt(forFunction(hasName("F")))));<br>
 }<br>
<br>
+TEST(Matcher, ForEachOverriden) {<br>
+  const auto ForEachOverriddenInClass = [](const char *ClassName) {<br>
+    return cxxMethodDecl(ofClass(hasName(ClassName)), isVirtual(),<br>
+                         forEachOverridden(cxxMethodDecl().bind("overridden")))<br>
+        .bind("override");<br>
+  };<br>
+  constexpr const char Code1[] = "class A { virtual void f(); };"<br>
+                                 "class B : public A { void f(); };"<br>
+                                 "class C : public B { void f(); };";<br>
+  // C::f overrides A::f.<br>
+  EXPECT_TRUE(matchAndVerifyResultTrue(<br>
+      Code1, ForEachOverriddenInClass("C"),<br>
+      llvm::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("override", "f", 1)));<br>
+  EXPECT_TRUE(matchAndVerifyResultTrue(<br>
+      Code1, ForEachOverriddenInClass("C"),<br>
+      llvm::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("overridden", "f",<br>
+                                                          1)));<br>
+  // B::f overrides A::f.<br>
+  EXPECT_TRUE(matchAndVerifyResultTrue(<br>
+      Code1, ForEachOverriddenInClass("B"),<br>
+      llvm::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("override", "f", 1)));<br>
+  EXPECT_TRUE(matchAndVerifyResultTrue(<br>
+      Code1, ForEachOverriddenInClass("B"),<br>
+      llvm::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("overridden", "f",<br>
+                                                          1)));<br>
+  // A::f overrides nothing.<br>
+  EXPECT_TRUE(notMatches(Code1, ForEachOverriddenInClass("A")));<br>
+<br>
+  constexpr const char Code2[] =<br>
+      "class A1 { virtual void f(); };"<br>
+      "class A2 { virtual void f(); };"<br>
+      "class B : public A1, public A2 { void f(); };";<br>
+  // B::f overrides A1::f and A2::f. This produces two matches.<br>
+  EXPECT_TRUE(matchAndVerifyResultTrue(<br>
+      Code2, ForEachOverriddenInClass("B"),<br>
+      llvm::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("override", "f", 2)));<br>
+  EXPECT_TRUE(matchAndVerifyResultTrue(<br>
+      Code2, ForEachOverriddenInClass("B"),<br>
+      llvm::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("overridden", "f",<br>
+                                                          2)));<br>
+  // A1::f overrides nothing.<br>
+  EXPECT_TRUE(notMatches(Code2, ForEachOverriddenInClass("A1")));<br>
+}<br>
+<br>
 } // namespace ast_matchers<br>
 } // namespace clang<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div></div>