diff --git a/include/clang/ASTMatchers/ASTMatchFinder.h b/include/clang/ASTMatchers/ASTMatchFinder.h
index 75525ad1d62eccb1b8780ed9951bed05958fa16a..dfd414f35be48ff6fed5ee7031c15cc0b54e1e0c 100644
--- a/include/clang/ASTMatchers/ASTMatchFinder.h
+++ b/include/clang/ASTMatchers/ASTMatchFinder.h
@@ -173,11 +173,23 @@ public:
   /// Each call to FindAll(...) will call the closure once.
   void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone);
 
-private:
-  /// \brief For each \c DynTypedMatcher a \c MatchCallback that will be called
+  /// \brief For each \c Matcher<> a \c MatchCallback that will be called
   /// when it matches.
-  std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *> >
-    MatcherCallbackPairs;
+  struct MatchersByType {
+    std::vector<std::pair<DeclarationMatcher, MatchCallback *>> Decl;
+    std::vector<std::pair<TypeMatcher, MatchCallback *>> Type;
+    std::vector<std::pair<StatementMatcher, MatchCallback *>> Stmt;
+    std::vector<std::pair<NestedNameSpecifierMatcher, MatchCallback *>>
+        NestedNameSpecifier;
+    std::vector<std::pair<NestedNameSpecifierLocMatcher, MatchCallback *>>
+        NestedNameSpecifierLoc;
+    std::vector<std::pair<TypeLocMatcher, MatchCallback *>> TypeLoc;
+    /// \brief All the callbacks in one container to simplify iteration.
+    std::vector<MatchCallback *> AllCallbacks;
+  };
+
+private:
+  MatchersByType Matchers;
 
   /// \brief Called when parsing is done.
   ParsingDoneTestCallback *ParsingDone;
diff --git a/lib/ASTMatchers/ASTMatchFinder.cpp b/lib/ASTMatchers/ASTMatchFinder.cpp
index 6c5bc3c3727de8d510cb008fe19465d2a7ff82f1..47f45bc3ad9e38dbcad01fd1d17702f8b09d9ddb 100644
--- a/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -292,29 +292,17 @@ private:
 class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
                         public ASTMatchFinder {
 public:
-  MatchASTVisitor(
-      std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *> > *
-          MatcherCallbackPairs)
-      : MatcherCallbackPairs(MatcherCallbackPairs), ActiveASTContext(nullptr) {}
+ MatchASTVisitor(const MatchFinder::MatchersByType *Matchers)
+     : Matchers(Matchers), ActiveASTContext(nullptr) {}
 
   void onStartOfTranslationUnit() {
-    for (std::vector<std::pair<internal::DynTypedMatcher,
-                               MatchCallback *> >::const_iterator
-             I = MatcherCallbackPairs->begin(),
-             E = MatcherCallbackPairs->end();
-         I != E; ++I) {
-      I->second->onStartOfTranslationUnit();
-    }
+    for (MatchCallback *MC : Matchers->AllCallbacks)
+      MC->onStartOfTranslationUnit();
   }
 
   void onEndOfTranslationUnit() {
-    for (std::vector<std::pair<internal::DynTypedMatcher,
-                               MatchCallback *> >::const_iterator
-             I = MatcherCallbackPairs->begin(),
-             E = MatcherCallbackPairs->end();
-         I != E; ++I) {
-      I->second->onEndOfTranslationUnit();
-    }
+    for (MatchCallback *MC : Matchers->AllCallbacks)
+      MC->onEndOfTranslationUnit();
   }
 
   void set_active_ast_context(ASTContext *NewActiveASTContext) {
@@ -447,22 +435,27 @@ public:
 
   // Matches all registered matchers on the given node and calls the
   // result callback for every node that matches.
-  void match(const ast_type_traits::DynTypedNode& Node) {
-    for (std::vector<std::pair<internal::DynTypedMatcher,
-                               MatchCallback *> >::const_iterator
-             I = MatcherCallbackPairs->begin(),
-             E = MatcherCallbackPairs->end();
-         I != E; ++I) {
-      BoundNodesTreeBuilder Builder;
-      if (I->first.matches(Node, this, &Builder)) {
-        MatchVisitor Visitor(ActiveASTContext, I->second);
-        Builder.visitMatches(&Visitor);
-      }
+  void match(const ast_type_traits::DynTypedNode &Node) {
+    // FIXME: Improve this with a switch or a visitor pattern.
+    if (auto *N = Node.get<Decl>()) {
+      match(*N);
+    } else if (auto *N = Node.get<Stmt>()) {
+      match(*N);
+    } else if (auto *N = Node.get<Type>()) {
+      match(*N);
+    } else if (auto *N = Node.get<QualType>()) {
+      match(*N);
+    } else if (auto *N = Node.get<NestedNameSpecifier>()) {
+      match(*N);
+    } else if (auto *N = Node.get<NestedNameSpecifierLoc>()) {
+      match(*N);
+    } else if (auto *N = Node.get<TypeLoc>()) {
+      match(*N);
     }
   }
 
   template <typename T> void match(const T &Node) {
-    match(ast_type_traits::DynTypedNode::create(Node));
+    matchDispatch(&Node);
   }
 
   // Implements ASTMatchFinder::getASTContext.
@@ -475,6 +468,40 @@ public:
   bool shouldUseDataRecursionFor(clang::Stmt *S) const { return false; }
 
 private:
+  /// \brief Runs all the \p Matchers on \p Node.
+  ///
+  /// Used by \c matchDispatch() below.
+  template <typename T, typename MC>
+  void matchImpl(const T &Node, const MC &Matchers) {
+    for (const auto &MP : Matchers) {
+      BoundNodesTreeBuilder Builder;
+      if (MP.first.matches(Node, this, &Builder)) {
+        MatchVisitor Visitor(ActiveASTContext, MP.second);
+        Builder.visitMatches(&Visitor);
+      }
+    }
+  }
+
+  /// @{
+  /// \brief Overloads to pair the different node types to their matchers.
+  void matchDispatch(const Decl *Node) { matchImpl(*Node, Matchers->Decl); }
+  void matchDispatch(const Stmt *Node) { matchImpl(*Node, Matchers->Stmt); }
+  void matchDispatch(const Type *Node) {
+    matchImpl(QualType(Node, 0), Matchers->Type);
+  }
+  void matchDispatch(const TypeLoc *Node) {
+    matchImpl(*Node, Matchers->TypeLoc);
+  }
+  void matchDispatch(const QualType *Node) { matchImpl(*Node, Matchers->Type); }
+  void matchDispatch(const NestedNameSpecifier *Node) {
+    matchImpl(*Node, Matchers->NestedNameSpecifier);
+  }
+  void matchDispatch(const NestedNameSpecifierLoc *Node) {
+    matchImpl(*Node, Matchers->NestedNameSpecifierLoc);
+  }
+  void matchDispatch(const void *) { /* Do nothing. */ }
+  /// @}
+
   // Returns whether an ancestor of \p Node matches \p Matcher.
   //
   // The order of matching ((which can lead to different nodes being bound in
@@ -602,8 +629,7 @@ private:
     return false;
   }
 
-  std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *> > *const
-  MatcherCallbackPairs;
+  const MatchFinder::MatchersByType *Matchers;
   ASTContext *ActiveASTContext;
 
   // Maps a canonical type to its TypedefDecls.
@@ -772,32 +798,38 @@ MatchFinder::~MatchFinder() {}
 
 void MatchFinder::addMatcher(const DeclarationMatcher &NodeMatch,
                              MatchCallback *Action) {
-  MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action));
+  Matchers.Decl.push_back(std::make_pair(NodeMatch, Action));
+  Matchers.AllCallbacks.push_back(Action);
 }
 
 void MatchFinder::addMatcher(const TypeMatcher &NodeMatch,
                              MatchCallback *Action) {
-  MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action));
+  Matchers.Type.push_back(std::make_pair(NodeMatch, Action));
+  Matchers.AllCallbacks.push_back(Action);
 }
 
 void MatchFinder::addMatcher(const StatementMatcher &NodeMatch,
                              MatchCallback *Action) {
-  MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action));
+  Matchers.Stmt.push_back(std::make_pair(NodeMatch, Action));
+  Matchers.AllCallbacks.push_back(Action);
 }
 
 void MatchFinder::addMatcher(const NestedNameSpecifierMatcher &NodeMatch,
                              MatchCallback *Action) {
-  MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action));
+  Matchers.NestedNameSpecifier.push_back(std::make_pair(NodeMatch, Action));
+  Matchers.AllCallbacks.push_back(Action);
 }
 
 void MatchFinder::addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch,
                              MatchCallback *Action) {
-  MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action));
+  Matchers.NestedNameSpecifierLoc.push_back(std::make_pair(NodeMatch, Action));
+  Matchers.AllCallbacks.push_back(Action);
 }
 
 void MatchFinder::addMatcher(const TypeLocMatcher &NodeMatch,
                              MatchCallback *Action) {
-  MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action));
+  Matchers.TypeLoc.push_back(std::make_pair(NodeMatch, Action));
+  Matchers.AllCallbacks.push_back(Action);
 }
 
 bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
@@ -830,13 +862,13 @@ std::unique_ptr<ASTConsumer> MatchFinder::newASTConsumer() {
 
 void MatchFinder::match(const clang::ast_type_traits::DynTypedNode &Node,
                         ASTContext &Context) {
-  internal::MatchASTVisitor Visitor(&MatcherCallbackPairs);
+  internal::MatchASTVisitor Visitor(&Matchers);
   Visitor.set_active_ast_context(&Context);
   Visitor.match(Node);
 }
 
 void MatchFinder::matchAST(ASTContext &Context) {
-  internal::MatchASTVisitor Visitor(&MatcherCallbackPairs);
+  internal::MatchASTVisitor Visitor(&Matchers);
   Visitor.set_active_ast_context(&Context);
   Visitor.onStartOfTranslationUnit();
   Visitor.TraverseDecl(Context.getTranslationUnitDecl());