]> granicus.if.org Git - clang/commitdiff
Fix isInstantiated and isInTemplateInstantiation to not recreate the matchers on...
authorSamuel Benzaquen <sbenza@google.com>
Mon, 8 Dec 2014 20:17:58 +0000 (20:17 +0000)
committerSamuel Benzaquen <sbenza@google.com>
Mon, 8 Dec 2014 20:17:58 +0000 (20:17 +0000)
Summary:
Store the result matcher after the first call and reuse it later on.
Recreating the matchers just to use them once incurs in a lot of
unnecessary temporary memory allocations.
This change speeds up our clang-tidy benchmarks by ~2%.

Reviewers: klimek

Subscribers: klimek, cfe-commits

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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@223690 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/ASTMatchers/ASTMatchers.h
include/clang/ASTMatchers/ASTMatchersInternal.h
include/clang/ASTMatchers/ASTMatchersMacros.h

index cbdca79fc46bf1fca15c580918ed1937d8ad8a87..9d20c9e0f5e2778296f26b1a583aebdbab8fa55d 100644 (file)
@@ -3159,12 +3159,10 @@ AST_POLYMORPHIC_MATCHER(
 /// \endcode
 /// functionDecl(isInstantiated())
 ///   matches 'A(int) {...};' and 'A(unsigned) {...}'.
-AST_MATCHER(Decl, isInstantiated) {
+AST_MATCHER_FUNCTION(internal::Matcher<Decl>, isInstantiated) {
   auto IsInstantiation = decl(anyOf(recordDecl(isTemplateInstantiation()),
                                     functionDecl(isTemplateInstantiation())));
-  auto InnerMatcher =
-      decl(anyOf(IsInstantiation, hasAncestor(IsInstantiation)));
-  return InnerMatcher.matches(Node, Finder, Builder);
+  return decl(anyOf(IsInstantiation, hasAncestor(IsInstantiation)));
 }
 
 /// \brief Matches statements inside of a template instantiation.
@@ -3181,11 +3179,10 @@ AST_MATCHER(Decl, isInstantiated) {
 /// unless(stmt(isInTemplateInstantiation()))
 ///   will NOT match j += 42; as it's shared between the template definition and
 ///   instantiation.
-AST_MATCHER(Stmt, isInTemplateInstantiation) {
-  auto InnerMatcher =
-      stmt(hasAncestor(decl(anyOf(recordDecl(isTemplateInstantiation()),
-                                  functionDecl(isTemplateInstantiation())))));
-  return InnerMatcher.matches(Node, Finder, Builder);
+AST_MATCHER_FUNCTION(internal::Matcher<Stmt>, isInTemplateInstantiation) {
+  return stmt(
+      hasAncestor(decl(anyOf(recordDecl(isTemplateInstantiation()),
+                             functionDecl(isTemplateInstantiation())))));
 }
 
 /// \brief Matches explicit template specializations of function, class, or
index 95e740e65b114c46be04a109d69b678bd17d9893..ebe5cddb622a2cc5ba6a5ebdc9a9b7a324323ddc 100644 (file)
@@ -44,6 +44,7 @@
 #include "clang/AST/Type.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/VariadicFunction.h"
+#include "llvm/Support/ManagedStatic.h"
 #include <map>
 #include <string>
 #include <vector>
@@ -1620,6 +1621,23 @@ private:
   const Matcher<InnerTBase> InnerMatcher;
 };
 
+/// \brief A simple memoizer of T(*)() functions.
+///
+/// It will call the passed 'Func' template parameter at most once.
+/// Used to support AST_MATCHER_FUNCTION() macro.
+template <typename Matcher, Matcher (*Func)()> class MemoizedMatcher {
+  struct Wrapper {
+    Wrapper() : M(Func()) {}
+    Matcher M;
+  };
+
+public:
+  static const Matcher &getInstance() {
+    static llvm::ManagedStatic<Wrapper> Instance;
+    return Instance->M;
+  }
+};
+
 // Define the create() method out of line to silence a GCC warning about
 // the struct "Func" having greater visibility than its base, which comes from
 // using the flag -fvisibility-inlines-hidden.
index 4d57b94c7fb932c415970ca2f83d98028746d836..b7888be7c176769b8f2fd93f83196154c3d6d427 100644 (file)
 #ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H
 #define LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H
 
+/// \brief AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) {
+/// defines a zero parameter function named DefineMatcher() that returns a
+/// ReturnType object.
+#define AST_MATCHER_FUNCTION(ReturnType, DefineMatcher)                        \
+  inline ReturnType DefineMatcher##_getInstance();                             \
+  inline ReturnType DefineMatcher() {                                          \
+    return internal::MemoizedMatcher<                                          \
+        ReturnType, DefineMatcher##_getInstance>::getInstance();               \
+  }                                                                            \
+  inline ReturnType DefineMatcher##_getInstance()
+
 /// \brief AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) {
 /// defines a single-parameter function named DefineMatcher() that returns a
 /// ReturnType object.