[clang] Revert "Reland: [clang][test] add testing for the AST matcher reference" (PR #116477)
Julian Schmidt via cfe-commits
cfe-commits at lists.llvm.org
Fri Nov 15 22:34:15 PST 2024
https://github.com/5chmidti created https://github.com/llvm/llvm-project/pull/116477
Reverts llvm/llvm-project#112168
>From 2f82f958126dbe55e580db8c65e087c054564ed6 Mon Sep 17 00:00:00 2001
From: Julian Schmidt <schmidt.julian99 at gmail.com>
Date: Sat, 16 Nov 2024 07:33:59 +0100
Subject: [PATCH] =?UTF-8?q?Revert=20"Reland:=20[clang][test]=20add=20testi?=
=?UTF-8?q?ng=20for=20the=20AST=20matcher=20reference=20(#112=E2=80=A6"?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This reverts commit 53e92e48d0c03a2475e8517dd4c28968d84fc217.
---
clang/docs/LibASTMatchersReference.html | 7947 +++++------------
clang/docs/ReleaseNotes.rst | 3 -
clang/docs/doxygen.cfg.in | 9 +-
clang/docs/tools/dump_ast_matchers.py | 68 +-
clang/include/clang/ASTMatchers/ASTMatchers.h | 5777 ++++--------
clang/unittests/ASTMatchers/ASTMatchersTest.h | 430 +-
clang/unittests/ASTMatchers/CMakeLists.txt | 15 -
clang/utils/generate_ast_matcher_doc_tests.py | 1097 ---
8 files changed, 3941 insertions(+), 11405 deletions(-)
delete mode 100755 clang/utils/generate_ast_matcher_doc_tests.py
diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html
index 99917ccff52604..c6307954d7f1bb 100644
--- a/clang/docs/LibASTMatchersReference.html
+++ b/clang/docs/LibASTMatchersReference.html
@@ -586,36 +586,28 @@ <h2 id="decl-matchers">Node Matchers</h2>
#pragma omp declare simd
int min();
-
-The matcher attr()
-matches nodiscard, nonnull, noinline, and
-declare simd.
+attr()
+ matches "nodiscard", "nonnull", "noinline", and the whole "#pragma" line.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>></td><td class="name" onclick="toggle('cxxBaseSpecifier0')"><a name="cxxBaseSpecifier0Anchor">cxxBaseSpecifier</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="cxxBaseSpecifier0"><pre>Matches class bases.
-Given
+Examples matches public virtual B.
class B {};
class C : public virtual B {};
-
-The matcher cxxRecordDecl(hasDirectBase(cxxBaseSpecifier()))
-matches C.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>></td><td class="name" onclick="toggle('cxxCtorInitializer0')"><a name="cxxCtorInitializer0Anchor">cxxCtorInitializer</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="cxxCtorInitializer0"><pre>Matches constructor initializers.
-Given
+Examples matches i(42).
class C {
C() : i(42) {}
int i;
};
-
-The matcher cxxCtorInitializer()
-matches i(42).
</pre></td></tr>
@@ -627,22 +619,17 @@ <h2 id="decl-matchers">Node Matchers</h2>
public:
int a;
};
-
-The matcher accessSpecDecl()
-matches public:.
+accessSpecDecl()
+ matches 'public:'
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('bindingDecl0')"><a name="bindingDecl0Anchor">bindingDecl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BindingDecl.html">BindingDecl</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="bindingDecl0"><pre>Matches binding declarations
+Example matches foo and bar
+(matcher = bindingDecl()
-Given
- struct pair { int x; int y; };
- pair make(int, int);
- auto [foo, bar] = make(42, 42);
-
-The matcher bindingDecl()
-matches foo and bar.
+ auto [foo, bar] = std::make_pair{42, 42};
</pre></td></tr>
@@ -655,18 +642,14 @@ <h2 id="decl-matchers">Node Matchers</h2>
myFunc(^(int p) {
printf("%d", p);
})
-
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('classTemplateDecl0')"><a name="classTemplateDecl0Anchor">classTemplateDecl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ClassTemplateDecl.html">ClassTemplateDecl</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="classTemplateDecl0"><pre>Matches C++ class template declarations.
-Given
+Example matches Z
template<class T> class Z {};
-
-The matcher classTemplateDecl()
-matches Z.
</pre></td></tr>
@@ -677,14 +660,13 @@ <h2 id="decl-matchers">Node Matchers</h2>
template<class T1, class T2, int I>
class A {};
- template<class T, int I> class A<T, T*, I> {};
+ template<class T, int I>
+ class A<T, T*, I> {};
template<>
class A<int, int, 1> {};
-
-The matcher classTemplatePartialSpecializationDecl()
-matches template<class T, int I> class A<T, T*, I> {},
-but does not match A<int, int, 1>.
+classTemplatePartialSpecializationDecl()
+ matches the specialization A<T,T*,I> but not A<int,int,1>
</pre></td></tr>
@@ -695,128 +677,87 @@ <h2 id="decl-matchers">Node Matchers</h2>
template<typename T> class A {};
template<> class A<double> {};
A<int> a;
-
-The matcher classTemplateSpecializationDecl()
-matches class A<int>
-and class A<double>.
+classTemplateSpecializationDecl()
+ matches the specializations A<int> and A<double>
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('conceptDecl0')"><a name="conceptDecl0Anchor">conceptDecl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ConceptDecl.html">ConceptDecl</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="conceptDecl0"><pre>Matches concept declarations.
-Given
- template<typename T> concept my_concept = true;
-
-
-The matcher conceptDecl()
-matches template<typename T>
-concept my_concept = true.
+Example matches integral
+ template<typename T>
+ concept integral = std::is_integral_v<T>;
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('cxxConstructorDecl0')"><a name="cxxConstructorDecl0Anchor">cxxConstructorDecl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html">CXXConstructorDecl</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="cxxConstructorDecl0"><pre>Matches C++ constructor declarations.
-Given
+Example matches Foo::Foo() and Foo::Foo(int)
class Foo {
public:
Foo();
Foo(int);
int DoSomething();
};
-
- struct Bar {};
-
-
-The matcher cxxConstructorDecl()
-matches Foo() and Foo(int).
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('cxxConversionDecl0')"><a name="cxxConversionDecl0Anchor">cxxConversionDecl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConversionDecl.html">CXXConversionDecl</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="cxxConversionDecl0"><pre>Matches conversion operator declarations.
-Given
+Example matches the operator.
class X { operator int() const; };
-
-
-The matcher cxxConversionDecl()
-matches operator int() const.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('cxxDeductionGuideDecl0')"><a name="cxxDeductionGuideDecl0Anchor">cxxDeductionGuideDecl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXDeductionGuideDecl.html">CXXDeductionGuideDecl</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="cxxDeductionGuideDecl0"><pre>Matches user-defined and implicitly generated deduction guide.
-Given
+Example matches the deduction guide.
template<typename T>
- class X { X(int); };
+ class X { X(int) };
X(int) -> X<int>;
-
-
-The matcher cxxDeductionGuideDecl()
-matches the written deduction guide
-auto (int) -> X<int>,
-the implicit copy deduction guide auto (int) -> X<T>
-and the implicitly declared deduction guide
-auto (X<T>) -> X<T>.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('cxxDestructorDecl0')"><a name="cxxDestructorDecl0Anchor">cxxDestructorDecl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXDestructorDecl.html">CXXDestructorDecl</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="cxxDestructorDecl0"><pre>Matches explicit C++ destructor declarations.
-Given
+Example matches Foo::~Foo()
class Foo {
public:
virtual ~Foo();
};
-
- struct Bar {};
-
-
-The matcher cxxDestructorDecl()
-matches virtual ~Foo().
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('cxxMethodDecl0')"><a name="cxxMethodDecl0Anchor">cxxMethodDecl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="cxxMethodDecl0"><pre>Matches method declarations.
-Given
+Example matches y
class X { void y(); };
-
-
-The matcher cxxMethodDecl()
-matches void y().
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('cxxRecordDecl0')"><a name="cxxRecordDecl0Anchor">cxxRecordDecl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="cxxRecordDecl0"><pre>Matches C++ class declarations.
-Given
+Example matches X, Z
class X;
template<class T> class Z {};
-
-The matcher cxxRecordDecl()
-matches X and Z.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('decl0')"><a name="decl0Anchor">decl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="decl0"><pre>Matches declarations.
-Given
+Examples matches X, C, and the friend declaration inside C;
void X();
class C {
- friend void X();
+ friend X;
};
-
-The matcher decl()
-matches void X(), C
-and friend void X().
</pre></td></tr>
@@ -826,49 +767,40 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
class X { int y; };
-
-The matcher declaratorDecl()
-matches int y.
+declaratorDecl()
+ matches int y.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('decompositionDecl0')"><a name="decompositionDecl0Anchor">decompositionDecl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DecompositionDecl.html">DecompositionDecl</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="decompositionDecl0"><pre>Matches decomposition-declarations.
-Given
- struct pair { int x; int y; };
- pair make(int, int);
- int number = 42;
- auto [foo, bar] = make(42, 42);
+Examples matches the declaration node with foo and bar, but not
+number.
+(matcher = declStmt(has(decompositionDecl())))
-The matcher decompositionDecl()
-matches auto [foo, bar] = make(42, 42),
-but does not match number.
+ int number = 42;
+ auto [foo, bar] = std::make_pair{42, 42};
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('enumConstantDecl0')"><a name="enumConstantDecl0Anchor">enumConstantDecl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1EnumConstantDecl.html">EnumConstantDecl</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="enumConstantDecl0"><pre>Matches enum constants.
-Given
+Example matches A, B, C
enum X {
A, B, C
};
-The matcher enumConstantDecl()
-matches A, B and C.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('enumDecl0')"><a name="enumDecl0Anchor">enumDecl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1EnumDecl.html">EnumDecl</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="enumDecl0"><pre>Matches enum declarations.
-Given
+Example matches X
enum X {
A, B, C
};
-
-The matcher enumDecl()
-matches the enum X.
</pre></td></tr>
@@ -876,14 +808,9 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="fieldDecl0"><pre>Matches field declarations.
Given
- int a;
- struct Foo {
- int x;
- };
- void bar(int val);
-
-The matcher fieldDecl()
-matches int x.
+ class X { int m; };
+fieldDecl()
+ matches 'm'.
</pre></td></tr>
@@ -892,20 +819,16 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
class X { friend void foo(); };
-
-The matcher friendDecl()
-matches friend void foo().
+friendDecl()
+ matches 'friend void foo()'.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('functionDecl0')"><a name="functionDecl0Anchor">functionDecl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="functionDecl0"><pre>Matches function declarations.
-Given
+Example matches f
void f();
-
-The matcher functionDecl()
-matches void f().
</pre></td></tr>
@@ -914,10 +837,6 @@ <h2 id="decl-matchers">Node Matchers</h2>
Example matches f
template<class T> void f(T t) {}
-
-
-The matcher functionTemplateDecl()
-matches template<class T> void f(T t) {}.
</pre></td></tr>
@@ -926,8 +845,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
struct X { struct { int a; }; };
-The matcher indirectFieldDecl()
-matches a.
+indirectFieldDecl()
+ matches 'a'.
</pre></td></tr>
@@ -935,13 +854,10 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="labelDecl0"><pre>Matches a declaration of label.
Given
- void bar();
- void foo() {
- goto FOO;
- FOO: bar();
- }
-The matcher labelDecl()
-matches FOO: bar().
+ goto FOO;
+ FOO: bar();
+labelDecl()
+ matches 'FOO:'
</pre></td></tr>
@@ -950,9 +866,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
extern "C" {}
-
-The matcher linkageSpecDecl()
-matches extern "C" {}.
+linkageSpecDecl()
+ matches "extern "C" {}"
</pre></td></tr>
@@ -960,18 +875,12 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="namedDecl0"><pre>Matches a declaration of anything that could have a name.
Example matches X, S, the anonymous union type, i, and U;
-Given
typedef int X;
struct S {
union {
int i;
} U;
};
-The matcher namedDecl()
-matches typedef int X, S, int i
- and U,
-with S matching twice in C++.
-Once for the injected class name and once for the declaration itself.
</pre></td></tr>
@@ -981,10 +890,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
namespace test {}
namespace alias = ::test;
-
-The matcher namespaceAliasDecl()
-matches alias,
-but does not match test.
+namespaceAliasDecl()
+ matches "namespace alias" but not "namespace test"
</pre></td></tr>
@@ -994,9 +901,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
namespace {}
namespace test {}
-
-The matcher namespaceDecl()
-matches namespace {} and namespace test {}.
+namespaceDecl()
+ matches "namespace {}" and "namespace test {}"
</pre></td></tr>
@@ -1005,10 +911,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
template <typename T, int N> struct C {};
-
-The matcher nonTypeTemplateParmDecl()
-matches int N,
-but does not match typename T.
+nonTypeTemplateParmDecl()
+ matches 'N', but not 'T'.
</pre></td></tr>
@@ -1018,7 +922,6 @@ <h2 id="decl-matchers">Node Matchers</h2>
Example matches Foo (Additions)
@interface Foo (Additions)
@end
-
</pre></td></tr>
@@ -1028,7 +931,6 @@ <h2 id="decl-matchers">Node Matchers</h2>
Example matches Foo (Additions)
@implementation Foo (Additions)
@end
-
</pre></td></tr>
@@ -1038,7 +940,6 @@ <h2 id="decl-matchers">Node Matchers</h2>
Example matches Foo
@implementation Foo
@end
-
</pre></td></tr>
@@ -1048,7 +949,6 @@ <h2 id="decl-matchers">Node Matchers</h2>
Example matches Foo
@interface Foo
@end
-
</pre></td></tr>
@@ -1060,7 +960,6 @@ <h2 id="decl-matchers">Node Matchers</h2>
BOOL _enabled;
}
@end
-
</pre></td></tr>
@@ -1075,7 +974,6 @@ <h2 id="decl-matchers">Node Matchers</h2>
@implementation Foo
- (void)method {}
@end
-
</pre></td></tr>
@@ -1086,7 +984,6 @@ <h2 id="decl-matchers">Node Matchers</h2>
@interface Foo
@property BOOL enabled;
@end
-
</pre></td></tr>
@@ -1096,7 +993,6 @@ <h2 id="decl-matchers">Node Matchers</h2>
Example matches FooDelegate
@protocol FooDelegate
@end
-
</pre></td></tr>
@@ -1105,58 +1001,48 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
void f(int x);
-The matcher parmVarDecl()
-matches int x.
+parmVarDecl()
+ matches int x.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('recordDecl0')"><a name="recordDecl0Anchor">recordDecl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordDecl.html">RecordDecl</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="recordDecl0"><pre>Matches class, struct, and union declarations.
-Given
+Example matches X, Z, U, and S
class X;
template<class T> class Z {};
struct S {};
union U {};
-
-The matcher recordDecl()
-matches X, Z,
-S and U.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('staticAssertDecl0')"><a name="staticAssertDecl0Anchor">staticAssertDecl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1StaticAssertDecl.html">StaticAssertDecl</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="staticAssertDecl0"><pre>Matches a C++ static_assert declaration.
-Given
+Example:
+ staticAssertDecl()
+matches
+ static_assert(sizeof(S) == sizeof(int))
+in
struct S {
int x;
};
static_assert(sizeof(S) == sizeof(int));
-
-
-The matcher staticAssertDecl()
-matches static_assert(sizeof(S) == sizeof(int)).
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('tagDecl0')"><a name="tagDecl0Anchor">tagDecl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="tagDecl0"><pre>Matches tag declarations.
-Given
+Example matches X, Z, U, S, E
class X;
template<class T> class Z {};
struct S {};
union U {};
- enum E { A, B, C };
-
-
-The matcher tagDecl()
-matches class X, class Z {}, the injected class name
-class Z, struct S {},
-the injected class name struct S, union U {},
-the injected class name union U
-and enum E { A, B, C }.
+ enum E {
+ A, B, C
+ };
</pre></td></tr>
@@ -1165,10 +1051,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
template <template <typename> class Z, int N> struct C {};
-
-The matcher templateTemplateParmDecl()
-matches template <typename> class Z,
-but does not match int N.
+templateTypeParmDecl()
+ matches 'Z', but not 'N'.
</pre></td></tr>
@@ -1177,10 +1061,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
template <typename T, int N> struct C {};
-
-The matcher templateTypeParmDecl()
-matches typename T,
-but does not int N.
+templateTypeParmDecl()
+ matches 'T', but not 'N'.
</pre></td></tr>
@@ -1190,12 +1072,10 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
int X;
namespace NS {
- int Y;
+ int Y;
} // namespace NS
-
-The matcher namedDecl(hasDeclContext(translationUnitDecl()))
-matches X and NS,
-but does not match Y.
+decl(hasDeclContext(translationUnitDecl()))
+ matches "int X", but not "int Y".
</pre></td></tr>
@@ -1205,22 +1085,17 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
typedef int X;
using Y = int;
-
-The matcher typeAliasDecl()
-matches using Y = int,
-but does not match typedef int X.
+typeAliasDecl()
+ matches "using Y = int", but not "typedef int X"
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('typeAliasTemplateDecl0')"><a name="typeAliasTemplateDecl0Anchor">typeAliasTemplateDecl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeAliasTemplateDecl.html">TypeAliasTemplateDecl</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="typeAliasTemplateDecl0"><pre>Matches type alias template declarations.
-Given
- template <typename T> struct X {};
- template <typename T> using Y = X<T>;
-
-The matcher typeAliasTemplateDecl()
-matches template <typename T> using Y = X<T>.
+typeAliasTemplateDecl() matches
+ template <typename T>
+ using Y = X<T>;
</pre></td></tr>
@@ -1230,10 +1105,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
typedef int X;
using Y = int;
-
-The matcher typedefDecl()
-matches typedef int X,
-but does not match using Y = int.
+typedefDecl()
+ matches "typedef int X", but not "using Y = int"
</pre></td></tr>
@@ -1243,9 +1116,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
typedef int X;
using Y = int;
-
-The matcher typedefNameDecl()
-matches typedef int X and using Y = int.
+typedefNameDecl()
+ matches "typedef int X" and "using Y = int"
</pre></td></tr>
@@ -1261,10 +1133,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
struct S : private Base<T> {
using typename Base<T>::Foo;
};
-
-The matcher unresolvedUsingTypenameDecl()
- matches using typename Base<T>::Foo
-</pre></td></tr>
+unresolvedUsingTypenameDecl()
+ matches using Base<T>::Foo </pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('unresolvedUsingValueDecl0')"><a name="unresolvedUsingValueDecl0Anchor">unresolvedUsingValueDecl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingValueDecl.html">UnresolvedUsingValueDecl</a>>...</td></tr>
@@ -1275,10 +1145,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
class C : private X {
using X::x;
};
-
-The matcher unresolvedUsingValueDecl()
- matches using X::x
-</pre></td></tr>
+unresolvedUsingValueDecl()
+ matches using X::x </pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('usingDecl0')"><a name="usingDecl0Anchor">usingDecl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1UsingDecl.html">UsingDecl</a>>...</td></tr>
@@ -1287,10 +1155,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
namespace X { int x; }
using X::x;
-
-The matcher usingDecl()
- matches using X::x
-</pre></td></tr>
+usingDecl()
+ matches using X::x </pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('usingDirectiveDecl0')"><a name="usingDirectiveDecl0Anchor">usingDirectiveDecl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1UsingDirectiveDecl.html">UsingDirectiveDecl</a>>...</td></tr>
@@ -1299,34 +1165,26 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
namespace X { int x; }
using namespace X;
-
-The matcher usingDirectiveDecl()
- matches using namespace X
-</pre></td></tr>
+usingDirectiveDecl()
+ matches using namespace X </pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('usingEnumDecl0')"><a name="usingEnumDecl0Anchor">usingEnumDecl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1UsingEnumDecl.html">UsingEnumDecl</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="usingEnumDecl0"><pre>Matches using-enum declarations.
Given
- namespace X { enum x { val1, val2 }; }
+ namespace X { enum x {...}; }
using enum X::x;
-
-The matcher usingEnumDecl()
- matches using enum X::x
-</pre></td></tr>
+usingEnumDecl()
+ matches using enum X::x </pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('valueDecl0')"><a name="valueDecl0Anchor">valueDecl</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="valueDecl0"><pre>Matches any value declaration.
-Given
+Example matches A, B, C and F
enum X { A, B, C };
void F();
- int V = 0;
-The matcher valueDecl()
-matches A, B, C, void F()
-and int V = 0.
</pre></td></tr>
@@ -1338,13 +1196,6 @@ <h2 id="decl-matchers">Node Matchers</h2>
Example matches a
int a;
- struct Foo {
- int x;
- };
- void bar(int val);
-
-The matcher varDecl()
-matches int a and int val, but not int x.
</pre></td></tr>
@@ -1357,29 +1208,13 @@ <h2 id="decl-matchers">Node Matchers</h2>
auto f = [x](){};
auto g = [x = 1](){};
}
-
-The matcher
-lambdaExpr(hasAnyCapture(lambdaCapture().bind("capture"))),
-matches [x](){} and [x = 1](){},
-with lambdaCapture() matching
-x and x = 1.
+In the matcher `lambdaExpr(hasAnyCapture(lambdaCapture()))`,
+`lambdaCapture()` matches `x` and `x=1`.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>></td><td class="name" onclick="toggle('nestedNameSpecifierLoc0')"><a name="nestedNameSpecifierLoc0Anchor">nestedNameSpecifierLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="nestedNameSpecifierLoc0"><pre>Same as nestedNameSpecifier but matches NestedNameSpecifierLoc.
-
-Given
- namespace ns {
- struct A { static void f(); };
- void A::f() {}
- void g() { A::f(); }
- }
- ns::A a;
-
-
-The matcher nestedNameSpecifierLoc() matches
-A:: twice, and ns:: once.
</pre></td></tr>
@@ -1393,9 +1228,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
void g() { A::f(); }
}
ns::A a;
-
-The matcher nestedNameSpecifier()
-matches ns and both A
+nestedNameSpecifier()
+ matches "ns::" and both "A::"
</pre></td></tr>
@@ -1403,38 +1237,20 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="ompDefaultClause0"><pre>Matches OpenMP ``default`` clause.
Given
- void foo() {
- #pragma omp parallel default(none)
- ;
- #pragma omp parallel default(shared)
- ;
- #pragma omp parallel default(private)
- ;
- #pragma omp parallel default(firstprivate)
- ;
- #pragma omp parallel
- ;
- }
+ #pragma omp parallel default(none)
+ #pragma omp parallel default(shared)
+ #pragma omp parallel default(private)
+ #pragma omp parallel default(firstprivate)
+ #pragma omp parallel
-The matcher
-ompExecutableDirective(hasAnyClause(ompDefaultClause())) matches
-#pragma omp parallel default(none),
-#pragma omp parallel default(shared),
-#pragma omp parallel default(private) and
-#pragma omp parallel default(firstprivate).
+``ompDefaultClause()`` matches ``default(none)``, ``default(shared)``,
+`` default(private)`` and ``default(firstprivate)``
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>></td><td class="name" onclick="toggle('qualType0')"><a name="qualType0Anchor">qualType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="qualType0"><pre>Matches QualTypes in the clang AST.
-
-Given
- int a = 0;
- const int b = 1;
-
-The matcher varDecl(hasType(qualType(isConstQualified())))
-matches const int b = 1, but not int a = 0.
</pre></td></tr>
@@ -1442,39 +1258,34 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="addrLabelExpr0"><pre>Matches address of label statements (GNU extension).
Given
-void bar();
-void foo() {
FOO: bar();
void *ptr = &&FOO;
- goto *ptr;
-}
-The matcher addrLabelExpr()
-matches &&FOO
+ goto *bar;
+addrLabelExpr()
+ matches '&&FOO'
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('arrayInitIndexExpr0')"><a name="arrayInitIndexExpr0Anchor">arrayInitIndexExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ArrayInitIndexExpr.html">ArrayInitIndexExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="arrayInitIndexExpr0"><pre>The arrayInitIndexExpr consists of two subexpressions: a common expression
-(the source array) that is evaluated once up-front, and a per-element
-initializer that runs once for each array element. Within the per-element
-initializer, the current index may be obtained via an ArrayInitIndexExpr.
+(the source array) that is evaluated once up-front, and a per-element initializer
+that runs once for each array element. Within the per-element initializer,
+the current index may be obtained via an ArrayInitIndexExpr.
Given
- void testStructuredBinding() {
+ void testStructBinding() {
int a[2] = {1, 2};
auto [x, y] = a;
}
-
-
-The matcher arrayInitIndexExpr() matches the array index
-that implicitly iterates over the array `a` to copy each element to the
-anonymous array that backs the structured binding.
+arrayInitIndexExpr() matches the array index that implicitly iterates
+over the array `a` to copy each element to the anonymous array
+that backs the structured binding `[x, y]` elements of which are
+referred to by their aliases `x` and `y`.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('arrayInitLoopExpr0')"><a name="arrayInitLoopExpr0Anchor">arrayInitLoopExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ArrayInitLoopExpr.html">ArrayInitLoopExpr</a>>...</td></tr>
-<tr><td colspan="4" class="doc" id="arrayInitLoopExpr0"><pre>Matches a loop initializing the elements of an array in a number of
-contexts:
+<tr><td colspan="4" class="doc" id="arrayInitLoopExpr0"><pre>Matches a loop initializing the elements of an array in a number of contexts:
* in the implicit copy/move constructor for a class with an array member
* when a lambda-expression captures an array by value
* when a decomposition declaration decomposes an array
@@ -1482,12 +1293,13 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
void testLambdaCapture() {
int a[10];
- [a]() {};
+ auto Lam1 = [a]() {
+ return;
+ };
}
-
-The matcher arrayInitLoopExpr() matches the implicit loop that
-initializes each element of the implicit array field inside the lambda
-object, that represents the array a captured by value.
+arrayInitLoopExpr() matches the implicit loop that initializes each element of
+the implicit array field inside the lambda object, that represents the array `a`
+captured by value.
</pre></td></tr>
@@ -1495,34 +1307,26 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="arraySubscriptExpr0"><pre>Matches array subscript expressions.
Given
- void foo() {
- int a[2] = {0, 1};
- int i = a[1];
- }
-The matcher arraySubscriptExpr()
-matches a[1].
+ int i = a[1];
+arraySubscriptExpr()
+ matches "a[1]"
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('asmStmt0')"><a name="asmStmt0Anchor">asmStmt</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AsmStmt.html">AsmStmt</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="asmStmt0"><pre>Matches asm statements.
-void foo() {
int i = 100;
- __asm("mov %al, 2");
-}
-The matcher asmStmt()
-matches __asm("mov %al, 2")
+ __asm("mov al, 2");
+asmStmt()
+ matches '__asm("mov al, 2")'
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('atomicExpr0')"><a name="atomicExpr0Anchor">atomicExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AtomicExpr.html">AtomicExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="atomicExpr0"><pre>Matches atomic builtins.
-
-Given
+Example matches __atomic_load_n(ptr, 1)
void foo() { int *ptr; __atomic_load_n(ptr, 1); }
-
-The matcher atomicExpr() matches __atomic_load_n(ptr, 1).
</pre></td></tr>
@@ -1533,35 +1337,24 @@ <h2 id="decl-matchers">Node Matchers</h2>
@autoreleasepool {
int x = 0;
}
-
-The matcher autoreleasePoolStmt(stmt()) matches the declaration of
-int x = 0 inside the autorelease pool.
+autoreleasePoolStmt(stmt()) matches the declaration of "x"
+inside the autorelease pool.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('binaryConditionalOperator0')"><a name="binaryConditionalOperator0Anchor">binaryConditionalOperator</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryConditionalOperator.html">BinaryConditionalOperator</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="binaryConditionalOperator0"><pre>Matches binary conditional operator expressions (GNU extension).
-Given
- int f(int a, int b) {
- return (a ?: b) + 42;
- }
-
-The matcher binaryConditionalOperator() matches a ?: b.
+Example matches a ?: b
+ (a ?: b) + 42;
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('binaryOperator0')"><a name="binaryOperator0Anchor">binaryOperator</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="binaryOperator0"><pre>Matches binary operator expressions.
-Given
- void foo(bool a, bool b) {
- !(a || b);
- }
-
-
-The matcher binaryOperator() matches a || b.
-
+Example matches a || b
+ !(a || b)
See also the binaryOperation() matcher for more-general matching.
</pre></td></tr>
@@ -1569,11 +1362,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('blockExpr0')"><a name="blockExpr0Anchor">blockExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockExpr.html">BlockExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="blockExpr0"><pre>Matches a reference to a block.
-Given
+Example: matches "^{}":
void f() { ^{}(); }
-
-
-The matcher blockExpr() matches ^{}.
</pre></td></tr>
@@ -1581,23 +1371,17 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="breakStmt0"><pre>Matches break statements.
Given
-void foo() {
while (true) { break; }
-}
-
-The matcher breakStmt()
-matches break
+breakStmt()
+ matches 'break'
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('cStyleCastExpr0')"><a name="cStyleCastExpr0Anchor">cStyleCastExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CStyleCastExpr.html">CStyleCastExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="cStyleCastExpr0"><pre>Matches a C-style cast expression.
-Given
+Example: Matches (int) 2.2f in
int i = (int) 2.2f;
-
-The matcher cStyleCastExpr()
-matches (int) 2.2f.
</pre></td></tr>
@@ -1605,16 +1389,9 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="callExpr0"><pre>Matches call expressions.
Example matches x.y() and y()
- struct X { void foo(); };
- void bar();
- void foobar() {
- X x;
- x.foo();
- bar();
- }
-
-The matcher callExpr()
-matches x.foo() and bar();
+ X x;
+ x.y();
+ y();
</pre></td></tr>
@@ -1622,41 +1399,22 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="caseStmt0"><pre>Matches case statements inside switch statements.
Given
-void foo(int a) {
switch(a) { case 42: break; default: break; }
-}
-The matcher caseStmt()
-matches case 42: break.
+caseStmt()
+ matches 'case 42:'.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('castExpr0')"><a name="castExpr0Anchor">castExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CastExpr.html">CastExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="castExpr0"><pre>Matches any cast nodes of Clang's AST.
-Given
- struct S {};
- const S* s;
- S* s2 = const_cast<S*>(s);
-
- const int val = 0;
- char val0 = 1;
- char val1 = (char)2;
- char val2 = static_cast<char>(3);
- int* val3 = reinterpret_cast<int*>(4);
- char val4 = char(5);
-
-
-The matcher castExpr()
-matches
-const_cast<S*>(s) and the implicit l- to r-value cast for s,
-the implicit cast to char for the initializer 1,
-the c-style cast (char)2 and it's implicit cast to char
-(part of the c-style cast) 2,
-static_cast<char>(3) and it's implicit cast to char
-(part of the static_cast) 3,
-reinterpret_cast<int*>(4),
-char(5) and it's implicit cast to char
-(part of the functional cast) 5.
+Example: castExpr() matches each of the following:
+ (int) 3;
+ const_cast<Expr *>(SubExpr);
+ char c = 0;
+but does not match
+ int i = (0);
+ int k = 0;
</pre></td></tr>
@@ -1666,24 +1424,14 @@ <h2 id="decl-matchers">Node Matchers</h2>
Not matching Hex-encoded chars (e.g. 0x1234, which is a IntegerLiteral),
though.
-Given
+Example matches 'a', L'a'
char ch = 'a';
wchar_t chw = L'a';
-
-
-The matcher characterLiteral() matches 'a' and
-L'a'.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('chooseExpr0')"><a name="chooseExpr0Anchor">chooseExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ChooseExpr.html">ChooseExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="chooseExpr0"><pre>Matches GNU __builtin_choose_expr.
-
-Given
- void f() { (void)__builtin_choose_expr(1, 2, 3); }
-
-The matcher chooseExpr() matches
-__builtin_choose_expr(1, 2, 3).
</pre></td></tr>
@@ -1691,45 +1439,9 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="coawaitExpr0"><pre>Matches co_await expressions.
Given
- namespace std {
- template <typename T = void>
- struct coroutine_handle {
- static constexpr coroutine_handle from_address(void* addr) {
- return {};
- }
- };
-
- struct always_suspend {
- bool await_ready() const noexcept;
- bool await_resume() const noexcept;
- template <typename T>
- bool await_suspend(coroutine_handle<T>) const noexcept;
- };
-
- template <typename T>
- struct coroutine_traits {
- using promise_type = T::promise_type;
- };
- } // namespace std
-
- struct generator {
- struct promise_type {
- std::always_suspend yield_value(int&&);
- std::always_suspend initial_suspend() const noexcept;
- std::always_suspend final_suspend() const noexcept;
- void return_void();
- void unhandled_exception();
- generator get_return_object();
- };
- };
-
- std::always_suspend h();
-
- generator g() { co_await h(); }
-
-The matcher
-coawaitExpr(has(callExpr(callee(functionDecl(hasName("h"))))))
-matches co_await h().
+ co_await 1;
+coawaitExpr()
+ matches 'co_await 1'
</pre></td></tr>
@@ -1737,48 +1449,35 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="compoundLiteralExpr0"><pre>Matches compound (i.e. non-scalar) literals
Example match: {1}, (1, 2)
- struct vector { int x; int y; };
- struct vector myvec = (struct vector){ 1, 2 };
-
-The matcher compoundLiteralExpr()
-matches (struct vector){ 1, 2 }.
+ int array[4] = {1};
+ vector int myvec = (vector int)(1, 2);
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('compoundStmt0')"><a name="compoundStmt0Anchor">compoundStmt</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundStmt.html">CompoundStmt</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="compoundStmt0"><pre>Matches compound statements.
-Given
-void foo() { for (;;) {{}} }
-
-The matcher compoundStmt() matches
-{ for (;;) {{}} }, {{}} and {}.
+Example matches '{}' and '{{}}' in 'for (;;) {{}}'
+ for (;;) {{}}
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('conditionalOperator0')"><a name="conditionalOperator0Anchor">conditionalOperator</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ConditionalOperator.html">ConditionalOperator</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="conditionalOperator0"><pre>Matches conditional operator expressions.
-Given
- int f(int a, int b, int c) {
- return (a ? b : c) + 42;
- }
-
-The matcher conditionalOperator() matches a ? b : c.
+Example matches a ? b : c
+ (a ? b : c) + 42
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('constantExpr0')"><a name="constantExpr0Anchor">constantExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ConstantExpr.html">ConstantExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="constantExpr0"><pre>Matches a constant expression wrapper.
-Given
- void f(int a) {
- switch (a) {
- case 37: break;
- }
+Example matches the constant in the case statement:
+ (matcher = constantExpr())
+ switch (a) {
+ case 37: break;
}
-
-The matcher constantExpr() matches 37.
</pre></td></tr>
@@ -1786,26 +1485,14 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="continueStmt0"><pre>Matches continue statements.
Given
-void foo() {
while (true) { continue; }
-}
-
-The matcher continueStmt()
-matches continue
+continueStmt()
+ matches 'continue'
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('convertVectorExpr0')"><a name="convertVectorExpr0Anchor">convertVectorExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ConvertVectorExpr.html">ConvertVectorExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="convertVectorExpr0"><pre>Matches builtin function __builtin_convertvector.
-
-Given
- typedef double vector4double __attribute__((__vector_size__(32)));
- typedef float vector4float __attribute__((__vector_size__(16)));
- vector4float vf;
- void f() { (void)__builtin_convertvector(vf, vector4double); }
-
-The matcher convertVectorExpr() matches
-__builtin_convertvector(vf, vector4double).
</pre></td></tr>
@@ -1813,85 +1500,19 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="coreturnStmt0"><pre>Matches co_return statements.
Given
- namespace std {
- template <typename T = void>
- struct coroutine_handle {
- static constexpr coroutine_handle from_address(void* addr) {
- return {};
- }
- };
-
- struct always_suspend {
- bool await_ready() const noexcept;
- bool await_resume() const noexcept;
- template <typename T>
- bool await_suspend(coroutine_handle<T>) const noexcept;
- };
-
- template <typename T>
- struct coroutine_traits {
- using promise_type = T::promise_type;
- };
- } // namespace std
-
- struct generator {
- struct promise_type {
- void return_value(int v);
- std::always_suspend yield_value(int&&);
- std::always_suspend initial_suspend() const noexcept;
- std::always_suspend final_suspend() const noexcept;
- void unhandled_exception();
- generator get_return_object();
- };
- };
-
- generator f() {
- co_return 10;
- }
-
-
-The matcher coreturnStmt(has(integerLiteral()))
-matches co_return 10
+ while (true) { co_return; }
+coreturnStmt()
+ matches 'co_return'
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('coroutineBodyStmt0')"><a name="coroutineBodyStmt0Anchor">coroutineBodyStmt</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CoroutineBodyStmt.html">CoroutineBodyStmt</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="coroutineBodyStmt0"><pre>Matches coroutine body statements.
-Given
- namespace std {
- template <typename T = void>
- struct coroutine_handle {
- static constexpr coroutine_handle from_address(void* addr) {
- return {};
- }
- };
-
- struct suspend_always {
- bool await_ready() const noexcept;
- bool await_resume() const noexcept;
- template <typename T>
- bool await_suspend(coroutine_handle<T>) const noexcept;
- };
-
- template <typename...>
- struct coroutine_traits {
- struct promise_type {
- std::suspend_always initial_suspend() const noexcept;
- std::suspend_always final_suspend() const noexcept;
- void return_void();
- void unhandled_exception();
- coroutine_traits get_return_object();
- };
- };
- } // namespace std
-
- void f() { while (true) { co_return; } }
-
-
-
-The matcher coroutineBodyStmt() matches
-{ while (true) { co_return; } }.
+coroutineBodyStmt() matches the coroutine below
+ generator<int> gen() {
+ co_return;
+ }
</pre></td></tr>
@@ -1899,77 +1520,27 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="coyieldExpr0"><pre>Matches co_yield expressions.
Given
- namespace std {
- template <typename T = void>
- struct coroutine_handle {
- static constexpr coroutine_handle from_address(void* addr) {
- return {};
- }
- };
-
- struct always_suspend {
- bool await_ready() const noexcept;
- bool await_resume() const noexcept;
- template <typename T>
- bool await_suspend(coroutine_handle<T>) const noexcept;
- };
-
- template <typename T>
- struct coroutine_traits {
- using promise_type = T::promise_type;
- };
- } // namespace std
-
- struct generator {
- struct promise_type {
- std::always_suspend yield_value(int&&);
- std::always_suspend initial_suspend() const noexcept;
- std::always_suspend final_suspend() const noexcept;
- void return_void();
- void unhandled_exception();
- generator get_return_object();
- };
- };
-
- generator f() {
- while (true) {
- co_yield 10;
- }
- }
-
-The matcher coyieldExpr()
-matches co_yield 10
+ co_yield 1;
+coyieldExpr()
+ matches 'co_yield 1'
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('cudaKernelCallExpr0')"><a name="cudaKernelCallExpr0Anchor">cudaKernelCallExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CUDAKernelCallExpr.html">CUDAKernelCallExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="cudaKernelCallExpr0"><pre>Matches CUDA kernel call expression.
-Given
- __global__ void kernel() {}
- void f() {
- kernel<<<32,32>>>();
- }
-
-The matcher cudaKernelCallExpr()
-matches kernel<<<i, k>>>()
+Example matches,
+ kernel<<<i,j>>>();
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('cxxBindTemporaryExpr0')"><a name="cxxBindTemporaryExpr0Anchor">cxxBindTemporaryExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBindTemporaryExpr.html">CXXBindTemporaryExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="cxxBindTemporaryExpr0"><pre>Matches nodes where temporaries are created.
-Given
- struct S {
- S() { } // User defined constructor makes S non-POD.
- ~S() { } // User defined destructor makes it non-trivial.
- };
- void test() {
- const S &s_ref = S(); // Requires a CXXBindTemporaryExpr.
- }
-
-The matcher cxxBindTemporaryExpr()
-matches the constructor call S().
+Example matches FunctionTakesString(GetStringByValue())
+ (matcher = cxxBindTemporaryExpr())
+ FunctionTakesString(GetStringByValue());
+ FunctionTakesStringByPointer(GetStringPointer());
</pre></td></tr>
@@ -1977,71 +1548,49 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="cxxBoolLiteral0"><pre>Matches bool literals.
Example matches true
- bool Flag = true;
-
-
-The matcher cxxBoolLiteral() matches true.
+ true
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('cxxCatchStmt0')"><a name="cxxCatchStmt0Anchor">cxxCatchStmt</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCatchStmt.html">CXXCatchStmt</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="cxxCatchStmt0"><pre>Matches catch statements.
-void foo() {
try {} catch(int i) {}
-}
-
-The matcher cxxCatchStmt()
-matches catch(int i) {}
+cxxCatchStmt()
+ matches 'catch(int i)'
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('cxxConstCastExpr0')"><a name="cxxConstCastExpr0Anchor">cxxConstCastExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstCastExpr.html">CXXConstCastExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="cxxConstCastExpr0"><pre>Matches a const_cast expression.
-Given
+Example: Matches const_cast<int*>(&r) in
int n = 42;
const int &r(n);
int* p = const_cast<int*>(&r);
-
-
-The matcher cxxConstCastExpr()
-matches const_cast<int*>(&r).
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('cxxConstructExpr0')"><a name="cxxConstructExpr0Anchor">cxxConstructExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="cxxConstructExpr0"><pre>Matches constructor call expressions (including implicit ones).
-Given
- struct string {
- string(const char*);
- string(const char*s, int n);
- };
+Example matches string(ptr, n) and ptr within arguments of f
+ (matcher = cxxConstructExpr())
void f(const string &a, const string &b);
- void foo(char *ptr, int n) {
- f(string(ptr, n), ptr);
- }
-
-
-The matcher cxxConstructExpr() matches string(ptr, n)
-and ptr within arguments of f .
+ char *ptr;
+ int n;
+ f(string(ptr, n), ptr);
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('cxxDefaultArgExpr0')"><a name="cxxDefaultArgExpr0Anchor">cxxDefaultArgExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXDefaultArgExpr.html">CXXDefaultArgExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="cxxDefaultArgExpr0"><pre>Matches the value of a default argument at the call site.
-Given
+Example matches the CXXDefaultArgExpr placeholder inserted for the
+ default value of the second parameter in the call expression f(42)
+ (matcher = cxxDefaultArgExpr())
void f(int x, int y = 0);
- void g() {
- f(42);
- }
-
-
-The matcher callExpr(has(cxxDefaultArgExpr()))
-matches the CXXDefaultArgExpr placeholder inserted for the default value
-of the second parameter in the call expression f(42).
+ f(42);
</pre></td></tr>
@@ -2049,17 +1598,9 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="cxxDeleteExpr0"><pre>Matches delete expressions.
Given
- void* operator new(decltype(sizeof(void*)));
- void operator delete(void*);
- struct X {};
- void foo() {
- auto* x = new X;
- delete x;
- }
-
-
-The matcher cxxDeleteExpr()
-matches delete x.
+ delete X;
+cxxDeleteExpr()
+ matches 'delete X'.
</pre></td></tr>
@@ -2069,8 +1610,7 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
template <class T> void f() { T t; t.g(); }
-
-The matcher cxxDependentScopeMemberExpr()
+cxxDependentScopeMemberExpr()
matches t.g
</pre></td></tr>
@@ -2078,83 +1618,53 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('cxxDynamicCastExpr0')"><a name="cxxDynamicCastExpr0Anchor">cxxDynamicCastExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXDynamicCastExpr.html">CXXDynamicCastExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="cxxDynamicCastExpr0"><pre>Matches a dynamic_cast expression.
-Given
+Example:
+ cxxDynamicCastExpr()
+matches
+ dynamic_cast<D*>(&b);
+in
struct B { virtual ~B() {} }; struct D : B {};
B b;
D* p = dynamic_cast<D*>(&b);
-
-
-The matcher cxxDynamicCastExpr()
-matches dynamic_cast<D*>(&b).
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('cxxFoldExpr0')"><a name="cxxFoldExpr0Anchor">cxxFoldExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFoldExpr.html">CXXFoldExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="cxxFoldExpr0"><pre>Matches C++17 fold expressions.
-Given
+Example matches `(0 + ... + args)`:
template <typename... Args>
auto sum(Args... args) {
return (0 + ... + args);
}
-
-
-The matcher cxxFoldExpr() matches (0 + ... + args).
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('cxxForRangeStmt0')"><a name="cxxForRangeStmt0Anchor">cxxForRangeStmt</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXForRangeStmt.html">CXXForRangeStmt</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="cxxForRangeStmt0"><pre>Matches range-based for statements.
-Given
- void foo() {
- int i[] = {1, 2, 3}; for (auto a : i);
- for(int j = 0; j < 5; ++j);
- }
-
-The matcher cxxForRangeStmt()
-matches for (auto a : i);
+cxxForRangeStmt() matches 'for (auto a : i)'
+ int i[] = {1, 2, 3}; for (auto a : i);
+ for(int j = 0; j < 5; ++j);
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('cxxFunctionalCastExpr0')"><a name="cxxFunctionalCastExpr0Anchor">cxxFunctionalCastExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="cxxFunctionalCastExpr0"><pre>Matches functional cast expressions
-Given
- struct Foo {
- Foo(int x);
- };
-
- void foo(int bar) {
- Foo f = bar;
- Foo g = (Foo) bar;
- Foo h = Foo(bar);
- }
-
-
-The matcher cxxFunctionalCastExpr()
-matches Foo(bar).
+Example: Matches Foo(bar);
+ Foo f = bar;
+ Foo g = (Foo) bar;
+ Foo h = Foo(bar);
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('cxxMemberCallExpr0')"><a name="cxxMemberCallExpr0Anchor">cxxMemberCallExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMemberCallExpr.html">CXXMemberCallExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="cxxMemberCallExpr0"><pre>Matches member call expressions.
-Given
- struct X {
- void y();
- void m() { y(); }
- };
- void f();
- void g() {
- X x;
- x.y();
- f();
- }
-
-
-The matcher cxxMemberCallExpr() matches x.y() and
-y(), but not f().
+Example matches x.y()
+ X x;
+ x.y();
</pre></td></tr>
@@ -2162,15 +1672,9 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="cxxNewExpr0"><pre>Matches new expressions.
Given
- void* operator new(decltype(sizeof(void*)));
- struct X {};
- void foo() {
- auto* x = new X;
- }
-
-
-The matcher cxxNewExpr()
-matches new X.
+ new X;
+cxxNewExpr()
+ matches 'new X'.
</pre></td></tr>
@@ -2183,24 +1687,14 @@ <h2 id="decl-matchers">Node Matchers</h2>
bool c() noexcept(false);
bool d() noexcept(noexcept(a()));
bool e = noexcept(b()) || noexcept(c());
-
-The matcher cxxNoexceptExpr()
-matches noexcept(a()), noexcept(b()) and
-noexcept(c()), but does not match the noexcept specifier in the
-declarations a, b, c or d.
+cxxNoexceptExpr()
+ matches `noexcept(a())`, `noexcept(b())` and `noexcept(c())`.
+ doesn't match the noexcept specifier in the declarations a, b, c or d.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('cxxNullPtrLiteralExpr0')"><a name="cxxNullPtrLiteralExpr0Anchor">cxxNullPtrLiteralExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNullPtrLiteralExpr.html">CXXNullPtrLiteralExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="cxxNullPtrLiteralExpr0"><pre>Matches nullptr literal.
-
-Given
- int a = 0;
- int* b = 0;
- int *c = nullptr;
-
-
-The matcher cxxNullPtrLiteralExpr() matches nullptr.
</pre></td></tr>
@@ -2212,16 +1706,11 @@ <h2 id="decl-matchers">Node Matchers</h2>
Currently it does not match operators such as new delete.
FIXME: figure out why these do not match?
-Given
- struct ostream;
+Example matches both operator<<((o << b), c) and operator<<(o, b)
+ (matcher = cxxOperatorCallExpr())
ostream &operator<< (ostream &out, int i) { };
- void f(ostream& o, int b, int c) {
- o << b << c;
- }
-
-
-The matcher cxxOperatorCallExpr() matches o << b << c
-and o << b.
+ ostream &o; int b = 1, c = 1;
+ o << b << c;
See also the binaryOperation() matcher for more-general matching of binary
uses of this AST node.
</pre></td></tr>
@@ -2236,10 +1725,6 @@ <h2 id="decl-matchers">Node Matchers</h2>
Example matches reinterpret_cast<char*>(&p) in
void* p = reinterpret_cast<char*>(&p);
-
-
-The matcher cxxReinterpretCastExpr()
-matches reinterpret_cast<char*>(&p).
</pre></td></tr>
@@ -2247,20 +1732,16 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="cxxRewrittenBinaryOperator0"><pre>Matches rewritten binary operators
Example matches use of "<":
+ #include <compare>
struct HasSpaceshipMem {
int a;
- constexpr bool operator==(const HasSpaceshipMem&) const = default;
+ constexpr auto operator<=>(const HasSpaceshipMem&) const = default;
};
void compare() {
HasSpaceshipMem hs1, hs2;
- if (hs1 != hs2)
+ if (hs1 < hs2)
return;
}
-
-
-The matcher cxxRewrittenBinaryOperator() matches
-hs1 != hs2.
-
See also the binaryOperation() matcher for more-general matching
of this AST node.
</pre></td></tr>
@@ -2272,12 +1753,12 @@ <h2 id="decl-matchers">Node Matchers</h2>
See also: hasDestinationType
See also: reinterpretCast
-Given
+Example:
+ cxxStaticCastExpr()
+matches
+ static_cast<long>(8)
+in
long eight(static_cast<long>(8));
-
-
-The matcher cxxStaticCastExpr()
-matches static_cast<long>(8).
</pre></td></tr>
@@ -2285,110 +1766,69 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="cxxStdInitializerListExpr0"><pre>Matches C++ initializer list expressions.
Given
- namespace std {
- template <typename T>
- class initializer_list {
- const T* begin;
- const T* end;
- };
- }
- template <typename T> class vector {
- public: vector(std::initializer_list<T>) {}
- };
-
- vector<int> a({ 1, 2, 3 });
- vector<int> b = { 4, 5 };
+ std::vector<int> a({ 1, 2, 3 });
+ std::vector<int> b = { 4, 5 };
int c[] = { 6, 7 };
- struct pair { int x; int y; };
- pair d = { 8, 9 };
-
-The matcher cxxStdInitializerListExpr()
-matches { 1, 2, 3 } and { 4, 5 }.
+ std::pair<int, int> d = { 8, 9 };
+cxxStdInitializerListExpr()
+ matches "{ 1, 2, 3 }" and "{ 4, 5 }"
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('cxxTemporaryObjectExpr0')"><a name="cxxTemporaryObjectExpr0Anchor">cxxTemporaryObjectExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXTemporaryObjectExpr.html">CXXTemporaryObjectExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="cxxTemporaryObjectExpr0"><pre>Matches functional cast expressions having N != 1 arguments
-Given
- struct Foo {
- Foo(int x, int y);
- };
-
- void foo(int bar) {
- Foo h = Foo(bar, bar);
- }
-
-
-The matcher cxxTemporaryObjectExpr()
-matches Foo(bar, bar).
+Example: Matches Foo(bar, bar)
+ Foo h = Foo(bar, bar);
</pre></td></tr>
-<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('cxxThisExpr0')"><a name="cxxThisExpr0Anchor">cxxThisExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXThisExpr.html">CXXThisExpr</a>>...</td></tr>
-<tr><td colspan="4" class="doc" id="cxxThisExpr0"><pre>Matches implicit and explicit this expressions.
-
-Given
- struct foo {
- int i;
- int f() { return i; }
- int g() { return this->i; }
- };
-
+<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('cxxThisExpr0')"><a name="cxxThisExpr0Anchor">cxxThisExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXThisExpr.html">CXXThisExpr</a>>...</td></tr>
+<tr><td colspan="4" class="doc" id="cxxThisExpr0"><pre>Matches implicit and explicit this expressions.
-The matcher cxxThisExpr()
-matches this of this->i and the implicit this expression
-of i.
+Example matches the implicit this expression in "return i".
+ (matcher = cxxThisExpr())
+struct foo {
+ int i;
+ int f() { return i; }
+};
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('cxxThrowExpr0')"><a name="cxxThrowExpr0Anchor">cxxThrowExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXThrowExpr.html">CXXThrowExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="cxxThrowExpr0"><pre>Matches throw expressions.
-void foo() {
try { throw 5; } catch(int i) {}
-}
-
-The matcher cxxThrowExpr()
-matches throw 5
+cxxThrowExpr()
+ matches 'throw 5'
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('cxxTryStmt0')"><a name="cxxTryStmt0Anchor">cxxTryStmt</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXTryStmt.html">CXXTryStmt</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="cxxTryStmt0"><pre>Matches try statements.
-void foo() {
try {} catch(int i) {}
-}
-
-The matcher cxxTryStmt()
-matches try {} catch(int i) {}
+cxxTryStmt()
+ matches 'try {}'
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('cxxUnresolvedConstructExpr0')"><a name="cxxUnresolvedConstructExpr0Anchor">cxxUnresolvedConstructExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html">CXXUnresolvedConstructExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="cxxUnresolvedConstructExpr0"><pre>Matches unresolved constructor call expressions.
-Given
+Example matches T(t) in return statement of f
+ (matcher = cxxUnresolvedConstructExpr())
template <typename T>
void f(const T& t) { return T(t); }
-
-
-The matcher cxxUnresolvedConstructExpr() matches
-T(t).
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('declRefExpr0')"><a name="declRefExpr0Anchor">declRefExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="declRefExpr0"><pre>Matches expressions that refer to declarations.
-Given
- void f(bool x) {
- if (x) {}
- }
-
-
-The matcher declRefExpr() matches x.
+Example matches x in if (x)
+ bool x;
+ if (x) {}
</pre></td></tr>
@@ -2396,11 +1836,9 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="declStmt0"><pre>Matches declaration statements.
Given
- void foo() {
- int a;
- }
-The matcher declStmt()
-matches int a;.
+ int a;
+declStmt()
+ matches 'int a'.
</pre></td></tr>
@@ -2408,75 +1846,22 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="defaultStmt0"><pre>Matches default statements inside switch statements.
Given
-void foo(int a) {
switch(a) { case 42: break; default: break; }
-}
-The matcher defaultStmt()
-matches default: break.
+defaultStmt()
+ matches 'default:'.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('dependentCoawaitExpr0')"><a name="dependentCoawaitExpr0Anchor">dependentCoawaitExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DependentCoawaitExpr.html">DependentCoawaitExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="dependentCoawaitExpr0"><pre>Matches co_await expressions where the type of the promise is dependent
-
-Given
- namespace std {
- template <typename T = void>
- struct coroutine_handle {
- static constexpr coroutine_handle from_address(void* addr) {
- return {};
- }
- };
-
- struct always_suspend {
- bool await_ready() const noexcept;
- bool await_resume() const noexcept;
- template <typename T>
- bool await_suspend(coroutine_handle<T>) const noexcept;
- };
-
- template <typename T>
- struct coroutine_traits {
- using promise_type = T::promise_type;
- };
- } // namespace std
-
- template <typename T>
- struct generator {
- struct promise_type {
- std::always_suspend yield_value(int&&);
- std::always_suspend initial_suspend() const noexcept;
- std::always_suspend final_suspend() const noexcept;
- void return_void();
- void unhandled_exception();
- generator get_return_object();
- };
- };
-
- template <typename T>
- std::always_suspend h();
-
- template <>
- std::always_suspend h<void>();
-
- template<typename T>
- generator<T> g() { co_await h<T>(); }
-
-The matcher dependentCoawaitExpr()
-matches co_await h<T>().
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('designatedInitExpr0')"><a name="designatedInitExpr0Anchor">designatedInitExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DesignatedInitExpr.html">DesignatedInitExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="designatedInitExpr0"><pre>Matches C99 designated initializer expressions [C99 6.7.8].
-Example: Given
- struct point2 { double x; double y; };
- struct point2 ptarray[10] = { [0].x = 1.0 };
- struct point2 pt = { .x = 2.0 };
-
-The matcher designatedInitExpr()
-matches [0].x = 1.0 and .x = 2.0.
+Example: Matches { [2].y = 1.0, [0].x = 1.0 }
+ point ptarray[10] = { [2].y = 1.0, [0].x = 1.0 };
</pre></td></tr>
@@ -2484,12 +1869,9 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="doStmt0"><pre>Matches do statements.
Given
-void foo() {
do {} while (true);
-}
-
-The matcher doStmt()
-matches do {} while (true)
+doStmt()
+ matches 'do {} while(true)'
</pre></td></tr>
@@ -2507,36 +1889,18 @@ <h2 id="decl-matchers">Node Matchers</h2>
See also: hasDestinationType.
- struct S {};
- const S* s;
- S* s2 = const_cast<S*>(s);
-
- const int val = 0;
- char val0 = val;
- char val1 = (char)val;
- char val2 = static_cast<char>(val);
- int* val3 = reinterpret_cast<int*>(val);
- char val4 = char(val);
-
-
-The matcher explicitCastExpr()
-matches (char)val, static_cast<char>(val),
-reinterpret_cast<int*>(val), const_cast<S*>(s)
-and char(val), but not the initialization of val0 with
-val.
+Example: matches all five of the casts in
+ int((int)(reinterpret_cast<int>(static_cast<int>(const_cast<int>(42)))))
+but does not match the implicit conversion in
+ long ell = 42;
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('expr0')"><a name="expr0Anchor">expr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="expr0"><pre>Matches expressions.
-Given
- int f(int x, int y) { return x + y; }
-
-The matcher expr() matches x + y once,
-x twice and y twice, matching the
-DeclRefExpr , and the ImplicitCastExpr that does an l- to r-value
-cast.
+Example matches x()
+ void f() { x(); }
</pre></td></tr>
@@ -2545,33 +1909,12 @@ <h2 id="decl-matchers">Node Matchers</h2>
of the sub-expression's evaluation.
Example matches std::string()
- struct A { ~A(); };
- void f(A);
- void g(A&);
- void h() {
- A a = A{};
- f(A{});
- f(a);
- g(a);
- }
-
-
-The matcher exprWithCleanups() matches A{},
-f(A{}) and f(a),
-but does not match passing g(a).
+ const std::string str = std::string();
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('fixedPointLiteral0')"><a name="fixedPointLiteral0Anchor">fixedPointLiteral</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FixedPointLiteral.html">FixedPointLiteral</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="fixedPointLiteral0"><pre>Matches fixed point literals
-
-Given
- void f() {
- 0.0k;
- }
-
-
-The matcher fixedPointLiteral() matches 0.0k.
</pre></td></tr>
@@ -2579,62 +1922,27 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="floatLiteral0"><pre>Matches float literals of all sizes / encodings, e.g.
1.0, 1.0f, 1.0L and 1e10.
-Given
- int a = 1.0;
- int b = 1.0F;
- int c = 1.0L;
- int d = 1e10;
- int e = 1;
-
-The matcher floatLiteral() matches
-1.0, 1.0F, 1.0L and 1e10, but does not match
-1.
+Does not match implicit conversions such as
+ float a = 10;
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('forStmt0')"><a name="forStmt0Anchor">forStmt</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ForStmt.html">ForStmt</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="forStmt0"><pre>Matches for statements.
-Given
- void foo() {
- for (;;) {}
- int i[] = {1, 2, 3}; for (auto a : i);
- }
-
-
-The matcher forStmt() matches for (;;) {},
-but not for (auto a : i);.
+Example matches 'for (;;) {}'
+ for (;;) {}
+ int i[] = {1, 2, 3}; for (auto a : i);
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('genericSelectionExpr0')"><a name="genericSelectionExpr0Anchor">genericSelectionExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1GenericSelectionExpr.html">GenericSelectionExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="genericSelectionExpr0"><pre>Matches C11 _Generic expression.
-
-Given
- double fdouble(double);
- float ffloat(float);
- #define GENERIC_MACRO(X) _Generic((X), double: fdouble, float: ffloat)(X)
-
- void f() {
- GENERIC_MACRO(0.0);
- GENERIC_MACRO(0.0F);
- }
-
-
-The matcher genericSelectionExpr() matches
-the generic selection expression that is expanded in
-GENERIC_MACRO(0.0) and GENERIC_MACRO(0.0F).
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('gnuNullExpr0')"><a name="gnuNullExpr0Anchor">gnuNullExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1GNUNullExpr.html">GNUNullExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="gnuNullExpr0"><pre>Matches GNU __null expression.
-
-Given
- auto val = __null;
-
-
-The matcher gnuNullExpr() matches __null.
</pre></td></tr>
@@ -2642,39 +1950,24 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="gotoStmt0"><pre>Matches goto statements.
Given
-void bar();
-void foo() {
goto FOO;
FOO: bar();
-}
-The matcher gotoStmt()
-matches goto FOO
+gotoStmt()
+ matches 'goto FOO'
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('ifStmt0')"><a name="ifStmt0Anchor">ifStmt</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1IfStmt.html">IfStmt</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="ifStmt0"><pre>Matches if statements.
-Given
- void foo(int x) {
- if (x) {}
- }
-
-The matcher ifStmt() matches if (x) {}.
+Example matches 'if (x) {}'
+ if (x) {}
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('imaginaryLiteral0')"><a name="imaginaryLiteral0Anchor">imaginaryLiteral</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ImaginaryLiteral.html">ImaginaryLiteral</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="imaginaryLiteral0"><pre>Matches imaginary literals, which are based on integer and floating
point literals e.g.: 1i, 1.0i
-
-Given
- auto a = 1i;
- auto b = 1.0i;
-
-
-The matcher imaginaryLiteral() matches 1i and
-1.0i.
</pre></td></tr>
@@ -2683,17 +1976,6 @@ <h2 id="decl-matchers">Node Matchers</h2>
This matches many different places, including function call return value
eliding, as well as any type conversions.
-
-void f(int);
-void g(int val1, int val2) {
- unsigned int a = val1;
- f(val2);
-}
-
-The matcher implicitCastExpr()
-matches val1 for the implicit cast from an l- to an r-value
-and for the cast to int}, f for the function pointer
-decay, and val2 for the cast from an l- to an r-value.
</pre></td></tr>
@@ -2701,11 +1983,9 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="implicitValueInitExpr0"><pre>Matches implicit initializers of init list expressions.
Given
- struct point { double x; double y; };
- struct point pt = { .x = 42.0 };
-The matcher
-initListExpr(has(implicitValueInitExpr().bind("implicit")))
-matches { .x = 42.0 }.
+ point ptarray[10] = { [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 };
+implicitValueInitExpr()
+ matches "[0].y" (implicitly)
</pre></td></tr>
@@ -2715,9 +1995,9 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
int a[] = { 1, 2 };
struct B { int x, y; };
- struct B b = { 5, 6 };
-The matcher initListExpr()
-matches { 1, 2 } and { 5, 6 }
+ B b = { 5, 6 };
+initListExpr()
+ matches "{ 1, 2 }" and "{ 5, 6 }"
</pre></td></tr>
@@ -2726,17 +2006,6 @@ <h2 id="decl-matchers">Node Matchers</h2>
1, 1L, 0x1 and 1U.
Does not match character-encoded integers such as L'a'.
-
-Given
- int a = 1;
- int b = 1L;
- int c = 0x1;
- int d = 1U;
- int e = 1.0;
-
-The matcher integerLiteral() matches
-1, 1L, 0x1 and 1U, but does not match
-1.0.
</pre></td></tr>
@@ -2744,26 +2013,18 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="labelStmt0"><pre>Matches label statements.
Given
-void bar();
-void foo() {
goto FOO;
FOO: bar();
-}
-The matcher labelStmt()
-matches FOO: bar()
+labelStmt()
+ matches 'FOO:'
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('lambdaExpr0')"><a name="lambdaExpr0Anchor">lambdaExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1LambdaExpr.html">LambdaExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="lambdaExpr0"><pre>Matches lambda expressions.
-Given
- void f() {
- []() { return 5; };
- }
-
-
-The matcher lambdaExpr() matches []() { return 5; }.
+Example matches [&](){return 5;}
+ [&](){return 5;}
</pre></td></tr>
@@ -2774,17 +2035,12 @@ <h2 id="decl-matchers">Node Matchers</h2>
struct T {void func();};
T f();
void g(T);
- void foo() {
- T u(f());
- g(f());
- f().func();
- f(); // does not match
- }
-
-The matcher materializeTemporaryExpr() matches
-f() three times before C++17 and it
-matches f() time with C++17 and later, but
-it does not match the f() in the last line in any version.
+materializeTemporaryExpr() matches 'f()' in these statements
+ T u(f());
+ g(f());
+ f().func();
+but does not match
+ f();
</pre></td></tr>
@@ -2796,20 +2052,17 @@ <h2 id="decl-matchers">Node Matchers</h2>
void x() { this->x(); x(); Y y; y.x(); a; this->b; Y::b; }
int a; static int b;
};
-
-The matcher memberExpr()
-matches this->x, x, y.x, a, this->b.
+memberExpr()
+ matches this->x, x, y.x, a, this->b
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('nullStmt0')"><a name="nullStmt0Anchor">nullStmt</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1NullStmt.html">NullStmt</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="nullStmt0"><pre>Matches null statements.
-void foo() {
foo();;
-}
-The matcher nullStmt()
-matches the second ;
+nullStmt()
+ matches the second ';'
</pre></td></tr>
@@ -2819,7 +2072,6 @@ <h2 id="decl-matchers">Node Matchers</h2>
Example matches @catch
@try {}
@catch (...) {}
-
</pre></td></tr>
@@ -2829,23 +2081,19 @@ <h2 id="decl-matchers">Node Matchers</h2>
Example matches @finally
@try {}
@finally {}
-
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('objcIvarRefExpr0')"><a name="objcIvarRefExpr0Anchor">objcIvarRefExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCIvarRefExpr.html">ObjCIvarRefExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="objcIvarRefExpr0"><pre>Matches a reference to an ObjCIvar.
-Given
+Example: matches "a" in "init" method:
@implementation A {
NSString *a;
}
- (void) init {
a = @"hello";
}
-
-
-The matcher objcIvarRefExpr() matches a.
</pre></td></tr>
@@ -2857,10 +2105,6 @@ <h2 id="decl-matchers">Node Matchers</h2>
"initWithString" instance method on the object returned from
NSString's "alloc". This matcher should match both message sends.
[[NSString alloc] initWithString:@"Hello"]
-
-
-The matcher objcMessageExpr() matches
-[[NSString alloc] initWithString:@"Hello"]
</pre></td></tr>
@@ -2869,7 +2113,6 @@ <h2 id="decl-matchers">Node Matchers</h2>
Example matches @"abcd"
NSString *s = @"abcd";
-
</pre></td></tr>
@@ -2877,7 +2120,6 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="objcThrowStmt0"><pre>Matches Objective-C statements.
Example matches @throw obj;
-
</pre></td></tr>
@@ -2887,7 +2129,6 @@ <h2 id="decl-matchers">Node Matchers</h2>
Example matches @try
@try {}
@catch (...) {}
-
</pre></td></tr>
@@ -2895,19 +2136,13 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="ompExecutableDirective0"><pre>Matches any ``#pragma omp`` executable directive.
Given
- void foo() {
- #pragma omp parallel
- {}
- #pragma omp parallel default(none)
- {
- #pragma omp taskyield
- }
- }
-The matcher ompExecutableDirective()
-matches #pragma omp parallel,
-#pragma omp parallel default(none)
-and #pragma omp taskyield.
+ #pragma omp parallel
+ #pragma omp parallel default(none)
+ #pragma omp taskyield
+
+``ompExecutableDirective()`` matches ``omp parallel``,
+``omp parallel default(none)`` and ``omp taskyield``.
</pre></td></tr>
@@ -2916,27 +2151,17 @@ <h2 id="decl-matchers">Node Matchers</h2>
to reference another expressions and can be met
in BinaryConditionalOperators, for example.
-Given
- int f(int a, int b) {
- return (a ?: b) + 42;
- }
-
-
-The matcher opaqueValueExpr() matches a twice,
-once for the check and once for the expression of the true path.
+Example matches 'a'
+ (a ?: c) + 42;
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('parenExpr0')"><a name="parenExpr0Anchor">parenExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ParenExpr.html">ParenExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="parenExpr0"><pre>Matches parentheses used in expressions.
-Given
+Example matches (foo() + 1)
int foo() { return 1; }
- int bar() {
- int a = (foo() + 1);
- }
-
-The matcher parenExpr() matches (foo() + 1).
+ int a = (foo() + 1);
</pre></td></tr>
@@ -2952,12 +2177,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
int a = 0, b = 1; int i = (a, b);
}
};
-
-The matcher parenListExpr()
-matches (*this),
-but does not match (a, b)
-because (a, b) has a predefined type and is a ParenExpr, not a
-ParenListExpr.
+parenListExpr() matches "*this" but NOT matches (a, b) because (a, b)
+has a predefined type and is a ParenExpr, not a ParenListExpr.
</pre></td></tr>
@@ -2965,12 +2186,7 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="predefinedExpr0"><pre>Matches predefined identifier expressions [C99 6.4.2.2].
Example: Matches __func__
- void f() {
- const char* func_name = __func__;
- }
-
-The matcher predefinedExpr()
-matches __func__.
+ printf("%s", __func__);
</pre></td></tr>
@@ -2978,11 +2194,9 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="returnStmt0"><pre>Matches return statements.
Given
-int foo() {
return 1;
-}
-The matcher returnStmt()
-matches return 1
+returnStmt()
+ matches 'return 1'
</pre></td></tr>
@@ -2990,35 +2204,26 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="stmt0"><pre>Matches statements.
Given
- void foo(int a) { { ++a; } }
-The matcher stmt()
-matches the function body itself { { ++a; } }, the compound
-statement { ++a; }, the expression ++a and a.
+ { ++a; }
+stmt()
+ matches both the compound statement '{ ++a; }' and '++a'.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('stmtExpr0')"><a name="stmtExpr0Anchor">stmtExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1StmtExpr.html">StmtExpr</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="stmtExpr0"><pre>Matches statement expression (GNU extension).
-Given
- void f() {
- int C = ({ int X = 4; X; });
- }
-
-The matcher stmtExpr() matches ({ int X = 4; X; }).
+Example match: ({ int X = 4; X; })
+ int C = ({ int X = 4; X; });
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('stringLiteral0')"><a name="stringLiteral0Anchor">stringLiteral</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1StringLiteral.html">StringLiteral</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="stringLiteral0"><pre>Matches string literals (also matches wide string literals).
-Given
+Example matches "abcd", L"abcd"
char *s = "abcd";
wchar_t *ws = L"abcd";
-
-
-The matcher stringLiteral() matches "abcd" and
-L"abcd".
</pre></td></tr>
@@ -3029,9 +2234,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
template <int N>
struct A { static const int n = N; };
struct B : public A<42> {};
-
-The matcher substNonTypeTemplateParmExpr()
-matches N in the right-hand side of "static const int n = N;"
+substNonTypeTemplateParmExpr()
+ matches "N" in the right-hand side of "static const int n = N;"
</pre></td></tr>
@@ -3039,11 +2243,9 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="switchCase0"><pre>Matches case and default statements inside switch statements.
Given
-void foo(int a) {
switch(a) { case 42: break; default: break; }
-}
-The matcher switchCase()
-matches case 42: break and default: break
+switchCase()
+ matches 'case 42:' and 'default:'.
</pre></td></tr>
@@ -3051,11 +2253,9 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="switchStmt0"><pre>Matches switch statements.
Given
-void foo(int a) {
switch(a) { case 42: break; default: break; }
-}
-The matcher switchStmt()
-matches switch(a) { case 42: break; default: break; }.
+switchStmt()
+ matches 'switch(a)'.
</pre></td></tr>
@@ -3063,11 +2263,10 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="unaryExprOrTypeTraitExpr0"><pre>Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL)
Given
- int x = 42;
+ Foo x = bar;
int y = sizeof(x) + alignof(x);
-
-The matcher unaryExprOrTypeTraitExpr()
-matches sizeof(x) and alignof(x)
+unaryExprOrTypeTraitExpr()
+ matches sizeof(x) and alignof(x)
</pre></td></tr>
@@ -3075,12 +2274,7 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="unaryOperator0"><pre>Matches unary operator expressions.
Example matches !a
- void foo(bool a, bool b) {
- !a || b;
- }
-
-
-The matcher unaryOperator() matches !a.
+ !a || b
</pre></td></tr>
@@ -3095,10 +2289,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
void bar() {
foo<T>();
}
-
-The matcher unresolvedLookupExpr()
-matches foo<T>.
-</pre></td></tr>
+unresolvedLookupExpr()
+ matches foo<T>() </pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('unresolvedMemberExpr0')"><a name="unresolvedMemberExpr0Anchor">unresolvedMemberExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedMemberExpr.html">UnresolvedMemberExpr</a>>...</td></tr>
@@ -3110,9 +2302,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
void g();
};
template <class T> void h() { X x; x.f<T>(); x.g(); }
-
-The matcher unresolvedMemberExpr()
-matches x.f<T>
+unresolvedMemberExpr()
+ matches x.f<T>
</pre></td></tr>
@@ -3120,12 +2311,6 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="userDefinedLiteral0"><pre>Matches user defined literal operator call.
Example match: "foo"_suffix
-Given
- float operator ""_foo(long double);
- float a = 1234.5_foo;
-
-
-The matcher userDefinedLiteral() matches 1234.5_foo.
</pre></td></tr>
@@ -3133,12 +2318,9 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="whileStmt0"><pre>Matches while statements.
Given
-void foo() {
while (true) {}
-}
-
-The matcher whileStmt()
-matches while (true) {}.
+whileStmt()
+ matches 'while (true) {}'.
</pre></td></tr>
@@ -3148,9 +2330,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
template <typename T> struct C {};
C<int> c;
-
-The matcher templateArgumentLoc()
-matches int in C<int>.
+templateArgumentLoc()
+ matches 'int' in C<int>.
</pre></td></tr>
@@ -3160,10 +2341,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
template <typename T> struct C {};
C<int> c;
-
-The matcher
-templateSpecializationType(hasAnyTemplateArgument(templateArgument()))
-matches C<int>.
+templateArgument()
+ matches 'int' in C<int>.
</pre></td></tr>
@@ -3171,14 +2350,10 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="templateName0"><pre>Matches template name.
Given
- template<template <typename> class S> class X {};
- template<typename T> class Y {};
- X<Y> xi;
-
-The matcher
-classTemplateSpecializationDecl(hasAnyTemplateArgument(
- refersToTemplate(templateName())))
-matches the specialization class X<Y>
+ template <typename T> class X { };
+ X<int> xi;
+templateName()
+ matches 'X' in X<int>.
</pre></td></tr>
@@ -3188,8 +2363,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
struct s {};
struct s ss;
-The matcher elaboratedTypeLoc()
-matches the type struct s of ss.
+elaboratedTypeLoc()
+ matches the `TypeLoc` of the variable declaration of `ss`.
</pre></td></tr>
@@ -3198,8 +2373,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
int* x;
-The matcher pointerTypeLoc()
- matches int*.
+pointerTypeLoc()
+ matches `int*`.
</pre></td></tr>
@@ -3208,11 +2383,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
const int x = 0;
-
-The matcher qualifiedTypeLoc()
-matches the type of the variable declaration x . However, the
-current implementation of QualifiedTypeLoc does not store the source
-locations for the qualifiers of the type int.
+qualifiedTypeLoc()
+ matches `const int`.
</pre></td></tr>
@@ -3223,10 +2395,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
int x = 3;
int& l = x;
int&& r = 3;
-
-
-The matcher referenceTypeLoc()
- matches int& and int&&.
+referenceTypeLoc()
+ matches `int&` and `int&&`.
</pre></td></tr>
@@ -3236,25 +2406,13 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
template <typename T> class C {};
C<char> var;
-
-The matcher
-varDecl(hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
-templateSpecializationTypeLoc(typeLoc())))))
-matches C<char> var.
+varDecl(hasTypeLoc(templateSpecializationTypeLoc(typeLoc())))
+ matches `C<char> var`.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>></td><td class="name" onclick="toggle('typeLoc0')"><a name="typeLoc0Anchor">typeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="typeLoc0"><pre>Matches TypeLocs in the clang AST.
-
-That is, information about a type and where it was written.
-
- void foo(int val);
-
-The matcher declaratorDecl(hasTypeLoc(typeLoc().bind("type")))
-matches void foo(int val) and int val, with
-typeLoc() matching void and
-int respectively.
</pre></td></tr>
@@ -3265,9 +2423,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
int a[] = { 2, 3 };
int b[4];
void f() { int c[a[0]]; }
-The matcher arrayType()
-int[4], int[a[0]] and
-int[];
+arrayType()
+ matches "int a[]", "int b[4]" and "int c[a[0]]";
</pre></td></tr>
@@ -3276,25 +2433,20 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
_Atomic(int) i;
-The matcher atomicType()
-_Atomic(int)
+atomicType()
+ matches "_Atomic(int) i"
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td><td class="name" onclick="toggle('autoType0')"><a name="autoType0Anchor">autoType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AutoType.html">AutoType</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="autoType0"><pre>Matches types nodes representing C++11 auto types.
-Given
- void foo() {
- auto n = 4;
- int v[] = { 2, 3 };
- for (auto i : v) { };
- }
-
-The matcher autoType()
-matches the auto of n and i ,
-as well as the auto types for the implicitly generated code of the range-for
-loop (for the range, the begin iterator and the end iterator).
+Given:
+ auto n = 4;
+ int v[] = { 2, 3 }
+ for (auto i : v) { }
+autoType()
+ matches "auto n" and "auto i"
</pre></td></tr>
@@ -3310,12 +2462,13 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="builtinType0"><pre>Matches builtin Types.
Given
- enum E { Ok };
- enum E e;
+ struct A {};
+ A a;
int b;
float c;
-The matcher varDecl(hasType(builtinType()))
-matches int b and float c.
+ bool d;
+builtinType()
+ matches "int b", "float c" and "bool d"
</pre></td></tr>
@@ -3324,8 +2477,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
_Complex float f;
-The matcher complexType()
-_Complex float
+complexType()
+ matches "_Complex float f"
</pre></td></tr>
@@ -3333,38 +2486,37 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="constantArrayType0"><pre>Matches C arrays with a specified constant size.
Given
- void foo() {
+ void() {
int a[2];
int b[] = { 2, 3 };
int c[b[0]];
}
-The matcher constantArrayType()
-int[2]
+constantArrayType()
+ matches "int a[2]"
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td><td class="name" onclick="toggle('decayedType0')"><a name="decayedType0Anchor">decayedType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DecayedType.html">DecayedType</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="decayedType0"><pre>Matches decayed type
+Example matches i[] in declaration of f.
+ (matcher = valueDecl(hasType(decayedType(hasDecayedType(pointerType())))))
+Example matches i[1].
+ (matcher = expr(hasType(decayedType(hasDecayedType(pointerType())))))
void f(int i[]) {
i[1] = 0;
}
-The matcher
-valueDecl(hasType(decayedType(hasDecayedType(pointerType()))))
-matches int i[] in declaration of The matcher
-expr(hasType(decayedType(hasDecayedType(pointerType()))))
-matches i in </pre></td></tr>
+</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td><td class="name" onclick="toggle('decltypeType0')"><a name="decltypeType0Anchor">decltypeType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DecltypeType.html">DecltypeType</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="decltypeType0"><pre>Matches types nodes representing C++11 decltype(<expr>) types.
-Given
+Given:
short i = 1;
int j = 42;
decltype(i + j) result = i + j;
-
-The matcher decltypeType()
-decltype(i + j)
+decltypeType()
+ matches "decltype(i + j)"
</pre></td></tr>
@@ -3377,9 +2529,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
class C { public: C(T); };
C c(123);
-
-The matcher deducedTemplateSpecializationType() matches the type
-C of the declaration of the variable c.
+deducedTemplateSpecializationType() matches the type in the declaration
+of the variable c.
</pre></td></tr>
@@ -3391,9 +2542,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
class array {
T data[Size];
};
-
-The matcher dependentSizedArrayType()
-T[Size]
+dependentSizedArrayType()
+ matches "T data[Size]"
</pre></td></tr>
@@ -3406,9 +2556,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
class vector {
typedef T __attribute__((ext_vector_type(Size))) type;
};
-
-The matcher dependentSizedExtVectorType()
-T __attribute__((ext_vector_type(Size)))
+dependentSizedExtVectorType()
+ matches "T __attribute__((ext_vector_type(Size)))"
</pre></td></tr>
@@ -3424,17 +2573,11 @@ <h2 id="decl-matchers">Node Matchers</h2>
}
class C {};
- C c;
+ class C c;
N::M::D d;
-
-The matcher elaboratedType() matches the type
-C three times. Once for the type of the
-variable c, once for the type of the class definition and once for the
-type in the injected class name. For D}, it matches
-N::M::D of variable d and its class definition and
-injected class name
-D one time respectively.
+elaboratedType() matches the type of the variable declarations of both
+c and d.
</pre></td></tr>
@@ -3448,10 +2591,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
C c;
S s;
-
-The matcher enumType() matches the type
-enum C of c ,
-and the type enum S of s .
+enumType() matches the type of the variable declarations of both c and
+s.
</pre></td></tr>
@@ -3461,11 +2602,9 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
int (*f)(int);
void g();
-The matcher functionProtoType()
-matches the type int (int) of 'f' and the type
-void (void) of 'g' in C++ mode.
-In C, the type void () of 'g' is not
-matched because it does not contain a prototype.
+functionProtoType()
+ matches "int (*f)(int)" and the type of "g" in C++ mode.
+ In C mode, "g" is not matched because it does not contain a prototype.
</pre></td></tr>
@@ -3475,12 +2614,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
int (*f)(int);
void g();
-The matcher functionType()
-int (int) and the type of
-void (void) in C++ and in C23 and
-later. Before C23, the function type for f will be matched the same way,
-but the function type for g will match
-void ().
+functionType()
+ matches "int (*f)(int)" and the type of "g".
</pre></td></tr>
@@ -3491,30 +2626,27 @@ <h2 id="decl-matchers">Node Matchers</h2>
int a[] = { 2, 3 };
int b[42];
void f(int c[]) { int d[a[0]]; };
-The matcher incompleteArrayType()
-int[] and int[]
+incompleteArrayType()
+ matches "int a[]" and "int c[]"
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td><td class="name" onclick="toggle('injectedClassNameType0')"><a name="injectedClassNameType0Anchor">injectedClassNameType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="injectedClassNameType0"><pre>Matches injected class name types.
-Given
+Example matches S s, but not S<T> s.
+ (matcher = parmVarDecl(hasType(injectedClassNameType())))
template <typename T> struct S {
void f(S s);
void g(S<T> s);
};
-
-The matcher
-parmVarDecl(hasType(elaboratedType(namesType(injectedClassNameType()))))
-matches S s, but not s}
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td><td class="name" onclick="toggle('lValueReferenceType0')"><a name="lValueReferenceType0Anchor">lValueReferenceType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1LValueReferenceType.html">LValueReferenceType</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="lValueReferenceType0"><pre>Matches lvalue reference types.
-Given
+Given:
int *a;
int &b = *a;
int &&c = 1;
@@ -3523,11 +2655,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
auto &&f = 2;
int g = 5;
-
-The matcher lValueReferenceType() matches the type
-int & of b and the type auto &
-of d.
-FIXME: figure out why auto changechange matches twice
+lValueReferenceType() matches the types of b, d, and e. e is
+matched since the type is deduced as int& by reference collapsing rules.
</pre></td></tr>
@@ -3538,23 +2667,18 @@ <h2 id="decl-matchers">Node Matchers</h2>
#define CDECL __attribute__((cdecl))
typedef void (CDECL *X)();
typedef void (__attribute__((cdecl)) *Y)();
-The matcher macroQualifiedType()
-matches the type CDECL void
-(void) of the typedef declaration of X , unless when in C98-C17, there
-CDECL void (),
-but it does not match the type
-__attribute((cdecl)) void () of Y .
+macroQualifiedType()
+ matches the type of the typedef declaration of X but not Y.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td><td class="name" onclick="toggle('memberPointerType0')"><a name="memberPointerType0Anchor">memberPointerType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html">MemberPointerType</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="memberPointerType0"><pre>Matches member pointer types.
Given
- struct A { int i; };
- int A::* ptr = &A::i;
-
-The matcher memberPointerType()
-matches int struct A::*.
+ struct A { int i; }
+ A::* ptr = A::i;
+memberPointerType()
+ matches "A::* ptr"
</pre></td></tr>
@@ -3568,10 +2692,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
@interface Foo
@end
Foo *f;
-
-The matcher pointerType()
-matches Foo *, but does not match
-int *.
+pointerType()
+ matches "Foo *f", but does not match "int *a".
</pre></td></tr>
@@ -3582,9 +2704,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
int (*ptr_to_array)[4];
int *array_of_ptrs[4];
-The matcher varDecl(hasType(pointsTo(parenType())))
- matches ptr_to_array but not
- array_of_ptrs.
+varDecl(hasType(pointsTo(parenType()))) matches ptr_to_array but not
+array_of_ptrs.
</pre></td></tr>
@@ -3593,28 +2714,22 @@ <h2 id="decl-matchers">Node Matchers</h2>
types.
Given
- typedef int* int_ptr;
- void foo(char *str,
- int val,
- int *val_ptr,
- int_ptr not_a_ptr,
- int_ptr *ptr);
-
-The matcher parmVarDecl(hasType(pointerType()))
-matches char *str, int *val_ptr and
-int_ptr *ptr.
+ int *a;
+ int &b = *a;
+ int c = 5;
@interface Foo
@end
Foo *f;
-
+pointerType()
+ matches "int *a", but does not match "Foo *f".
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td><td class="name" onclick="toggle('rValueReferenceType0')"><a name="rValueReferenceType0Anchor">rValueReferenceType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1RValueReferenceType.html">RValueReferenceType</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="rValueReferenceType0"><pre>Matches rvalue reference types.
-Given
+Given:
int *a;
int &b = *a;
int &&c = 1;
@@ -3623,10 +2738,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
auto &&f = 2;
int g = 5;
-
-The matcher rValueReferenceType() matches the type
-int && of c and the type
-auto && of f.
+rValueReferenceType() matches the types of c and f. e is not
+matched as it is deduced to int& by reference collapsing rules.
</pre></td></tr>
@@ -3640,14 +2753,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
C c;
S s;
-
-The matcher recordType() matches the type
-class C of the variable declaration of c and
-matches the type struct S of the variable
-declaration of s.
-Both of these types are matched three times, once for the type of the
-variable, once for the definition of the class, and once for the type of the
-injected class name.
+recordType() matches the type of the variable declarations of both c
+and s.
</pre></td></tr>
@@ -3663,12 +2770,7 @@ <h2 id="decl-matchers">Node Matchers</h2>
auto &&f = 2;
int g = 5;
-
-The matcher referenceType() matches the type
-int & of b , the type int && of
-c, the type
-auto & d, and the type
-auto && of e and f.
+referenceType() matches the types of b, c, d, e, and f.
</pre></td></tr>
@@ -3679,17 +2781,10 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
template <typename T>
void F(T t) {
- T local;
int i = 1 + t;
}
- void f() {
- F(0);
- }
-
-The matcher varDecl(hasType(substTemplateTypeParmType()))
-matches T t and T local for the substituted template type
-int in the instantiation of F .
+substTemplateTypeParmType() matches the type of 't' but not '1'
</pre></td></tr>
@@ -3697,18 +2792,14 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="tagType0"><pre>Matches tag types (record and enum types).
Given
- enum E { Ok };
+ enum E {};
class C {};
E e;
C c;
-
-The matcher tagType() matches the type
-enum E of variable e and the type
-class C three times, once for the type
-of the variable c , once for the type of the class definition and once of
-the type in the injected class name.
+tagType() matches the type of the variable declarations of both e
+and c.
</pre></td></tr>
@@ -3719,38 +2810,25 @@ <h2 id="decl-matchers">Node Matchers</h2>
template <typename T>
class C { };
- template class C<int>;
- C<int> intvar;
- C<char> charvar;
+ template class C<int>; // A
+ C<char> var; // B
-
-The matcher templateSpecializationType() matches the type
-C<int> of the explicit instantiation in A and the
-type C<char> of the variable declaration in
-B.
+templateSpecializationType() matches the type of the explicit
+instantiation in A and the type of the variable declaration in B.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td><td class="name" onclick="toggle('templateTypeParmType0')"><a name="templateTypeParmType0Anchor">templateTypeParmType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="templateTypeParmType0"><pre>Matches template type parameter types.
-Given
+Example matches T, but not int.
+ (matcher = templateTypeParmType())
template <typename T> void f(int i);
-
-The matcher templateTypeParmType() matches T,
-but does not match int.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td><td class="name" onclick="toggle('type0')"><a name="type0Anchor">type</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="type0"><pre>Matches Types in the clang AST.
-
-Given
- const int b = 1;
-
-The matcher varDecl(hasType(type().bind("type")))
-matches const int b = 1, with type()
-matching int.
</pre></td></tr>
@@ -3759,22 +2837,18 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
typedef int X;
- X x = 0;
-The matcher typedefType()
-matches X.
+typedefType()
+ matches "typedef int X"
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td><td class="name" onclick="toggle('unaryTransformType0')"><a name="unaryTransformType0Anchor">unaryTransformType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1UnaryTransformType.html">UnaryTransformType</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="unaryTransformType0"><pre>Matches types nodes representing unary type transformations.
-Given
- template <typename T> struct A {
- typedef __underlying_type(T) type;
- };
-
-The matcher unaryTransformType()
-matches __underlying_type(T)
+Given:
+ typedef __underlying_type(T) type;
+unaryTransformType()
+ matches "__underlying_type(T)"
</pre></td></tr>
@@ -3786,9 +2860,7 @@ <h2 id="decl-matchers">Node Matchers</h2>
using a::S;
S s;
-
-The matcher usingType() matches the type a::S
-of the variable declaration of s.
+usingType() matches the type of the variable declaration of s.
</pre></td></tr>
@@ -3798,12 +2870,12 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
void f() {
- int a[] = { 2, 3 };
+ int a[] = { 2, 3 }
int b[42];
int c[a[0]];
}
-The matcher variableArrayType()
-int[a[0]]
+variableArrayType()
+ matches "int c[a[0]]"
</pre></td></tr>
<!--END_DECL_MATCHERS -->
@@ -3827,12 +2899,6 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="allOf0"><pre>Matches if all given matchers match.
Usable as: Any Matcher
-
- int v0 = 0;
- int v1 = 1;
-
-The matcher varDecl(allOf(hasName("v0"), hasType(isInteger())))
-matches int v0 = 0.
</pre></td></tr>
@@ -3840,13 +2906,6 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="anyOf0"><pre>Matches if any of the given matchers matches.
Usable as: Any Matcher
-
- char v0 = 'a';
- int v1 = 1;
- float v2 = 2.0;
-
-The matcher varDecl(anyOf(hasName("v0"), hasType(isInteger())))
-matches char v0 = 'a' and int v1 = 1.
</pre></td></tr>
@@ -3857,11 +2916,11 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
additional constraint. This will often be used with an explicit conversion
to an internal::Matcher<> type such as TypeMatcher.
-Given
+Example: DeclarationMatcher(anything()) matches all declarations, e.g.,
+"int* p" and "void f()" in
int* p;
void f();
-The matcher decl(anything())
-matches int* p and void f().
+
Usable as: Any Matcher
</pre></td></tr>
@@ -3870,25 +2929,21 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="mapAnyOf0"><pre>Matches any of the NodeMatchers with InnerMatchers nested within
Given
- void f() {
- if (true);
- for (; true; );
- }
-
-
-The matcher stmt(mapAnyOf(ifStmt, forStmt).with(
- hasCondition(cxxBoolLiteral(equals(true)))
- )),
-which is equivalent to
-stmt(anyOf(
- ifStmt(hasCondition(cxxBoolLiteral(equals(true)))).bind("trueCond"),
- forStmt(hasCondition(cxxBoolLiteral(equals(true)))).bind("trueCond")
- )),
-matches if (true); and for (; true; );.
+ if (true);
+ for (; true; );
+with the matcher
+ mapAnyOf(ifStmt, forStmt).with(
+ hasCondition(cxxBoolLiteralExpr(equals(true)))
+ ).bind("trueCond")
+matches the if and the for. It is equivalent to:
+ auto trueCond = hasCondition(cxxBoolLiteralExpr(equals(true)));
+ anyOf(
+ ifStmt(trueCond).bind("trueCond"),
+ forStmt(trueCond).bind("trueCond")
+ );
The with() chain-call accepts zero or more matchers which are combined
as-if with allOf() in each of the node matchers.
-
Usable as: Any Matcher
</pre></td></tr>
@@ -3896,13 +2951,10 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td>Matcher<*></td><td class="name" onclick="toggle('unless0')"><a name="unless0Anchor">unless</a></td><td>Matcher<*></td></tr>
<tr><td colspan="4" class="doc" id="unless0"><pre>Matches if the provided matcher does not match.
-Given
+Example matches Y (matcher = cxxRecordDecl(unless(hasName("X"))))
class X {};
class Y {};
-The matcher cxxRecordDecl(unless(hasName("X")))
-matches Y
-
Usable as: Any Matcher
</pre></td></tr>
@@ -3910,20 +2962,6 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Attr.html">Attr</a>></td><td class="name" onclick="toggle('isImplicit1')"><a name="isImplicit1Anchor">isImplicit</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isImplicit1"><pre>Matches an entity that has been implicitly added by the compiler (e.g.
implicit default/copy constructors).
-
-Given
- struct S {};
- void f(S obj) {
- S copy = obj;
- [&](){ return copy; };
- }
-
-
-The matcher cxxConstructorDecl(isImplicit(), isCopyConstructor())
-matches the implicit copy constructor of S.
-The matcher lambdaExpr(forEachLambdaCapture(
- lambdaCapture(isImplicit()))) matches [&](){ return copy; },
-because it implicitly captures copy .
</pre></td></tr>
@@ -3931,26 +2969,9 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="hasAnyOperatorName0"><pre>Matches operator expressions (binary or unary) that have any of the
specified names.
-It provides a compact way of writing if an operator has any of the specified
-names:
-The matcher
hasAnyOperatorName("+", "-")
-Is equivalent to
- hasOperatorName("-"))}
-
-Given
-void foo(bool a, bool b) {
- !(a || b);
- }
-
-void bar(bool a, bool b) {
- a && b;
- }
-
-The matcher binaryOperator(hasAnyOperatorName("||", "&&"))
-matches a || b and a && b.
-The matcher unaryOperator(hasAnyOperatorName("-", "!"))
-matches !(a || b).
+ Is equivalent to
+ anyOf(hasOperatorName("+"), hasOperatorName("-"))
</pre></td></tr>
@@ -3958,62 +2979,43 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="hasOperatorName0"><pre>Matches the operator Name of operator expressions and fold expressions
(binary or unary).
-Given
-void foo(bool a, bool b) {
- !(a || b);
- }
-
-The matcher binaryOperator(hasOperatorName("||"))
-matches a || b
+Example matches a || b (matcher = binaryOperator(hasOperatorName("||")))
+ !(a || b)
-Given
+Example matches `(0 + ... + args)`
+ (matcher = cxxFoldExpr(hasOperatorName("+")))
template <typename... Args>
auto sum(Args... args) {
return (0 + ... + args);
}
-
-The matcher cxxFoldExpr(hasOperatorName("+"))
- matches (0 + ... + args).
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>></td><td class="name" onclick="toggle('isAssignmentOperator0')"><a name="isAssignmentOperator0Anchor">isAssignmentOperator</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isAssignmentOperator0"><pre>Matches all kinds of assignment operators.
-Given
-void foo(int a, int b) {
+Example 1: matches a += b (matcher = binaryOperator(isAssignmentOperator()))
if (a == b)
a += b;
-}
-The matcher binaryOperator(isAssignmentOperator())
-matches a += b.
-Given
+Example 2: matches s1 = s2
+ (matcher = cxxOperatorCallExpr(isAssignmentOperator()))
struct S { S& operator=(const S&); };
void x() { S s1, s2; s1 = s2; }
-
-The matcher cxxOperatorCallExpr(isAssignmentOperator())
-matches s1 = s2.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>></td><td class="name" onclick="toggle('isComparisonOperator0')"><a name="isComparisonOperator0Anchor">isComparisonOperator</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isComparisonOperator0"><pre>Matches comparison operators.
-Given
-void foo(int a, int b) {
+Example 1: matches a == b (matcher = binaryOperator(isComparisonOperator()))
if (a == b)
a += b;
-}
-The matcher binaryOperator(isComparisonOperator())
-matches a == b
-Given
+Example 2: matches s1 < s2
+ (matcher = cxxOperatorCallExpr(isComparisonOperator()))
struct S { bool operator<(const S& other); };
void x(S s1, S s2) { bool b1 = s1 < s2; }
-
-The matcher cxxOperatorCallExpr(isComparisonOperator())
-matches s1 < s2
</pre></td></tr>
@@ -4021,25 +3023,16 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="isPrivate1"><pre>Matches private C++ declarations and C++ base specifers that specify private
inheritance.
-Given
+Examples:
class C {
public: int a;
protected: int b;
- private: int c;
+ private: int c; // fieldDecl(isPrivate()) matches 'c'
};
-The matcher fieldDecl(isPrivate())
-matches c.
-
struct Base {};
- struct Derived1 : private Base {}; // Base
- class Derived2 : Base {}; // Base
-
-The matcher
-cxxRecordDecl(hasAnyBase(cxxBaseSpecifier(isPrivate()).bind("base")))
-matches Derived1 and Derived2, with
-cxxBaseSpecifier(isPrivate()) matching
-Base.
+ struct Derived1 : private Base {}; // matches 'Base'
+ class Derived2 : Base {}; // matches 'Base'
</pre></td></tr>
@@ -4047,24 +3040,15 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="isProtected1"><pre>Matches protected C++ declarations and C++ base specifers that specify
protected inheritance.
-Given
+Examples:
class C {
public: int a;
- protected: int b;
+ protected: int b; // fieldDecl(isProtected()) matches 'b'
private: int c;
};
-The matcher fieldDecl(isProtected())
-matches b.
-
class Base {};
- class Derived : protected Base {};
-
-The matcher
-cxxRecordDecl(hasAnyBase(cxxBaseSpecifier(isProtected()).bind("base")))
-matches Derived, with
-cxxBaseSpecifier(isProtected()) matching
-Base.
+ class Derived : protected Base {}; // matches 'Base'
</pre></td></tr>
@@ -4072,26 +3056,16 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="isPublic1"><pre>Matches public C++ declarations and C++ base specifers that specify public
inheritance.
-Given
+Examples:
class C {
- public: int a;
+ public: int a; // fieldDecl(isPublic()) matches 'a'
protected: int b;
private: int c;
};
-The matcher fieldDecl(isPublic())
-matches a.
-
-Given
class Base {};
- class Derived1 : public Base {};
- struct Derived2 : Base {};
-
-The matcher
-cxxRecordDecl(hasAnyBase(cxxBaseSpecifier(isPublic()).bind("base")))
-matches Derived1 and Derived2,
-with cxxBaseSpecifier(isPublic()) matching
-public Base and Base.
+ class Derived1 : public Base {}; // matches 'Base'
+ struct Derived2 : Base {}; // matches 'Base'
</pre></td></tr>
@@ -4099,23 +3073,16 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="isVirtual1"><pre>Matches declarations of virtual methods and C++ base specifers that specify
virtual inheritance.
-Given
+Example:
class A {
public:
virtual void x(); // matches x
};
-The matcher cxxMethodDecl(isVirtual())
-matches x.
-
-Given
- struct Base {};
- struct DirectlyDerived : virtual Base {}; // matches Base
- struct IndirectlyDerived : DirectlyDerived, Base {}; // matches Base
-
-The matcher
-cxxRecordDecl(hasDirectBase(cxxBaseSpecifier(isVirtual())))
-matches DirectlyDerived.
+Example:
+ class Base {};
+ class DirectlyDerived : virtual Base {}; // matches Base
+ class IndirectlyDerived : DirectlyDerived, Base {}; // matches Base
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>>
</pre></td></tr>
@@ -4129,27 +3096,22 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="equals2"><pre>Matches literals that are equal to the given value of type ValueT.
Given
-void f(char, bool, double, int);
-void foo() {
f('false, 3.14, 42);
-}
-
-The matcher characterLiteral(equals(0U)) matches 'The matchers cxxBoolLiteral(equals(false)) and
-cxxBoolLiteral(equals(0)) match false.
-The matcher floatLiteral(equals(3.14)) matches 3.14.
-The matcher integerLiteral(equals(42)) matches 42.
+characterLiteral(equals(0))
+ matches 'cxxBoolLiteral(equals(false)) and cxxBoolLiteral(equals(0))
+ match false
+floatLiteral(equals(3.14)) and floatLiteral(equals(314e-2))
+ match 3.14
+integerLiteral(equals(42))
+ matches 42
Note that you cannot directly match a negative numeric literal because the
minus sign is not part of the literal: It is a unary operator whose operand
is the positive numeric literal. Instead, you must use a unaryOperator()
matcher to match the minus sign:
-Given
- int val = -1;
-
-The matcher unaryOperator(hasOperatorName("-"),
- hasUnaryOperand(integerLiteral(equals(1))))
-matches -1.
+unaryOperator(hasOperatorName("-"),
+ hasUnaryOperand(integerLiteral(equals(13))))
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>>
@@ -4168,15 +3130,14 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="isCatchAll0"><pre>Matches a C++ catch statement that has a catch-all handler.
Given
- void foo() {
- try {}
- catch (int) {}
- catch (...) {}
+ try {
+ // ...
+ } catch (int) {
+ // ...
+ } catch (...) {
+ // ...
}
-
-The matcher cxxCatchStmt(isCatchAll())
-matches catch (...) {}
-but does not match catch(int)
+cxxCatchStmt(isCatchAll()) matches catch(...) but not catch(int).
</pre></td></tr>
@@ -4184,15 +3145,12 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="argumentCountAtLeast1"><pre>Checks that a call expression or a constructor call expression has at least
the specified number of arguments (including absent default arguments).
-Given
+Example matches f(0, 0) and g(0, 0, 0)
+(matcher = callExpr(argumentCountAtLeast(2)))
void f(int x, int y);
void g(int x, int y, int z);
- void foo() {
- f(0, 0);
- g(0, 0, 0);
- }
-The matcher callExpr(argumentCountAtLeast(2))
-matches f(0, 0) and g(0, 0, 0)
+ f(0, 0);
+ g(0, 0, 0);
</pre></td></tr>
@@ -4200,39 +3158,14 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="argumentCountIs1"><pre>Checks that a call expression or a constructor call expression has
a specific number of arguments (including absent default arguments).
-Given
+Example matches f(0, 0) (matcher = callExpr(argumentCountIs(2)))
void f(int x, int y);
- void foo() {
- f(0, 0);
- }
-The matcher callExpr(argumentCountIs(2))
-matches f(0, 0)
+ f(0, 0);
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>></td><td class="name" onclick="toggle('isListInitialization0')"><a name="isListInitialization0Anchor">isListInitialization</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isListInitialization0"><pre>Matches a constructor call expression which uses list initialization.
-
-Given
- namespace std {
- template <typename T>
- class initializer_list {
- const T* begin;
- const T* end;
- };
- }
- template <typename T> class vector {
- public: vector(std::initializer_list<T>) {}
- };
-
- vector<int> a({ 1, 2, 3 });
- vector<int> b = { 4, 5 };
- int c[] = { 6, 7 };
- struct pair { int x; int y; };
- pair d = { 8, 9 };
-
-The matcher cxxConstructExpr(isListInitialization())
-matches { 4, 5 }.
</pre></td></tr>
@@ -4242,15 +3175,11 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
Given
void foo() {
- struct Foo {
- double x;
- };
- auto Val = Foo();
+ struct point { double x; double y; };
+ point pt[2] = { { 1.0, 2.0 } };
}
-
-The matcher
-cxxConstructExpr(requiresZeroInitialization())
-matches Foo() because the x member has to be zero initialized.
+initListExpr(has(cxxConstructExpr(requiresZeroInitialization()))
+will match the implicit array filler for pt[1].
</pre></td></tr>
@@ -4263,10 +3192,7 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
S(const S &); // #2
S(S &&); // #3
};
-
-The matcher cxxConstructorDecl(isCopyConstructor())
-matches S(const S &),
-but does not match S() or S(S &&).
+cxxConstructorDecl(isCopyConstructor()) will match #2, but not #1 or #3.
</pre></td></tr>
@@ -4279,10 +3205,7 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
S(const S &); // #2
S(S &&); // #3
};
-
-The matcher cxxConstructorDecl(isDefaultConstructor())
-matches S()
-but does not match S(const S &); or S(S &&);.
+cxxConstructorDecl(isDefaultConstructor()) will match #1, but not #2 or #3.
</pre></td></tr>
@@ -4296,10 +3219,8 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
S(S &&) : S() {} // #3
};
S::S() : S(0) {} // #4
-
-The matcher cxxConstructorDecl(isDelegatingConstructor())
-matches S(S &&) : S() {} and S::S() : S(0) {},
-but does not match S() or S(int).
+cxxConstructorDecl(isDelegatingConstructor()) will match #3 and #4, but not
+#1 or #2.
</pre></td></tr>
@@ -4315,27 +3236,15 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
explicit S(double); // #2
operator int(); // #3
explicit operator bool(); // #4
- explicit(false) S(bool); // # 7
- explicit(true) S(char); // # 8
- explicit(b) S(float); // # 9
+ explicit(false) S(bool) // # 7
+ explicit(true) S(char) // # 8
+ explicit(b) S(S) // # 9
};
- S(int) -> S<true>; // #5
- explicit S(double) -> S<false>; // #6
-
-The matcher cxxConstructorDecl(isExplicit())
-matches explicit S(double)
-and explicit(true) S(char)
-but does not match S(int);, explicit(false) S(bool); or
-explicit(b) S(float)
-The matcher cxxConversionDecl(isExplicit())
-matches explicit operator bool()
-but does not match operator int().
-The matcher cxxDeductionGuideDecl(isExplicit())
-matches the deduction guide explicit S(double) -> S<false>,
-the implicit copy deduction candiate
-auto (double) -> S<b> and
-the implicitly generated deduction guide for explicit(true) S(char),
-but does not match S(int) -> S<true>.
+ S(int) -> S<true> // #5
+ explicit S(double) -> S<false> // #6
+cxxConstructorDecl(isExplicit()) will match #2 and #8, but not #1, #7 or #9.
+cxxConversionDecl(isExplicit()) will match #4, but not #3.
+cxxDeductionGuideDecl(isExplicit()) will match #6, but not #5.
</pre></td></tr>
@@ -4352,10 +3261,7 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
S(const S &); // #2
S(S &&); // #3
};
-
-The matcher cxxConstructorDecl(isMoveConstructor())
-matches S(S &&)
-but does not match S(); or S(S &&);
+cxxConstructorDecl(isMoveConstructor()) will match #3, but not #1 or #2.
</pre></td></tr>
@@ -4371,27 +3277,15 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
explicit S(double); // #2
operator int(); // #3
explicit operator bool(); // #4
- explicit(false) S(bool); // # 7
- explicit(true) S(char); // # 8
- explicit(b) S(float); // # 9
+ explicit(false) S(bool) // # 7
+ explicit(true) S(char) // # 8
+ explicit(b) S(S) // # 9
};
- S(int) -> S<true>; // #5
- explicit S(double) -> S<false>; // #6
-
-The matcher cxxConstructorDecl(isExplicit())
-matches explicit S(double)
-and explicit(true) S(char)
-but does not match S(int);, explicit(false) S(bool); or
-explicit(b) S(float)
-The matcher cxxConversionDecl(isExplicit())
-matches explicit operator bool()
-but does not match operator int().
-The matcher cxxDeductionGuideDecl(isExplicit())
-matches the deduction guide explicit S(double) -> S<false>,
-the implicit copy deduction candiate
-auto (double) -> S<b> and
-the implicitly generated deduction guide for explicit(true) S(char),
-but does not match S(int) -> S<true>.
+ S(int) -> S<true> // #5
+ explicit S(double) -> S<false> // #6
+cxxConstructorDecl(isExplicit()) will match #2 and #8, but not #1, #7 or #9.
+cxxConversionDecl(isExplicit()) will match #4, but not #3.
+cxxDeductionGuideDecl(isExplicit()) will match #6, but not #5.
</pre></td></tr>
@@ -4408,12 +3302,8 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
struct E : B {
E() : B() {}
};
-
-The matcher
cxxConstructorDecl(hasAnyConstructorInitializer(isBaseInitializer()))
-matches E() : B() {} and D(int i) : I(i) {}.
-The constructor of D is matched, because it implicitly has a constructor
-initializer for B .
+ will match E(), but not match D(int).
</pre></td></tr>
@@ -4430,11 +3320,8 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
struct E : B {
E() : B() {}
};
-
-The matcher
cxxConstructorDecl(hasAnyConstructorInitializer(isMemberInitializer()))
- will match D(int i) : I(i) {}, but not match E() : B()
- {}.
+ will match D(int), but not match E().
</pre></td></tr>
@@ -4443,16 +3330,13 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
code (as opposed to implicitly added by the compiler).
Given
- struct Bar { explicit Bar(const char*); };
struct Foo {
Foo() { }
Foo(int) : foo_("A") { }
- Bar foo_{""};
+ string foo_;
};
-
-The matcher
-cxxConstructorDecl(hasAnyConstructorInitializer(isWritten())) will
-match Foo(int) : foo_("A") { }, but not Foo() { }
+cxxConstructorDecl(hasAnyConstructorInitializer(isWritten()))
+ will match Foo(int), but not Foo()
</pre></td></tr>
@@ -4468,27 +3352,15 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
explicit S(double); // #2
operator int(); // #3
explicit operator bool(); // #4
- explicit(false) S(bool); // # 7
- explicit(true) S(char); // # 8
- explicit(b) S(float); // # 9
+ explicit(false) S(bool) // # 7
+ explicit(true) S(char) // # 8
+ explicit(b) S(S) // # 9
};
- S(int) -> S<true>; // #5
- explicit S(double) -> S<false>; // #6
-
-The matcher cxxConstructorDecl(isExplicit())
-matches explicit S(double)
-and explicit(true) S(char)
-but does not match S(int);, explicit(false) S(bool); or
-explicit(b) S(float)
-The matcher cxxConversionDecl(isExplicit())
-matches explicit operator bool()
-but does not match operator int().
-The matcher cxxDeductionGuideDecl(isExplicit())
-matches the deduction guide explicit S(double) -> S<false>,
-the implicit copy deduction candiate
-auto (double) -> S<b> and
-the implicitly generated deduction guide for explicit(true) S(char),
-but does not match S(int) -> S<true>.
+ S(int) -> S<true> // #5
+ explicit S(double) -> S<false> // #6
+cxxConstructorDecl(isExplicit()) will match #2 and #8, but not #1, #7 or #9.
+cxxConversionDecl(isExplicit()) will match #4, but not #3.
+cxxDeductionGuideDecl(isExplicit()) will match #6, but not #5.
</pre></td></tr>
@@ -4510,9 +3382,7 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
S<T> s;
s.mem();
}
-
-The matcher cxxDependentScopeMemberExpr(hasMemberName("mem"))
-matches s.mem.
+cxxDependentScopeMemberExpr(hasMemberName("mem")) matches `s.mem()`
</pre></td></tr>
@@ -4531,25 +3401,14 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
};
template <class T>
class Z {
- void x() {
- this->m;
- this->t;
- this->t->m;
- }
- int m;
- T* t;
+ void x() { this->m; }
};
-
-The matcher memberExpr(isArrow())
-matches this->x, x, a,
-this->b, this->m and two times this->t,
-once for the standalone member expression, and once for the member
-expression that later accesses m .
-Additionally, it does not match this->t->t.
-The matcher cxxDependentScopeMemberExpr(isArrow())
-matches this->t->m, but not this->m or this->t.
-The matcher unresolvedMemberExpr(isArrow())
-matches this->f<T>, f<T>
+memberExpr(isArrow())
+ matches this->x, x, y.x, a, this->b
+cxxDependentScopeMemberExpr(isArrow())
+ matches this->m
+unresolvedMemberExpr(isArrow())
+ matches this->f<T>, f<T>
</pre></td></tr>
@@ -4573,20 +3432,19 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
S<T> s;
s.mem();
}
-
-The matcher cxxDependentScopeMemberExpr(
- hasObjectExpression(declRefExpr(hasType(
- elaboratedType(namesType(templateSpecializationType(
+The matcher
+ at code
+cxxDependentScopeMemberExpr(
+ hasObjectExpression(declRefExpr(hasType(templateSpecializationType(
hasDeclaration(classTemplateDecl(has(cxxRecordDecl(has(
cxxMethodDecl(hasName("mem")).bind("templMem")
)))))
- )))
- ))),
+ )))),
memberHasSameNameAsBoundNode("templMem")
-)
-matches s.mem, with the inner matcher
-cxxMethodDecl(hasName("mem")) matching
-void mem() of the S template.
+ )
+ at endcode
+first matches and binds the @c mem member of the @c S template, then
+compares its name to the usage in @c s.mem() in the @c x function template
</pre></td></tr>
@@ -4594,29 +3452,23 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="hasOperatorName3"><pre>Matches the operator Name of operator expressions and fold expressions
(binary or unary).
-Given
-void foo(bool a, bool b) {
- !(a || b);
- }
-
-The matcher binaryOperator(hasOperatorName("||"))
-matches a || b
+Example matches a || b (matcher = binaryOperator(hasOperatorName("||")))
+ !(a || b)
-Given
+Example matches `(0 + ... + args)`
+ (matcher = cxxFoldExpr(hasOperatorName("+")))
template <typename... Args>
auto sum(Args... args) {
return (0 + ... + args);
}
-
-The matcher cxxFoldExpr(hasOperatorName("+"))
- matches (0 + ... + args).
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFoldExpr.html">CXXFoldExpr</a>></td><td class="name" onclick="toggle('isBinaryFold0')"><a name="isBinaryFold0Anchor">isBinaryFold</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isBinaryFold0"><pre>Matches binary fold expressions, i.e. fold expressions with an initializer.
-Given
+Example matches `(0 + ... + args)`
+ (matcher = cxxFoldExpr(isBinaryFold()))
template <typename... Args>
auto sum(Args... args) {
return (0 + ... + args);
@@ -4626,17 +3478,14 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
auto multiply(Args... args) {
return (args * ...);
}
-
-
-The matcher cxxFoldExpr(isBinaryFold())
-matches (0 + ... + args).
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFoldExpr.html">CXXFoldExpr</a>></td><td class="name" onclick="toggle('isLeftFold0')"><a name="isLeftFold0Anchor">isLeftFold</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isLeftFold0"><pre>Matches left-folding fold expressions.
-Given
+Example matches `(0 + ... + args)`
+ (matcher = cxxFoldExpr(isLeftFold()))
template <typename... Args>
auto sum(Args... args) {
return (0 + ... + args);
@@ -4646,17 +3495,14 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
auto multiply(Args... args) {
return (args * ... * 1);
}
-
-
-The matcher cxxFoldExpr(isLeftFold())
-matches (0 + ... + args).
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFoldExpr.html">CXXFoldExpr</a>></td><td class="name" onclick="toggle('isRightFold0')"><a name="isRightFold0Anchor">isRightFold</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isRightFold0"><pre>Matches right-folding fold expressions.
-Given
+Example matches `(args * ... * 1)`
+ (matcher = cxxFoldExpr(isRightFold()))
template <typename... Args>
auto sum(Args... args) {
return (0 + ... + args);
@@ -4666,10 +3512,6 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
auto multiply(Args... args) {
return (args * ... * 1);
}
-
-
-The matcher cxxFoldExpr(isRightFold())
-matches (args * ... * 1).
</pre></td></tr>
@@ -4677,7 +3519,8 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="isUnaryFold0"><pre>Matches unary fold expressions, i.e. fold expressions without an
initializer.
-Given
+Example matches `(args * ...)`
+ (matcher = cxxFoldExpr(isUnaryFold()))
template <typename... Args>
auto sum(Args... args) {
return (0 + ... + args);
@@ -4687,10 +3530,6 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
auto multiply(Args... args) {
return (args * ...);
}
-
-
-The matcher cxxFoldExpr(isUnaryFold())
-matches (args * ...), but not (0 + ... + args).
</pre></td></tr>
@@ -4703,9 +3542,7 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
void bar();
};
-
-The matcher cxxMethodDecl(isConst())
-matches foo but not bar
+cxxMethodDecl(isConst()) matches A::foo() but not A::bar()
</pre></td></tr>
@@ -4719,10 +3556,8 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
A &operator=(A &&);
};
-
-The matcher cxxMethodDecl(isCopyAssignmentOperator())
-matches A &operator=(const A &)
-but does not match A &operator=(A &&)
+cxxMethodDecl(isCopyAssignmentOperator()) matches the first method but not
+the second one.
</pre></td></tr>
@@ -4738,19 +3573,15 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
int operator+(int);
};
-
-The matcher cxxMethodDecl(isExplicitObjectMemberFunction())
-matches int operator-(this A, int) and
-void fun(this A &&self),
-but not static int operator()(int) or
-int operator+(int).
+cxxMethodDecl(isExplicitObjectMemberFunction()) matches the first two
+methods but not the last two.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>></td><td class="name" onclick="toggle('isFinal1')"><a name="isFinal1Anchor">isFinal</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isFinal1"><pre>Matches if the given method or class declaration is final.
-Given
+Given:
class A final {};
struct B {
@@ -4760,13 +3591,7 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
struct C : B {
void f() final;
};
-
-The matcher cxxRecordDecl(isFinal())
-matches A,
-but does not match B or C.
-The matcher cxxMethodDecl(isFinal())
-matches void f() final in C ,
-but does not match virtual void f() in B .
+matches A and C::f, but not B, C, or B::f
</pre></td></tr>
@@ -4780,10 +3605,8 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
A &operator=(A &&);
};
-
-The matcher cxxMethodDecl(isMoveAssignmentOperator())
-matches A &operator=(A &&)
-but does not match A &operator=(const A &)
+cxxMethodDecl(isMoveAssignmentOperator()) matches the second method but not
+the first one.
</pre></td></tr>
@@ -4797,11 +3620,9 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
};
class B : public A {
public:
- void x() override;
+ virtual void x();
};
-
-The matcher cxxMethodDecl(isOverride())
- matches void x() override
+ matches B::x
</pre></td></tr>
@@ -4813,9 +3634,7 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
public:
virtual void x() = 0;
};
-
-The matcher cxxMethodDecl(isPure())
-matches virtual void x() = 0
+ matches A::x
</pre></td></tr>
@@ -4828,10 +3647,7 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
S(const S &) = default; // #2
S(S &&) = delete; // #3
};
-
-The matcher cxxConstructorDecl(isUserProvided())
-will match S(), but not S &) = default} or
-&&) = delete}
+cxxConstructorDecl(isUserProvided()) will match #1, but not #2 or #3.
</pre></td></tr>
@@ -4839,23 +3655,16 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="isVirtual0"><pre>Matches declarations of virtual methods and C++ base specifers that specify
virtual inheritance.
-Given
+Example:
class A {
public:
virtual void x(); // matches x
};
-The matcher cxxMethodDecl(isVirtual())
-matches x.
-
-Given
- struct Base {};
- struct DirectlyDerived : virtual Base {}; // matches Base
- struct IndirectlyDerived : DirectlyDerived, Base {}; // matches Base
-
-The matcher
-cxxRecordDecl(hasDirectBase(cxxBaseSpecifier(isVirtual())))
-matches DirectlyDerived.
+Example:
+ class Base {};
+ class DirectlyDerived : virtual Base {}; // matches Base
+ class IndirectlyDerived : DirectlyDerived, Base {}; // matches Base
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>>
</pre></td></tr>
@@ -4873,22 +3682,17 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
public:
void x();
};
-
-The matcher cxxMethodDecl(isVirtualAsWritten())
-matches virtual void x() of A,
-but does not match x()} of B .
+ matches A::x but not B::x
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>></td><td class="name" onclick="toggle('isArray0')"><a name="isArray0Anchor">isArray</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isArray0"><pre>Matches array new expressions.
-Given
- struct MyClass { int x; };
+Given:
MyClass *p1 = new MyClass[10];
-
-The matcher cxxNewExpr(isArray())
-matches new MyClass[10].
+cxxNewExpr(isArray())
+ matches the expression 'new MyClass[10]'.
</pre></td></tr>
@@ -4896,26 +3700,9 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="hasAnyOperatorName1"><pre>Matches operator expressions (binary or unary) that have any of the
specified names.
-It provides a compact way of writing if an operator has any of the specified
-names:
-The matcher
hasAnyOperatorName("+", "-")
-Is equivalent to
- hasOperatorName("-"))}
-
-Given
-void foo(bool a, bool b) {
- !(a || b);
- }
-
-void bar(bool a, bool b) {
- a && b;
- }
-
-The matcher binaryOperator(hasAnyOperatorName("||", "&&"))
-matches a || b and a && b.
-The matcher unaryOperator(hasAnyOperatorName("-", "!"))
-matches !(a || b).
+ Is equivalent to
+ anyOf(hasOperatorName("+"), hasOperatorName("-"))
</pre></td></tr>
@@ -4926,30 +3713,6 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
"operator" prefix: e.g. "<<".
hasAnyOverloadedOperatorName("+", "-")
-
-Given
- struct Point { double x; double y; };
- Point operator+(const Point&, const Point&);
- Point operator-(const Point&, const Point&);
-
- Point sub(Point a, Point b) {
- return b - a;
- }
-
-
-The matcher functionDecl(hasAnyOverloadedOperatorName("+", "-")),
-which is equivalent to
-functionDecl(anyOf(hasAnyOverloadedOperatorName("+"),
-hasOverloadedOperatorName("-"))),
-matches Point operator+(const Point&, const Point&) and
-Point operator-(const Point&, const Point&).
-The matcher
-cxxOperatorCallExpr(hasAnyOverloadedOperatorName("+", "-")),
-which is equivalent to
-cxxOperatorCallExpr(anyOf(hasOverloadedOperatorName("+"),
-hasOverloadedOperatorName("-"))),
-matches b - a.
-
Is equivalent to
anyOf(hasOverloadedOperatorName("+"), hasOverloadedOperatorName("-"))
</pre></td></tr>
@@ -4959,22 +3722,15 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="hasOperatorName1"><pre>Matches the operator Name of operator expressions and fold expressions
(binary or unary).
-Given
-void foo(bool a, bool b) {
- !(a || b);
- }
-
-The matcher binaryOperator(hasOperatorName("||"))
-matches a || b
+Example matches a || b (matcher = binaryOperator(hasOperatorName("||")))
+ !(a || b)
-Given
+Example matches `(0 + ... + args)`
+ (matcher = cxxFoldExpr(hasOperatorName("+")))
template <typename... Args>
auto sum(Args... args) {
return (0 + ... + args);
}
-
-The matcher cxxFoldExpr(hasOperatorName("+"))
- matches (0 + ... + args).
</pre></td></tr>
@@ -4984,19 +3740,16 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
Matches overloaded operator names specified in strings without the
"operator" prefix: e.g. "<<".
-Given
- struct A { int operator*(); };
+Given:
+ class A { int operator*(); };
const A &operator<<(const A &a, const A &b);
- void f(A a) {
- a << a; // <-- This matches
- }
+ A a;
+ a << a; // <-- This matches
-
-The matcher cxxOperatorCallExpr(hasOverloadedOperatorName("<<"))
-matches a << a.
-The matcher
+cxxOperatorCallExpr(hasOverloadedOperatorName("<<"))) matches the
+specified line and
cxxRecordDecl(hasMethod(hasOverloadedOperatorName("*")))
-matches struct A { int operator*(); }.
+matches the declaration of A.
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>>
</pre></td></tr>
@@ -5005,104 +3758,47 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>></td><td class="name" onclick="toggle('isAssignmentOperator1')"><a name="isAssignmentOperator1Anchor">isAssignmentOperator</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isAssignmentOperator1"><pre>Matches all kinds of assignment operators.
-Given
-void foo(int a, int b) {
+Example 1: matches a += b (matcher = binaryOperator(isAssignmentOperator()))
if (a == b)
a += b;
-}
-The matcher binaryOperator(isAssignmentOperator())
-matches a += b.
-Given
+Example 2: matches s1 = s2
+ (matcher = cxxOperatorCallExpr(isAssignmentOperator()))
struct S { S& operator=(const S&); };
void x() { S s1, s2; s1 = s2; }
-
-The matcher cxxOperatorCallExpr(isAssignmentOperator())
-matches s1 = s2.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>></td><td class="name" onclick="toggle('isComparisonOperator1')"><a name="isComparisonOperator1Anchor">isComparisonOperator</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isComparisonOperator1"><pre>Matches comparison operators.
-Given
-void foo(int a, int b) {
+Example 1: matches a == b (matcher = binaryOperator(isComparisonOperator()))
if (a == b)
a += b;
-}
-The matcher binaryOperator(isComparisonOperator())
-matches a == b
-Given
+Example 2: matches s1 < s2
+ (matcher = cxxOperatorCallExpr(isComparisonOperator()))
struct S { bool operator<(const S& other); };
void x(S s1, S s2) { bool b1 = s1 < s2; }
-
-The matcher cxxOperatorCallExpr(isComparisonOperator())
-matches s1 < s2
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>></td><td class="name" onclick="toggle('hasDefinition0')"><a name="hasDefinition0Anchor">hasDefinition</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasDefinition0"><pre>Matches a class declaration that is defined.
-Given
+Example matches x (matcher = cxxRecordDecl(hasDefinition()))
class x {};
class y;
-
-The matcher cxxRecordDecl(hasDefinition())
-matches class x {}
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>></td><td class="name" onclick="toggle('isDerivedFrom2')"><a name="isDerivedFrom2Anchor">isDerivedFrom</a></td><td>std::string BaseName</td></tr>
<tr><td colspan="4" class="doc" id="isDerivedFrom2"><pre>Overloaded method as shortcut for isDerivedFrom(hasName(...)).
-
-Matches C++ classes that are directly or indirectly derived from a class
-matching Base, or Objective-C classes that directly or indirectly
-subclass a class matching Base.
-
-Note that a class is not considered to be derived from itself.
-
-Example matches Y, Z, C (Base == hasName("X"))
- class X {};
- class Y : public X {}; // directly derived
- class Z : public Y {}; // indirectly derived
- typedef X A;
- typedef A B;
- class C : public B {}; // derived from a typedef of X
-
- class Foo {};
- typedef Foo Alias;
- class Bar : public Alias {}; // derived from Alias, which is a
- // typedef of Foo
-
-
-The matcher cxxRecordDecl(isDerivedFrom("X"))
-matches Y, Z and C.
-The matcher cxxRecordDecl(isDerivedFrom("Foo"))
-matches Bar.
-
-In the following example, Bar matches isDerivedFrom(hasName("NSObject"))
- @interface NSObject @end
- @interface Bar : NSObject @end
-
-
-Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCInterfaceDecl.html">ObjCInterfaceDecl</a>>
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>></td><td class="name" onclick="toggle('isDirectlyDerivedFrom2')"><a name="isDirectlyDerivedFrom2Anchor">isDirectlyDerivedFrom</a></td><td>std::string BaseName</td></tr>
<tr><td colspan="4" class="doc" id="isDirectlyDerivedFrom2"><pre>Overloaded method as shortcut for isDirectlyDerivedFrom(hasName(...)).
-
-Given
- struct Base {};
- struct DirectlyDerived : public Base {};
- struct IndirectlyDerived : public DirectlyDerived {};
-
-
-The matcher cxxRecordDecl(isDirectlyDerivedFrom("Base"))
-matches DirectlyDerived, but not
-IndirectlyDerived.
</pre></td></tr>
@@ -5113,9 +3809,8 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
Given
template<typename T> void A(T t) { }
template<> void A(int N) { }
-
-The matcher functionDecl(isExplicitTemplateSpecialization())
- matches the specialization template<> void A(int N) { }.
+functionDecl(isExplicitTemplateSpecialization())
+ matches the specialization A<int>().
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>>
</pre></td></tr>
@@ -5124,7 +3819,7 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>></td><td class="name" onclick="toggle('isFinal0')"><a name="isFinal0Anchor">isFinal</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isFinal0"><pre>Matches if the given method or class declaration is final.
-Given
+Given:
class A final {};
struct B {
@@ -5134,46 +3829,24 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
struct C : B {
void f() final;
};
-
-The matcher cxxRecordDecl(isFinal())
-matches A,
-but does not match B or C.
-The matcher cxxMethodDecl(isFinal())
-matches void f() final in C ,
-but does not match virtual void f() in B .
+matches A and C::f, but not B, C, or B::f
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>></td><td class="name" onclick="toggle('isLambda0')"><a name="isLambda0Anchor">isLambda</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isLambda0"><pre>Matches the generated class of lambda expressions.
-Given
+Given:
auto x = []{};
-
-The matcher varDecl(hasType(cxxRecordDecl(isLambda())))
-matches auto x = []{}.
+cxxRecordDecl(isLambda()) matches the implicit class declaration of
+decltype(x)
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>></td><td class="name" onclick="toggle('isSameOrDerivedFrom2')"><a name="isSameOrDerivedFrom2Anchor">isSameOrDerivedFrom</a></td><td>std::string BaseName</td></tr>
-<tr><td colspan="4" class="doc" id="isSameOrDerivedFrom2"><pre>Similar to isDerivedFrom(), but also matches classes that directly
-match Base.
-Overloaded method as shortcut for
+<tr><td colspan="4" class="doc" id="isSameOrDerivedFrom2"><pre>Overloaded method as shortcut for
isSameOrDerivedFrom(hasName(...)).
-
-Given
- class X {};
- class Y : public X {}; // directly derived
- class Z : public Y {}; // indirectly derived
- typedef X A;
- typedef A B;
- class C : public B {}; // derived from a typedef of X
-
-The matcher
-cxxRecordDecl(isSameOrDerivedFrom("X"), isDefinition())
-matches class X {}, class Y : public X {},
-class Z : public Y {} and class C : public B {}.
</pre></td></tr>
@@ -5182,36 +3855,18 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
member variable template instantiations.
Given
- template <typename T> class X {};
- class A {};
- X<A> x;
-
-The matcher cxxRecordDecl(hasName("::X"),
-isTemplateInstantiation())
-matches class X<class A>.
- template <typename T> class X {};
- class A {};
- template class X<A>;
-
-The matcher cxxRecordDecl(hasName("::X"),
-isTemplateInstantiation())
-matches template class X<A>
- template <typename T> class X {};
- class A {};
- extern template class X<A>;
-
-The matcher cxxRecordDecl(hasName("::X"),
-isTemplateInstantiation())
-matches extern template class X<A>
+ template <typename T> class X {}; class A {}; X<A> x;
+or
+ template <typename T> class X {}; class A {}; template class X<A>;
+or
+ template <typename T> class X {}; class A {}; extern template class X<A>;
+cxxRecordDecl(hasName("::X"), isTemplateInstantiation())
+ matches the template instantiation of X<A>.
But given
- template <typename T> class X {};
- class A {};
- template <> class X<A> {};
- X<A> x;
-
-The matcher cxxRecordDecl(hasName("::X"),
-isTemplateInstantiation())
+ template <typename T> class X {}; class A {};
+ template <> class X<A> {}; X<A> x;
+cxxRecordDecl(hasName("::X"), isTemplateInstantiation())
does not match, as X<A> is an explicit template specialization.
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>>
@@ -5222,26 +3877,9 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="hasAnyOperatorName2"><pre>Matches operator expressions (binary or unary) that have any of the
specified names.
-It provides a compact way of writing if an operator has any of the specified
-names:
-The matcher
hasAnyOperatorName("+", "-")
-Is equivalent to
- hasOperatorName("-"))}
-
-Given
-void foo(bool a, bool b) {
- !(a || b);
- }
-
-void bar(bool a, bool b) {
- a && b;
- }
-
-The matcher binaryOperator(hasAnyOperatorName("||", "&&"))
-matches a || b and a && b.
-The matcher unaryOperator(hasAnyOperatorName("-", "!"))
-matches !(a || b).
+ Is equivalent to
+ anyOf(hasOperatorName("+"), hasOperatorName("-"))
</pre></td></tr>
@@ -5249,62 +3887,43 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="hasOperatorName2"><pre>Matches the operator Name of operator expressions and fold expressions
(binary or unary).
-Given
-void foo(bool a, bool b) {
- !(a || b);
- }
-
-The matcher binaryOperator(hasOperatorName("||"))
-matches a || b
+Example matches a || b (matcher = binaryOperator(hasOperatorName("||")))
+ !(a || b)
-Given
+Example matches `(0 + ... + args)`
+ (matcher = cxxFoldExpr(hasOperatorName("+")))
template <typename... Args>
auto sum(Args... args) {
return (0 + ... + args);
}
-
-The matcher cxxFoldExpr(hasOperatorName("+"))
- matches (0 + ... + args).
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRewrittenBinaryOperator.html">CXXRewrittenBinaryOperator</a>></td><td class="name" onclick="toggle('isAssignmentOperator2')"><a name="isAssignmentOperator2Anchor">isAssignmentOperator</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isAssignmentOperator2"><pre>Matches all kinds of assignment operators.
-Given
-void foo(int a, int b) {
+Example 1: matches a += b (matcher = binaryOperator(isAssignmentOperator()))
if (a == b)
a += b;
-}
-The matcher binaryOperator(isAssignmentOperator())
-matches a += b.
-Given
+Example 2: matches s1 = s2
+ (matcher = cxxOperatorCallExpr(isAssignmentOperator()))
struct S { S& operator=(const S&); };
void x() { S s1, s2; s1 = s2; }
-
-The matcher cxxOperatorCallExpr(isAssignmentOperator())
-matches s1 = s2.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRewrittenBinaryOperator.html">CXXRewrittenBinaryOperator</a>></td><td class="name" onclick="toggle('isComparisonOperator2')"><a name="isComparisonOperator2Anchor">isComparisonOperator</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isComparisonOperator2"><pre>Matches comparison operators.
-Given
-void foo(int a, int b) {
+Example 1: matches a == b (matcher = binaryOperator(isComparisonOperator()))
if (a == b)
a += b;
-}
-The matcher binaryOperator(isComparisonOperator())
-matches a == b
-Given
+Example 2: matches s1 < s2
+ (matcher = cxxOperatorCallExpr(isComparisonOperator()))
struct S { bool operator<(const S& other); };
void x(S s1, S s2) { bool b1 = s1 < s2; }
-
-The matcher cxxOperatorCallExpr(isComparisonOperator())
-matches s1 < s2
</pre></td></tr>
@@ -5312,15 +3931,12 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="argumentCountAtLeast2"><pre>Checks that a call expression or a constructor call expression has at least
the specified number of arguments (including absent default arguments).
-Given
+Example matches f(0, 0) and g(0, 0, 0)
+(matcher = callExpr(argumentCountAtLeast(2)))
void f(int x, int y);
void g(int x, int y, int z);
- void foo() {
- f(0, 0);
- g(0, 0, 0);
- }
-The matcher callExpr(argumentCountAtLeast(2))
-matches f(0, 0) and g(0, 0, 0)
+ f(0, 0);
+ g(0, 0, 0);
</pre></td></tr>
@@ -5328,13 +3944,9 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="argumentCountIs2"><pre>Checks that a call expression or a constructor call expression has
a specific number of arguments (including absent default arguments).
-Given
+Example matches f(0, 0) (matcher = callExpr(argumentCountIs(2)))
void f(int x, int y);
- void foo() {
- f(0, 0);
- }
-The matcher callExpr(argumentCountIs(2))
-matches f(0, 0)
+ f(0, 0);
</pre></td></tr>
@@ -5342,15 +3954,12 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="argumentCountAtLeast0"><pre>Checks that a call expression or a constructor call expression has at least
the specified number of arguments (including absent default arguments).
-Given
+Example matches f(0, 0) and g(0, 0, 0)
+(matcher = callExpr(argumentCountAtLeast(2)))
void f(int x, int y);
void g(int x, int y, int z);
- void foo() {
- f(0, 0);
- g(0, 0, 0);
- }
-The matcher callExpr(argumentCountAtLeast(2))
-matches f(0, 0) and g(0, 0, 0)
+ f(0, 0);
+ g(0, 0, 0);
</pre></td></tr>
@@ -5358,20 +3967,16 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="argumentCountIs0"><pre>Checks that a call expression or a constructor call expression has
a specific number of arguments (including absent default arguments).
-Given
+Example matches f(0, 0) (matcher = callExpr(argumentCountIs(2)))
void f(int x, int y);
- void foo() {
- f(0, 0);
- }
-The matcher callExpr(argumentCountIs(2))
-matches f(0, 0)
+ f(0, 0);
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>></td><td class="name" onclick="toggle('usesADL0')"><a name="usesADL0Anchor">usesADL</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="usesADL0"><pre>Matches call expressions which were resolved using ADL.
-Given
+Example matches y(x) but not y(42) or NS::y(x).
namespace NS {
struct X {};
void y(X);
@@ -5387,20 +3992,15 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
using NS::y;
y(x); // Found by both unqualified lookup and ADL, doesn't match
}
-
-
-The matcher callExpr(usesADL())
-matches y(x), but not y(42) or NS::y(x).
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CastExpr.html">CastExpr</a>></td><td class="name" onclick="toggle('hasCastKind0')"><a name="hasCastKind0Anchor">hasCastKind</a></td><td>CastKind Kind</td></tr>
<tr><td colspan="4" class="doc" id="hasCastKind0"><pre>Matches casts that has a given cast kind.
-Given
+Example: matches the implicit cast around 0
+(matcher = castExpr(hasCastKind(CK_NullToPointer)))
int *p = 0;
-The matcher castExpr(hasCastKind(CK_NullToPointer))
-matches the implicit cast around 0
If the matcher is use from clang-query, CastKind parameter
should be passed as a quoted string. e.g., hasCastKind("CK_NullToPointer").
@@ -5415,27 +4015,22 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="equals3"><pre>Matches literals that are equal to the given value of type ValueT.
Given
-void f(char, bool, double, int);
-void foo() {
f('false, 3.14, 42);
-}
-
-The matcher characterLiteral(equals(0U)) matches 'The matchers cxxBoolLiteral(equals(false)) and
-cxxBoolLiteral(equals(0)) match false.
-The matcher floatLiteral(equals(3.14)) matches 3.14.
-The matcher integerLiteral(equals(42)) matches 42.
+characterLiteral(equals(0))
+ matches 'cxxBoolLiteral(equals(false)) and cxxBoolLiteral(equals(0))
+ match false
+floatLiteral(equals(3.14)) and floatLiteral(equals(314e-2))
+ match 3.14
+integerLiteral(equals(42))
+ matches 42
Note that you cannot directly match a negative numeric literal because the
minus sign is not part of the literal: It is a unary operator whose operand
is the positive numeric literal. Instead, you must use a unaryOperator()
matcher to match the minus sign:
-Given
- int val = -1;
-
-The matcher unaryOperator(hasOperatorName("-"),
- hasUnaryOperand(integerLiteral(equals(1))))
-matches -1.
+unaryOperator(hasOperatorName("-"),
+ hasUnaryOperand(integerLiteral(equals(13))))
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>>
@@ -5456,10 +4051,8 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
Given
template<typename T> struct C {};
C<int> c;
-
-The matcher
classTemplateSpecializationDecl(templateArgumentCountIs(1))
-matches struct C<int>.
+ matches C<int>.
</pre></td></tr>
@@ -5468,11 +4061,9 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
child statements.
Example: Given
-void foo() {
{ for (;;) {} }
-}
-The matcher compoundStmt(statementCountIs(0))
-{}
+compoundStmt(statementCountIs(0)))
+ matches '{}'
but does not match the outer compound statement.
</pre></td></tr>
@@ -5487,11 +4078,10 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
char *s = "abcd";
wchar_t *ws = L"abcd";
char *w = "a";
-
-The matcher constantArrayType(hasSize(42))
-matches int[42] twice.
-The matcher stringLiteral(hasSize(4))
-matches "abcd" and L"abcd".
+constantArrayType(hasSize(42))
+ matches "int a[42]" and "int b[2 * 21]"
+stringLiteral(hasSize(4))
+ matches "abcd", L"abcd"
</pre></td></tr>
@@ -5499,15 +4089,12 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="declCountIs0"><pre>Matches declaration statements that contain a specific number of
declarations.
-Given
- void foo() {
- int a, b;
- int c;
- int d = 2, e;
- }
-The matcher declStmt(declCountIs(2))
-matches int a, b; and int d = 2, e;,
-but does not match int c;
+Example: Given
+ int a, b;
+ int c;
+ int d = 2, e;
+declCountIs(2)
+ matches 'int a, b;' and 'int d = 2, e;', but not 'int c;'.
</pre></td></tr>
@@ -5518,11 +4105,10 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
Given
class X { int a; int b; };
-
-The matcher cxxRecordDecl(
+cxxRecordDecl(
has(fieldDecl(hasName("a"), hasType(type().bind("t")))),
has(fieldDecl(hasName("b"), hasType(type(equalsBoundNode("t"))))))
- matches X, as a and b have the same type.
+ matches the class X, as a and b have the same type.
Note that when multiple matches are involved via forEach* matchers,
equalsBoundNodes acts as a filter.
@@ -5546,13 +4132,10 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="hasAttr0"><pre>Matches declaration that has a given attribute.
Given
- __attribute__((device)) void f() {}
-
-The matcher decl(hasAttr(clang::attr::CUDADevice))
-matches f.
-If the matcher is used from clang-query, attr::Kind
-parameter should be passed as a quoted string. e.g.,
-hasAttr("attr::CUDADevice").
+ __attribute__((device)) void f() { ... }
+decl(hasAttr(clang::attr::CUDADevice)) matches the function declaration of
+f. If the matcher is used from clang-query, attr::Kind parameter should be
+passed as a quoted string. e.g., hasAttr("attr::CUDADevice").
</pre></td></tr>
@@ -5561,15 +4144,6 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
Does not match if only part of the statement is expanded from that macro or
if different parts of the statement are expanded from different
appearances of the macro.
-
-Given
- #define A 0
- #define B A
- int c = B;
-
-The matcher integerLiteral(isExpandedFromMacro("A"))
-matches the literal expanded at the initializer B of the variable
-c .
</pre></td></tr>
@@ -5577,25 +4151,12 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="isExpansionInFileMatching0"><pre>Matches AST nodes that were expanded within files whose name is
partially matching a given regex.
-Given the headers Y.h
- #pragma once
- typedef int my_y_int;
-and X.h
- #pragma once
- typedef int my_x_int;
-and the source code
- #include "X.h"
- #include "Y.h"
- typedef int my_main_file_int;
- my_main_file_int a = 0;
- my_x_int b = 1;
- my_y_int c = 2;
-
-The matcher
-typedefDecl(isExpansionInFileMatching("Y.h"))
-matches typedef int my_y_int,
-but does not match typedef int my_main_file_int or
-typedef int my_x_int.
+Example matches Y but not X
+ (matcher = cxxRecordDecl(isExpansionInFileMatching("AST.*"))
+ #include "ASTMatcher.h"
+ class X {};
+ASTMatcher.h:
+ class Y {};
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>>
@@ -5608,18 +4169,12 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('isExpansionInMainFile0')"><a name="isExpansionInMainFile0Anchor">isExpansionInMainFile</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isExpansionInMainFile0"><pre>Matches AST nodes that were expanded within the main-file.
-Given the header Y.h
- #pragma once
- typedef int my_header_int;
-and the source file
- #include "Y.h"
- typedef int my_main_file_int;
- my_main_file_int a = 0;
- my_header_int b = 1;
-
-The matcher typedefDecl(isExpansionInMainFile())
-matches typedef int my_main_file_int,
-but does not match typedef int my_header_int.
+Example matches X but not Y
+ (matcher = cxxRecordDecl(isExpansionInMainFile())
+ #include <Y.h>
+ class X {};
+Y.h:
+ class Y {};
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>>
</pre></td></tr>
@@ -5628,17 +4183,12 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('isExpansionInSystemHeader0')"><a name="isExpansionInSystemHeader0Anchor">isExpansionInSystemHeader</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isExpansionInSystemHeader0"><pre>Matches AST nodes that were expanded within system-header-files.
-Given the header SystemHeader.h
- #pragma once
- int header();
-and the source code
+Example matches Y but not X
+ (matcher = cxxRecordDecl(isExpansionInSystemHeader())
#include <SystemHeader.h>
- static int main_file();
-
-
-The matcher functionDecl(isExpansionInSystemHeader())
-matches int header(),
-but does not match static int main_file().
+ class X {};
+SystemHeader.h:
+ class Y {};
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>>
</pre></td></tr>
@@ -5647,20 +4197,6 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('isImplicit0')"><a name="isImplicit0Anchor">isImplicit</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isImplicit0"><pre>Matches an entity that has been implicitly added by the compiler (e.g.
implicit default/copy constructors).
-
-Given
- struct S {};
- void f(S obj) {
- S copy = obj;
- [&](){ return copy; };
- }
-
-
-The matcher cxxConstructorDecl(isImplicit(), isCopyConstructor())
-matches the implicit copy constructor of S.
-The matcher lambdaExpr(forEachLambdaCapture(
- lambdaCapture(isImplicit()))) matches [&](){ return copy; },
-because it implicitly captures copy .
</pre></td></tr>
@@ -5678,14 +4214,11 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
namespace {
class vector {}; // #2
namespace foo {
- class vector {}; // #3
+ class vector{}; // #3
}
}
-
-The matcher cxxRecordDecl(hasName("vector"),
- isInAnonymousNamespace())
-matches vector,
-twice per declaration at #1, #2 and #3.
+cxxRecordDecl(hasName("vector"), isInAnonymousNamespace()) will match
+#1, #2 and #3.
</pre></td></tr>
@@ -5708,9 +4241,7 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
}
}
}
-
-The matcher cxxRecordDecl(hasName("vector"), isInStdNamespace())
-matches class vector {} inside of namespace std.
+cxxRecordDecl(hasName("vector"), isInStdNamespace()) will match only #1.
</pre></td></tr>
@@ -5720,14 +4251,10 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
Given
template<typename T> void A(T t) { T i; }
- void foo() {
- A(0);
- A(0U);
- }
-
-The matcher functionDecl(isInstantiated())
-matches the two instantiations of void A(T t) { T i; } that
-are generated for int , and for int}.
+ A(0);
+ A(0U);
+functionDecl(isInstantiated())
+ matches 'A(int) {...};' and 'A(unsigned) {...}'.
</pre></td></tr>
@@ -5735,25 +4262,16 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="isPrivate0"><pre>Matches private C++ declarations and C++ base specifers that specify private
inheritance.
-Given
+Examples:
class C {
public: int a;
protected: int b;
- private: int c;
+ private: int c; // fieldDecl(isPrivate()) matches 'c'
};
-The matcher fieldDecl(isPrivate())
-matches c.
-
struct Base {};
- struct Derived1 : private Base {}; // Base
- class Derived2 : Base {}; // Base
-
-The matcher
-cxxRecordDecl(hasAnyBase(cxxBaseSpecifier(isPrivate()).bind("base")))
-matches Derived1 and Derived2, with
-cxxBaseSpecifier(isPrivate()) matching
-Base.
+ struct Derived1 : private Base {}; // matches 'Base'
+ class Derived2 : Base {}; // matches 'Base'
</pre></td></tr>
@@ -5761,24 +4279,15 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="isProtected0"><pre>Matches protected C++ declarations and C++ base specifers that specify
protected inheritance.
-Given
+Examples:
class C {
public: int a;
- protected: int b;
+ protected: int b; // fieldDecl(isProtected()) matches 'b'
private: int c;
};
-The matcher fieldDecl(isProtected())
-matches b.
-
class Base {};
- class Derived : protected Base {};
-
-The matcher
-cxxRecordDecl(hasAnyBase(cxxBaseSpecifier(isProtected()).bind("base")))
-matches Derived, with
-cxxBaseSpecifier(isProtected()) matching
-Base.
+ class Derived : protected Base {}; // matches 'Base'
</pre></td></tr>
@@ -5786,26 +4295,16 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="isPublic0"><pre>Matches public C++ declarations and C++ base specifers that specify public
inheritance.
-Given
+Examples:
class C {
- public: int a;
+ public: int a; // fieldDecl(isPublic()) matches 'a'
protected: int b;
private: int c;
};
-The matcher fieldDecl(isPublic())
-matches a.
-
-Given
class Base {};
- class Derived1 : public Base {};
- struct Derived2 : Base {};
-
-The matcher
-cxxRecordDecl(hasAnyBase(cxxBaseSpecifier(isPublic()).bind("base")))
-matches Derived1 and Derived2,
-with cxxBaseSpecifier(isPublic()) matching
-public Base and Base.
+ class Derived1 : public Base {}; // matches 'Base'
+ struct Derived2 : Base {}; // matches 'Base'
</pre></td></tr>
@@ -5814,24 +4313,20 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
a specific number of designators.
Example: Given
- struct point2 { double x; double y; };
- struct point2 ptarray[10] = { [0].x = 1.0 };
- struct point2 pt = { .x = 2.0 };
-
-The matcher designatedInitExpr(designatorCountIs(2))
-matches [0].x = 1.0, but not .x = 2.0.
+ point ptarray[10] = { [2].y = 1.0, [0].x = 1.0 };
+ point ptarray2[10] = { [2].y = 1.0, [2].x = 0.0, [0].x = 1.0 };
+designatorCountIs(2)
+ matches '{ [2].y = 1.0, [0].x = 1.0 }',
+ but not '{ [2].y = 1.0, [2].x = 0.0, [0].x = 1.0 }'.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1EnumDecl.html">EnumDecl</a>></td><td class="name" onclick="toggle('isScoped0')"><a name="isScoped0Anchor">isScoped</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isScoped0"><pre>Matches C++11 scoped enum declaration.
-Given
+Example matches Y (matcher = enumDecl(isScoped()))
enum X {};
enum class Y {};
-
-The matcher enumDecl(isScoped())
-matches enum class Y {}
</pre></td></tr>
@@ -5845,12 +4340,8 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
sizeof is known (std::size_t) and therefore the size of the outer
sizeof is known.
template<typename T>
- void f(T x, T y) { sizeof(T() + T()); }
-
-The matcher expr(isInstantiationDependent())
-matches sizeof(T() + T()),
-(T() + T()),
-T() + T() and T().
+ void f(T x, T y) { sizeof(sizeof(T() + T()); }
+expr(isInstantiationDependent()) matches sizeof(sizeof(T() + T())
</pre></td></tr>
@@ -5864,9 +4355,7 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
void add(T x, int y) {
x + y;
}
-
-The matcher expr(isTypeDependent())
-matches x + y and x.
+expr(isTypeDependent()) matches x + y
</pre></td></tr>
@@ -5877,9 +4366,7 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
For example, the array bound of "Chars" in the following example is
value-dependent.
template<int Size> int f() { return Size; }
-
-The matcher expr(isValueDependent())
-matches the return value Size.
+expr(isValueDependent()) matches return Size
</pre></td></tr>
@@ -5887,22 +4374,16 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="nullPointerConstant0"><pre>Matches expressions that resolve to a null pointer constant, such as
GNU's __null, C++11's nullptr, or C's NULL macro.
-Given
- #define NULL 0
+Given:
void *v1 = NULL;
void *v2 = nullptr;
void *v3 = __null; // GNU extension
char *cp = (char *)0;
int *ip = 0;
int i = 0;
-
-The matcher expr(nullPointerConstant())
-matches the initializer NULL of v1,
-matches the initializer nullptr of v2,
-matches the initializer __null of v3,
-matches the initializer 0 of cp and
-matches the initializer 0 of ip,
-but does not match the initializer i of i.
+expr(nullPointerConstant())
+ matches the initializer for v1, v2, v3, cp, and ip. Does not match the
+ initializer for i.
</pre></td></tr>
@@ -5916,10 +4397,8 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
int b : 4;
int c : 2;
};
-
-The matcher fieldDecl(hasBitWidth(2))
-matches a and c,
-but not b.
+fieldDecl(hasBitWidth(2))
+ matches 'int a;' and 'int c;' but not 'int b;'.
</pre></td></tr>
@@ -5931,10 +4410,8 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
int a : 2;
int b;
};
-
-The matcher fieldDecl(isBitField())
-matches a,
-but does not match b.
+fieldDecl(isBitField())
+ matches 'int a;' but not 'int b;'.
</pre></td></tr>
@@ -5942,27 +4419,22 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="equals1"><pre>Matches literals that are equal to the given value of type ValueT.
Given
-void f(char, bool, double, int);
-void foo() {
f('false, 3.14, 42);
-}
-
-The matcher characterLiteral(equals(0U)) matches 'The matchers cxxBoolLiteral(equals(false)) and
-cxxBoolLiteral(equals(0)) match false.
-The matcher floatLiteral(equals(3.14)) matches 3.14.
-The matcher integerLiteral(equals(42)) matches 42.
+characterLiteral(equals(0))
+ matches 'cxxBoolLiteral(equals(false)) and cxxBoolLiteral(equals(0))
+ match false
+floatLiteral(equals(3.14)) and floatLiteral(equals(314e-2))
+ match 3.14
+integerLiteral(equals(42))
+ matches 42
Note that you cannot directly match a negative numeric literal because the
minus sign is not part of the literal: It is a unary operator whose operand
is the positive numeric literal. Instead, you must use a unaryOperator()
matcher to match the minus sign:
-Given
- int val = -1;
-
-The matcher unaryOperator(hasOperatorName("-"),
- hasUnaryOperand(integerLiteral(equals(1))))
-matches -1.
+unaryOperator(hasOperatorName("-"),
+ hasUnaryOperand(integerLiteral(equals(13))))
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>>
@@ -5980,30 +4452,6 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
"operator" prefix: e.g. "<<".
hasAnyOverloadedOperatorName("+", "-")
-
-Given
- struct Point { double x; double y; };
- Point operator+(const Point&, const Point&);
- Point operator-(const Point&, const Point&);
-
- Point sub(Point a, Point b) {
- return b - a;
- }
-
-
-The matcher functionDecl(hasAnyOverloadedOperatorName("+", "-")),
-which is equivalent to
-functionDecl(anyOf(hasAnyOverloadedOperatorName("+"),
-hasOverloadedOperatorName("-"))),
-matches Point operator+(const Point&, const Point&) and
-Point operator-(const Point&, const Point&).
-The matcher
-cxxOperatorCallExpr(hasAnyOverloadedOperatorName("+", "-")),
-which is equivalent to
-cxxOperatorCallExpr(anyOf(hasOverloadedOperatorName("+"),
-hasOverloadedOperatorName("-"))),
-matches b - a.
-
Is equivalent to
anyOf(hasOverloadedOperatorName("+"), hasOverloadedOperatorName("-"))
</pre></td></tr>
@@ -6012,32 +4460,17 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>></td><td class="name" onclick="toggle('hasDynamicExceptionSpec0')"><a name="hasDynamicExceptionSpec0Anchor">hasDynamicExceptionSpec</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasDynamicExceptionSpec0"><pre>Matches functions that have a dynamic exception specification.
-Given
- void f(int);
- void g(int) noexcept;
- void h(int) noexcept(true);
- void i(int) noexcept(false);
- void j(int) throw();
- void k(int) throw(int);
- void l(int) throw(...);
-
-The matcher functionDecl(hasDynamicExceptionSpec())
-matches the declarations void j(int) throw(),
-void k(int) throw(int)
-and void l(int) throw(...),
-but does not match void f(int), void g(int) noexcept,
-void h(int) noexcept(true)
-or void i(int) noexcept(true).
-The matcher
-functionProtoType(hasDynamicExceptionSpec()) matches
-the type void (int) throw() of j ,
-the type void (int) throw(int) of k and
-the type void (int) throw(...) of l .
-It does not match
-the type void (int) noexcept of f ,
-the type void (int) noexcept of g ,
-the type void (int) noexcept(int) of h or
-the type void (int) noexcept(...) of i .
+Given:
+ void f();
+ void g() noexcept;
+ void h() noexcept(true);
+ void i() noexcept(false);
+ void j() throw();
+ void k() throw(int);
+ void l() throw(...);
+functionDecl(hasDynamicExceptionSpec()) and
+ functionProtoType(hasDynamicExceptionSpec())
+ match the declarations of j, k, and l, but not f, g, h, or i.
</pre></td></tr>
@@ -6047,19 +4480,16 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
Matches overloaded operator names specified in strings without the
"operator" prefix: e.g. "<<".
-Given
- struct A { int operator*(); };
+Given:
+ class A { int operator*(); };
const A &operator<<(const A &a, const A &b);
- void f(A a) {
- a << a; // <-- This matches
- }
-
+ A a;
+ a << a; // <-- This matches
-The matcher cxxOperatorCallExpr(hasOverloadedOperatorName("<<"))
-matches a << a.
-The matcher
+cxxOperatorCallExpr(hasOverloadedOperatorName("<<"))) matches the
+specified line and
cxxRecordDecl(hasMethod(hasOverloadedOperatorName("*")))
-matches struct A { int operator*(); }.
+matches the declaration of A.
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>>
</pre></td></tr>
@@ -6068,12 +4498,9 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>></td><td class="name" onclick="toggle('hasTrailingReturn0')"><a name="hasTrailingReturn0Anchor">hasTrailingReturn</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasTrailingReturn0"><pre>Matches a function declared with a trailing return type.
-Given
+Example matches Y (matcher = functionDecl(hasTrailingReturn()))
int X() {}
auto Y() -> int {}
-
-The matcher functionDecl(hasTrailingReturn())
-matches auto Y() -> int {}.
</pre></td></tr>
@@ -6081,18 +4508,15 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="isConsteval0"><pre>Matches consteval function declarations and if consteval/if ! consteval
statements.
-Given
+Given:
consteval int a();
void b() { if consteval {} }
void c() { if ! consteval {} }
void d() { if ! consteval {} else {} }
-
-The matcher functionDecl(isConsteval())
-matches a.
-The matcher ifStmt(isConsteval())
-matches the if statements
-if consteval {}, if ! consteval {} and
-if ! consteval {} else {}.
+functionDecl(isConsteval())
+ matches the declaration of "int a()".
+ifStmt(isConsteval())
+ matches the if statement in "void b()", "void c()", "void d()".
</pre></td></tr>
@@ -6100,30 +4524,27 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="isConstexpr1"><pre>Matches constexpr variable and function declarations,
and if constexpr.
-Given
+Given:
constexpr int foo = 42;
constexpr int bar();
void baz() { if constexpr(1 > 0) {} }
-
-The matcher varDecl(isConstexpr())
-matches foo.
-The matcher functionDecl(isConstexpr())
-matches bar.
-The matcher ifStmt(isConstexpr())
-matches if constexpr(1 > 0) {}.
+varDecl(isConstexpr())
+ matches the declaration of foo.
+functionDecl(isConstexpr())
+ matches the declaration of bar.
+ifStmt(isConstexpr())
+ matches the if statement in baz.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>></td><td class="name" onclick="toggle('isDefaulted0')"><a name="isDefaulted0Anchor">isDefaulted</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isDefaulted0"><pre>Matches defaulted function declarations.
-Given
+Given:
class A { ~A(); };
class B { ~B() = default; };
-
-The matcher functionDecl(isDefaulted())
- matches ~B() = default,
-but does not match ~A().
+functionDecl(isDefaulted())
+ matches the declaration of ~B, but not ~A.
</pre></td></tr>
@@ -6137,14 +4558,6 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
extern int vb; // Doesn't match, as it doesn't define the variable.
void fa() {}
void fb(); // Doesn't match, as it has no body.
-
-The matcher tagDecl(isDefinition())
-matches A
-The matcher varDecl(isDefinition())
-matches va
-The matcher functionDecl(isDefinition())
-matches fa
-
@interface X
- (void)ma; // Doesn't match, interface is declaration.
@end
@@ -6152,9 +4565,6 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
- (void)ma {}
@end
-The matcher objcMethodDecl(isDefinition())
-matches - (void)ma {}
-
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>>
</pre></td></tr>
@@ -6163,13 +4573,11 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>></td><td class="name" onclick="toggle('isDeleted0')"><a name="isDeleted0Anchor">isDeleted</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isDeleted0"><pre>Matches deleted function declarations.
-Given
+Given:
void Func();
void DeletedFunc() = delete;
-
-The matcher functionDecl(isDeleted())
-matches DeletedFunc,
-but does not match Func.
+functionDecl(isDeleted())
+ matches the declaration of DeletedFunc, but not Func.
</pre></td></tr>
@@ -6180,9 +4588,8 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
Given
template<typename T> void A(T t) { }
template<> void A(int N) { }
-
-The matcher functionDecl(isExplicitTemplateSpecialization())
- matches the specialization template<> void A(int N) { }.
+functionDecl(isExplicitTemplateSpecialization())
+ matches the specialization A<int>().
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>>
</pre></td></tr>
@@ -6191,21 +4598,17 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>></td><td class="name" onclick="toggle('isExternC0')"><a name="isExternC0Anchor">isExternC</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isExternC0"><pre>Matches extern "C" function or variable declarations.
-Given
+Given:
extern "C" void f() {}
extern "C" { void g() {} }
void h() {}
extern "C" int x = 1;
extern "C" int y = 2;
int z = 3;
-
-The matcher functionDecl(isExternC())
-matches f
-and g.
-The matcher varDecl(isExternC())
-matches x
-and y,
-but does not match z.
+functionDecl(isExternC())
+ matches the declaration of f and g, but not the declaration of h.
+varDecl(isExternC())
+ matches the declaration of x and y, but not the declaration of z.
</pre></td></tr>
@@ -6220,22 +4623,15 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
inline namespace m {}
}
inline int Foo = 5;
-
-The matcher functionDecl(isInline()) matches f.
-The matcher namespaceDecl(isInline()) matches m.
-The matcher varDecl(isInline()) matches Foo
+functionDecl(isInline()) will match ::f().
+namespaceDecl(isInline()) will match n::m.
+varDecl(isInline()) will match Foo;
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>></td><td class="name" onclick="toggle('isMain0')"><a name="isMain0Anchor">isMain</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isMain0"><pre>Determines whether the function is "main", which is the entry point
into an executable program.
-
-Given
- void f();
- int main() {}
-
-The matcher functionDecl(isMain()) matches int main() {}.
</pre></td></tr>
@@ -6247,38 +4643,23 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
[[noreturn]] void a();
__attribute__((noreturn)) void b();
struct c { [[noreturn]] c(); };
-
-The matcher functionDecl(isNoReturn())
-match a, b
-and c
-but do not match nope
+functionDecl(isNoReturn())
+ matches all of those except
+ void nope();
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>></td><td class="name" onclick="toggle('isNoThrow0')"><a name="isNoThrow0Anchor">isNoThrow</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isNoThrow0"><pre>Matches functions that have a non-throwing exception specification.
-Given
- void f(int);
- void g(int) noexcept;
- void h(int) noexcept(false);
- void i(int) throw();
- void j(int) throw(int);
-
-The matcher functionDecl(isNoThrow())
-matches the declaration void g(int) noexcept
-and void i(int) throw(),
-but does not match void f(int),
-void h(int) noexcept(false)
-or void j(int) throw(int).
-The matcher
-functionProtoType(isNoThrow())
-matches the type void (int) throw() of i
-and the type void (int) noexcept of g,
-but does not match
-the type void (int) of f ,
-the type void (int) noexcept(false) of h or
-the type void (int) throw(int) of j .
+Given:
+ void f();
+ void g() noexcept;
+ void h() throw();
+ void i() throw(int);
+ void j() noexcept(false);
+functionDecl(isNoThrow()) and functionProtoType(isNoThrow())
+ match the declarations of g, and h, but not f, i or j.
</pre></td></tr>
@@ -6286,15 +4667,15 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="isStaticStorageClass0"><pre>Matches variable/function declarations that have "static" storage
class specifier ("static" keyword) written in the source.
-Given
+Given:
static void f() {}
static int i = 0;
extern int j;
int k;
-The matcher functionDecl(isStaticStorageClass())
- matches f
-The matcher varDecl(isStaticStorageClass())
- matches i
+functionDecl(isStaticStorageClass())
+ matches the function declaration f.
+varDecl(isStaticStorageClass())
+ matches the variable declaration i.
</pre></td></tr>
@@ -6303,36 +4684,18 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
member variable template instantiations.
Given
- template <typename T> class X {};
- class A {};
- X<A> x;
-
-The matcher cxxRecordDecl(hasName("::X"),
-isTemplateInstantiation())
-matches class X<class A>.
- template <typename T> class X {};
- class A {};
- template class X<A>;
-
-The matcher cxxRecordDecl(hasName("::X"),
-isTemplateInstantiation())
-matches template class X<A>
- template <typename T> class X {};
- class A {};
- extern template class X<A>;
-
-The matcher cxxRecordDecl(hasName("::X"),
-isTemplateInstantiation())
-matches extern template class X<A>
+ template <typename T> class X {}; class A {}; X<A> x;
+or
+ template <typename T> class X {}; class A {}; template class X<A>;
+or
+ template <typename T> class X {}; class A {}; extern template class X<A>;
+cxxRecordDecl(hasName("::X"), isTemplateInstantiation())
+ matches the template instantiation of X<A>.
But given
- template <typename T> class X {};
- class A {};
- template <> class X<A> {};
- X<A> x;
-
-The matcher cxxRecordDecl(hasName("::X"),
-isTemplateInstantiation())
+ template <typename T> class X {}; class A {};
+ template <> class X<A> {}; X<A> x;
+cxxRecordDecl(hasName("::X"), isTemplateInstantiation())
does not match, as X<A> is an explicit template specialization.
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>>
@@ -6348,25 +4711,17 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
void g(int);
template <typename... Ts> void h(Ts...);
void i();
-
-The matcher functionDecl(isVariadic())
-matches void f(...),
-but does not match void g(int),
-template <typename... Ts> void h(Ts...),
-or void i().
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>></td><td class="name" onclick="toggle('isWeak0')"><a name="isWeak0Anchor">isWeak</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isWeak0"><pre>Matches weak function declarations.
-Given
- static void f();
- void g() __attribute__((weak));
-The matcher functionDecl(isWeak())
- matches the weak declaration
-void g() __attribute__((weak)),
-but does not match static void foo_v1().
+Given:
+ void foo() __attribute__((__weakref__("__foo")));
+ void bar();
+functionDecl(isWeak())
+ matches the weak declaration "foo", but not "bar".
</pre></td></tr>
@@ -6380,71 +4735,43 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
void h(int i, int j);
void j(int i);
void k(int x, int y, int z, ...);
-The matcher functionDecl(parameterCountIs(2))
-matches g and h
-The matcher functionProtoType(parameterCountIs(1))
-matches the type void (int) of f and j.
-The matcher functionProtoType(parameterCountIs(3)) matches the
-type void (int, int, int, ...) of k.
+functionDecl(parameterCountIs(2))
+ matches g and h
+functionProtoType(parameterCountIs(2))
+ matches g and h
+functionProtoType(parameterCountIs(3))
+ matches k
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionProtoType.html">FunctionProtoType</a>></td><td class="name" onclick="toggle('hasDynamicExceptionSpec1')"><a name="hasDynamicExceptionSpec1Anchor">hasDynamicExceptionSpec</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasDynamicExceptionSpec1"><pre>Matches functions that have a dynamic exception specification.
-Given
- void f(int);
- void g(int) noexcept;
- void h(int) noexcept(true);
- void i(int) noexcept(false);
- void j(int) throw();
- void k(int) throw(int);
- void l(int) throw(...);
-
-The matcher functionDecl(hasDynamicExceptionSpec())
-matches the declarations void j(int) throw(),
-void k(int) throw(int)
-and void l(int) throw(...),
-but does not match void f(int), void g(int) noexcept,
-void h(int) noexcept(true)
-or void i(int) noexcept(true).
-The matcher
-functionProtoType(hasDynamicExceptionSpec()) matches
-the type void (int) throw() of j ,
-the type void (int) throw(int) of k and
-the type void (int) throw(...) of l .
-It does not match
-the type void (int) noexcept of f ,
-the type void (int) noexcept of g ,
-the type void (int) noexcept(int) of h or
-the type void (int) noexcept(...) of i .
+Given:
+ void f();
+ void g() noexcept;
+ void h() noexcept(true);
+ void i() noexcept(false);
+ void j() throw();
+ void k() throw(int);
+ void l() throw(...);
+functionDecl(hasDynamicExceptionSpec()) and
+ functionProtoType(hasDynamicExceptionSpec())
+ match the declarations of j, k, and l, but not f, g, h, or i.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionProtoType.html">FunctionProtoType</a>></td><td class="name" onclick="toggle('isNoThrow1')"><a name="isNoThrow1Anchor">isNoThrow</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isNoThrow1"><pre>Matches functions that have a non-throwing exception specification.
-Given
- void f(int);
- void g(int) noexcept;
- void h(int) noexcept(false);
- void i(int) throw();
- void j(int) throw(int);
-
-The matcher functionDecl(isNoThrow())
-matches the declaration void g(int) noexcept
-and void i(int) throw(),
-but does not match void f(int),
-void h(int) noexcept(false)
-or void j(int) throw(int).
-The matcher
-functionProtoType(isNoThrow())
-matches the type void (int) throw() of i
-and the type void (int) noexcept of g,
-but does not match
-the type void (int) of f ,
-the type void (int) noexcept(false) of h or
-the type void (int) throw(int) of j .
+Given:
+ void f();
+ void g() noexcept;
+ void h() throw();
+ void i() throw(int);
+ void j() noexcept(false);
+functionDecl(isNoThrow()) and functionProtoType(isNoThrow())
+ match the declarations of g, and h, but not f, i or j.
</pre></td></tr>
@@ -6458,12 +4785,12 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
void h(int i, int j);
void j(int i);
void k(int x, int y, int z, ...);
-The matcher functionDecl(parameterCountIs(2))
-matches g and h
-The matcher functionProtoType(parameterCountIs(1))
-matches the type void (int) of f and j.
-The matcher functionProtoType(parameterCountIs(3)) matches the
-type void (int, int, int, ...) of k.
+functionDecl(parameterCountIs(2))
+ matches g and h
+functionProtoType(parameterCountIs(2))
+ matches g and h
+functionProtoType(parameterCountIs(3))
+ matches k
</pre></td></tr>
@@ -6471,18 +4798,15 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="isConsteval1"><pre>Matches consteval function declarations and if consteval/if ! consteval
statements.
-Given
+Given:
consteval int a();
void b() { if consteval {} }
void c() { if ! consteval {} }
void d() { if ! consteval {} else {} }
-
-The matcher functionDecl(isConsteval())
-matches a.
-The matcher ifStmt(isConsteval())
-matches the if statements
-if consteval {}, if ! consteval {} and
-if ! consteval {} else {}.
+functionDecl(isConsteval())
+ matches the declaration of "int a()".
+ifStmt(isConsteval())
+ matches the if statement in "void b()", "void c()", "void d()".
</pre></td></tr>
@@ -6490,17 +4814,16 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="isConstexpr2"><pre>Matches constexpr variable and function declarations,
and if constexpr.
-Given
+Given:
constexpr int foo = 42;
constexpr int bar();
void baz() { if constexpr(1 > 0) {} }
-
-The matcher varDecl(isConstexpr())
-matches foo.
-The matcher functionDecl(isConstexpr())
-matches bar.
-The matcher ifStmt(isConstexpr())
-matches if constexpr(1 > 0) {}.
+varDecl(isConstexpr())
+ matches the declaration of foo.
+functionDecl(isConstexpr())
+ matches the declaration of bar.
+ifStmt(isConstexpr())
+ matches the if statement in baz.
</pre></td></tr>
@@ -6512,27 +4835,22 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="equals0"><pre>Matches literals that are equal to the given value of type ValueT.
Given
-void f(char, bool, double, int);
-void foo() {
f('false, 3.14, 42);
-}
-
-The matcher characterLiteral(equals(0U)) matches 'The matchers cxxBoolLiteral(equals(false)) and
-cxxBoolLiteral(equals(0)) match false.
-The matcher floatLiteral(equals(3.14)) matches 3.14.
-The matcher integerLiteral(equals(42)) matches 42.
+characterLiteral(equals(0))
+ matches 'cxxBoolLiteral(equals(false)) and cxxBoolLiteral(equals(0))
+ match false
+floatLiteral(equals(3.14)) and floatLiteral(equals(314e-2))
+ match 3.14
+integerLiteral(equals(42))
+ matches 42
Note that you cannot directly match a negative numeric literal because the
minus sign is not part of the literal: It is a unary operator whose operand
is the positive numeric literal. Instead, you must use a unaryOperator()
matcher to match the minus sign:
-Given
- int val = -1;
-
-The matcher unaryOperator(hasOperatorName("-"),
- hasUnaryOperand(integerLiteral(equals(1))))
-matches -1.
+unaryOperator(hasOperatorName("-"),
+ hasUnaryOperand(integerLiteral(equals(13))))
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CharacterLiteral.html">CharacterLiteral</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1IntegerLiteral.html">IntegerLiteral</a>>
@@ -6558,30 +4876,14 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
return l();
}
};
-
-The matcher
lambdaExpr(hasAnyCapture(lambdaCapture(capturesThis())))
-matches [this]() { return cc; }.
+ matches `[this]() { return cc; }`.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1LambdaCapture.html">LambdaCapture</a>></td><td class="name" onclick="toggle('isImplicit2')"><a name="isImplicit2Anchor">isImplicit</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isImplicit2"><pre>Matches an entity that has been implicitly added by the compiler (e.g.
implicit default/copy constructors).
-
-Given
- struct S {};
- void f(S obj) {
- S copy = obj;
- [&](){ return copy; };
- }
-
-
-The matcher cxxConstructorDecl(isImplicit(), isCopyConstructor())
-matches the implicit copy constructor of S.
-The matcher lambdaExpr(forEachLambdaCapture(
- lambdaCapture(isImplicit()))) matches [&](){ return copy; },
-because it implicitly captures copy .
</pre></td></tr>
@@ -6600,25 +4902,14 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
};
template <class T>
class Z {
- void x() {
- this->m;
- this->t;
- this->t->m;
- }
- int m;
- T* t;
+ void x() { this->m; }
};
-
-The matcher memberExpr(isArrow())
-matches this->x, x, a,
-this->b, this->m and two times this->t,
-once for the standalone member expression, and once for the member
-expression that later accesses m .
-Additionally, it does not match this->t->t.
-The matcher cxxDependentScopeMemberExpr(isArrow())
-matches this->t->m, but not this->m or this->t.
-The matcher unresolvedMemberExpr(isArrow())
-matches this->f<T>, f<T>
+memberExpr(isArrow())
+ matches this->x, x, y.x, a, this->b
+cxxDependentScopeMemberExpr(isArrow())
+ matches this->m
+unresolvedMemberExpr(isArrow())
+ matches this->f<T>, f<T>
</pre></td></tr>
@@ -6626,43 +4917,29 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="hasAnyName0"><pre>Matches NamedDecl nodes that have any of the specified names.
This matcher is only provided as a performance optimization of hasName.
-
-Given
- void f(int a, int b);
-
-The matcher namedDecl(hasAnyName("a", "b")),
-which is equivalent to the matcher
-namedDecl(hasAnyName("a", "b")),
-matches int a and int b, but not
-void f(int a, int b).
+ hasAnyName(a, b, c)
+ is equivalent to, but faster than
+ anyOf(hasName(a), hasName(b), hasName(c))
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>></td><td class="name" onclick="toggle('hasExternalFormalLinkage0')"><a name="hasExternalFormalLinkage0Anchor">hasExternalFormalLinkage</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasExternalFormalLinkage0"><pre>Matches a declaration that has external formal linkage.
-Given
+Example matches only z (matcher = varDecl(hasExternalFormalLinkage()))
void f() {
- int a;
- static int b;
+ int x;
+ static int y;
}
-int c;
-static int d;
-The matcher varDecl(hasExternalFormalLinkage())
-matches int c,
-but not int a, static int b or int d.
-
-Given
- namespace {
- void f() {}
- }
- void g() {}
- static void h() {}
+int z;
+Example matches f() because it has external formal linkage despite being
+unique to the translation unit as though it has internal likage
+(matcher = functionDecl(hasExternalFormalLinkage()))
-The matcher functionDecl(hasExternalFormalLinkage())
-matches void g() {}, but not void f() {} or
-static void h() {}.
+namespace {
+void f() {}
+}
</pre></td></tr>
@@ -6673,22 +4950,11 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
with '<enclosing>::'.
Does not match typedefs of an underlying type with the given name.
-Given
+Example matches X (Name == "X")
class X;
-
-The matcher namedDecl(hasName("X"))
-matches class X.
-
-Given
+Example matches X (Name is one of "::a::b::X", "a::b::X", "b::X", "X")
namespace a { namespace b { class X; } }
-
-
-The matchers namedDecl(hasName("::a::b::X")),
-namedDecl(hasName("a::b::X")),
-namedDecl(hasName("b::X")) and
-namedDecl(hasName("X"))
-match class X.
</pre></td></tr>
@@ -6700,12 +4966,11 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
prefixing the name with '<enclosing>::'. Does not match typedefs
of an underlying type with the given name.
-Given
- namespace foo { namespace bar { class X; } }
-
+Example matches X (regexp == "::X")
+ class X;
-The matcher namedDecl(matchesName("^::foo:.*X"))
-matches class X.
+Example matches X (regexp is one of "::X", "^foo::.*X", among others)
+ namespace foo { namespace bar { class X; } }
If the matcher is used in clang-query, RegexFlags parameter
should be passed as a quoted string. e.g: "NoFlags".
@@ -6720,9 +4985,7 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
namespace n {
namespace {} // #1
}
-
-The matcher namespaceDecl(isAnonymous())
-matches namespace {}, but not namespace n.
+namespaceDecl(isAnonymous()) will match #1 but not ::n.
</pre></td></tr>
@@ -6737,10 +5000,9 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
inline namespace m {}
}
inline int Foo = 5;
-
-The matcher functionDecl(isInline()) matches f.
-The matcher namespaceDecl(isInline()) matches m.
-The matcher varDecl(isInline()) matches Foo
+functionDecl(isInline()) will match ::f().
+namespaceDecl(isInline()) will match n::m.
+varDecl(isInline()) will match Foo;
</pre></td></tr>
@@ -6749,23 +5011,15 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
specified.
Given
- void foo() {
- #pragma omp parallel
- ;
- #pragma omp parallel default(none)
- ;
- #pragma omp parallel default(shared)
- ;
- #pragma omp parallel default(private)
- ;
- #pragma omp parallel default(firstprivate)
- ;
- }
+ #pragma omp parallel
+ #pragma omp parallel default(none)
+ #pragma omp parallel default(shared)
+ #pragma omp parallel default(private)
+ #pragma omp parallel default(firstprivate)
-The matcher
-ompExecutableDirective(hasAnyClause(ompDefaultClause(isFirstPrivateKind())))
-matches #pragma omp parallel default(firstprivate).
+``ompDefaultClause(isFirstPrivateKind())`` matches only
+``default(firstprivate)``.
</pre></td></tr>
@@ -6773,23 +5027,14 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="isNoneKind0"><pre>Matches if the OpenMP ``default`` clause has ``none`` kind specified.
Given
- void foo() {
- #pragma omp parallel
- ;
- #pragma omp parallel default(none)
- ;
- #pragma omp parallel default(shared)
- ;
- #pragma omp parallel default(private)
- ;
- #pragma omp parallel default(firstprivate)
- ;
- }
+ #pragma omp parallel
+ #pragma omp parallel default(none)
+ #pragma omp parallel default(shared)
+ #pragma omp parallel default(private)
+ #pragma omp parallel default(firstprivate)
-The matcher
-ompExecutableDirective(hasAnyClause(ompDefaultClause(isNoneKind())))
-matches only #pragma omp parallel default(none).
+``ompDefaultClause(isNoneKind())`` matches only ``default(none)``.
</pre></td></tr>
@@ -6798,23 +5043,15 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
specified.
Given
- void foo() {
- #pragma omp parallel
- ;
+
+ #pragma omp parallel
#pragma omp parallel default(none)
- ;
#pragma omp parallel default(shared)
- ;
#pragma omp parallel default(private)
- ;
#pragma omp parallel default(firstprivate)
- ;
- }
-
-The matcher
-ompExecutableDirective(hasAnyClause(ompDefaultClause(isPrivateKind())))
-matches #pragma omp parallel default(private).
+``ompDefaultClause(isPrivateKind())`` matches only
+``default(private)``.
</pre></td></tr>
@@ -6822,23 +5059,14 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="isSharedKind0"><pre>Matches if the OpenMP ``default`` clause has ``shared`` kind specified.
Given
- void foo() {
- #pragma omp parallel
- ;
- #pragma omp parallel default(none)
- ;
+
+ #pragma omp parallel
+ #pragma omp parallel default(none)
#pragma omp parallel default(shared)
- ;
#pragma omp parallel default(private)
- ;
#pragma omp parallel default(firstprivate)
- ;
- }
-
-The matcher
-ompExecutableDirective(hasAnyClause(ompDefaultClause(isSharedKind())))
-matches #pragma omp parallel default(shared).
+``ompDefaultClause(isSharedKind())`` matches only ``default(shared)``.
</pre></td></tr>
@@ -6847,21 +5075,13 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
clause kind.
Given
- void foo() {
- #pragma omp parallel
- ;
- #pragma omp parallel for
- for (int i = 0; i < 10; ++i) {}
- #pragma omp for
- for (int i = 0; i < 10; ++i) {}
- }
+ #pragma omp parallel
+ #pragma omp parallel for
+ #pragma omp for
-The matcher
-ompExecutableDirective(isAllowedToContainClauseKind(
-OpenMPClauseKind::OMPC_default))
-matches #pragma omp parallel
-and #pragma omp parallel for.
+`ompExecutableDirective(isAllowedToContainClause(OMPC_default))`` matches
+``omp parallel`` and ``omp parallel for``.
If the matcher is use from clang-query, ``OpenMPClauseKind`` parameter
should be passed as a quoted string. e.g.,
@@ -6874,89 +5094,29 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
i.e., directives that can't have a structured block.
Given
- void foo() {
- #pragma omp parallel
- {
- #pragma omp taskyield
- }
- }
+ #pragma omp parallel
+ {}
+ #pragma omp taskyield
-The matcher ompExecutableDirective(isStandaloneDirective())
-matches #pragma omp taskyield.
+``ompExecutableDirective(isStandaloneDirective()))`` matches
+``omp taskyield``.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCInterfaceDecl.html">ObjCInterfaceDecl</a>></td><td class="name" onclick="toggle('isDerivedFrom3')"><a name="isDerivedFrom3Anchor">isDerivedFrom</a></td><td>std::string BaseName</td></tr>
<tr><td colspan="4" class="doc" id="isDerivedFrom3"><pre>Overloaded method as shortcut for isDerivedFrom(hasName(...)).
-
-Matches C++ classes that are directly or indirectly derived from a class
-matching Base, or Objective-C classes that directly or indirectly
-subclass a class matching Base.
-
-Note that a class is not considered to be derived from itself.
-
-Example matches Y, Z, C (Base == hasName("X"))
- class X {};
- class Y : public X {}; // directly derived
- class Z : public Y {}; // indirectly derived
- typedef X A;
- typedef A B;
- class C : public B {}; // derived from a typedef of X
-
- class Foo {};
- typedef Foo Alias;
- class Bar : public Alias {}; // derived from Alias, which is a
- // typedef of Foo
-
-
-The matcher cxxRecordDecl(isDerivedFrom("X"))
-matches Y, Z and C.
-The matcher cxxRecordDecl(isDerivedFrom("Foo"))
-matches Bar.
-
-In the following example, Bar matches isDerivedFrom(hasName("NSObject"))
- @interface NSObject @end
- @interface Bar : NSObject @end
-
-
-Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCInterfaceDecl.html">ObjCInterfaceDecl</a>>
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCInterfaceDecl.html">ObjCInterfaceDecl</a>></td><td class="name" onclick="toggle('isDirectlyDerivedFrom3')"><a name="isDirectlyDerivedFrom3Anchor">isDirectlyDerivedFrom</a></td><td>std::string BaseName</td></tr>
<tr><td colspan="4" class="doc" id="isDirectlyDerivedFrom3"><pre>Overloaded method as shortcut for isDirectlyDerivedFrom(hasName(...)).
-
-Given
- struct Base {};
- struct DirectlyDerived : public Base {};
- struct IndirectlyDerived : public DirectlyDerived {};
-
-
-The matcher cxxRecordDecl(isDirectlyDerivedFrom("Base"))
-matches DirectlyDerived, but not
-IndirectlyDerived.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCInterfaceDecl.html">ObjCInterfaceDecl</a>></td><td class="name" onclick="toggle('isSameOrDerivedFrom3')"><a name="isSameOrDerivedFrom3Anchor">isSameOrDerivedFrom</a></td><td>std::string BaseName</td></tr>
-<tr><td colspan="4" class="doc" id="isSameOrDerivedFrom3"><pre>Similar to isDerivedFrom(), but also matches classes that directly
-match Base.
-Overloaded method as shortcut for
+<tr><td colspan="4" class="doc" id="isSameOrDerivedFrom3"><pre>Overloaded method as shortcut for
isSameOrDerivedFrom(hasName(...)).
-
-Given
- class X {};
- class Y : public X {}; // directly derived
- class Z : public Y {}; // indirectly derived
- typedef X A;
- typedef A B;
- class C : public B {}; // derived from a typedef of X
-
-The matcher
-cxxRecordDecl(isSameOrDerivedFrom("X"), isDefinition())
-matches class X {}, class Y : public X {},
-class Z : public Y {} and class C : public B {}.
</pre></td></tr>
@@ -6964,15 +5124,12 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="argumentCountAtLeast3"><pre>Checks that a call expression or a constructor call expression has at least
the specified number of arguments (including absent default arguments).
-Given
+Example matches f(0, 0) and g(0, 0, 0)
+(matcher = callExpr(argumentCountAtLeast(2)))
void f(int x, int y);
void g(int x, int y, int z);
- void foo() {
- f(0, 0);
- g(0, 0, 0);
- }
-The matcher callExpr(argumentCountAtLeast(2))
-matches f(0, 0) and g(0, 0, 0)
+ f(0, 0);
+ g(0, 0, 0);
</pre></td></tr>
@@ -6980,13 +5137,9 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="argumentCountIs3"><pre>Checks that a call expression or a constructor call expression has
a specific number of arguments (including absent default arguments).
-Given
+Example matches f(0, 0) (matcher = callExpr(argumentCountIs(2)))
void f(int x, int y);
- void foo() {
- f(0, 0);
- }
-The matcher callExpr(argumentCountIs(2))
-matches f(0, 0)
+ f(0, 0);
</pre></td></tr>
@@ -6994,27 +5147,24 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="hasAnySelector0"><pre>Matches when at least one of the supplied string equals to the
Selector.getAsString()
+ matcher = objCMessageExpr(hasSelector("methodA:", "methodB:"));
+ matches both of the expressions below:
[myObj methodA:argA];
[myObj methodB:argB];
-
- The matcher objCMessageExpr(hasSelector("methodA:", "methodB:"));
- matches [myObj methodA:argA]; and [myObj methodB:argB];
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>></td><td class="name" onclick="toggle('hasKeywordSelector0')"><a name="hasKeywordSelector0Anchor">hasKeywordSelector</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasKeywordSelector0"><pre>Matches when the selector is a keyword selector
-Given
+objCMessageExpr(hasKeywordSelector()) matches the generated setFrame
+message expression in
+
UIWebView *webView = ...;
CGRect bodyFrame = webView.frame;
bodyFrame.size.height = self.bodyContentHeight;
webView.frame = bodyFrame;
// ^---- matches here
-
-
-The matcher objCMessageExpr(hasKeywordSelector()) matches the
-generated setFrame message expression in
</pre></td></tr>
@@ -7029,68 +5179,56 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>></td><td class="name" onclick="toggle('hasSelector0')"><a name="hasSelector0Anchor">hasSelector</a></td><td>std::string BaseName</td></tr>
<tr><td colspan="4" class="doc" id="hasSelector0"><pre>Matches when BaseName == Selector.getAsString()
+ matcher = objCMessageExpr(hasSelector("loadHTMLString:baseURL:"));
+ matches the outer message expr in the code below, but NOT the message
+ invocation for self.bodyView.
[self.bodyView loadHTMLString:html baseURL:NULL];
-
-The matcher
-objCMessageExpr(hasSelector("loadHTMLString:baseURL:")); matches
-the outer message expr in the code below, but NOT the message invocation
-for self.bodyView.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>></td><td class="name" onclick="toggle('hasUnarySelector0')"><a name="hasUnarySelector0Anchor">hasUnarySelector</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasUnarySelector0"><pre>Matches when the selector is a Unary Selector
-Given
- [self.bodyView loadHTMLString:html baseURL:NULL];
-
-
- The matcher objCMessageExpr(matchesSelector(hasUnarySelector());
- matches self.bodyView, but does not match the outer message
+ matcher = objCMessageExpr(matchesSelector(hasUnarySelector());
+ matches self.bodyView in the code below, but NOT the outer message
invocation of "loadHTMLString:baseURL:".
+ [self.bodyView loadHTMLString:html baseURL:NULL];
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>></td><td class="name" onclick="toggle('isClassMessage0')"><a name="isClassMessage0Anchor">isClassMessage</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isClassMessage0"><pre>Returns true when the Objective-C message is sent to a class.
-Given
+Example
+matcher = objcMessageExpr(isClassMessage())
+matches
[NSString stringWithFormat:@"format"];
+but not
NSString *x = @"hello";
[x containsString:@"h"];
-
-The matcher objcMessageExpr(isClassMessage())
-matches [NSString stringWithFormat:@"format"];
-but does not match [[x containsString:@"h"]
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>></td><td class="name" onclick="toggle('isInstanceMessage0')"><a name="isInstanceMessage0Anchor">isInstanceMessage</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isInstanceMessage0"><pre>Returns true when the Objective-C message is sent to an instance.
-Given
+Example
+matcher = objcMessageExpr(isInstanceMessage())
+matches
NSString *x = @"hello";
[x containsString:@"h"];
+but not
[NSString stringWithFormat:@"format"];
-
-The matcher objcMessageExpr(isInstanceMessage())
-matches [x containsString:@"h"];
-but does not match [NSString stringWithFormat:@"format"];
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>></td><td class="name" onclick="toggle('matchesSelector0')"><a name="matchesSelector0Anchor">matchesSelector</a></td><td>StringRef RegExp, Regex::RegexFlags Flags = NoFlags</td></tr>
<tr><td colspan="4" class="doc" id="matchesSelector0"><pre>Matches ObjC selectors whose name contains
a substring matched by the given RegExp.
-
-Given
+ matcher = objCMessageExpr(matchesSelector("loadHTMLStringmatches the outer message expr in the code below, but NOT the message
+ invocation for self.bodyView.
[self.bodyView loadHTMLString:html baseURL:NULL];
-
-The matcher
-objCMessageExpr(matchesSelector("loadHTMLStringmatches the outer message expr in the code below, but NOT the message
-invocation for self.bodyView.
-
If the matcher is used in clang-query, RegexFlags parameter
should be passed as a quoted string. e.g: "NoFlags".
Flags can be combined with '|' example "IgnoreCase | BasicRegex"
@@ -7100,26 +5238,25 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>></td><td class="name" onclick="toggle('numSelectorArgs0')"><a name="numSelectorArgs0Anchor">numSelectorArgs</a></td><td>unsigned N</td></tr>
<tr><td colspan="4" class="doc" id="numSelectorArgs0"><pre>Matches when the selector has the specified number of arguments
- [self.bodyView loadHTMLString:html baseURL:NULL];
+ matcher = objCMessageExpr(numSelectorArgs(0));
+ matches self.bodyView in the code below
-The matcher objCMessageExpr(numSelectorArgs(0))
-matches self.bodyView.
-The matcher objCMessageExpr(numSelectorArgs(2))
-matches the invocation of loadHTMLString:baseURL:
-but does not match self.bodyView
+ matcher = objCMessageExpr(numSelectorArgs(2));
+ matches the invocation of "loadHTMLString:baseURL:" but not that
+ of self.bodyView
+ [self.bodyView loadHTMLString:html baseURL:NULL];
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>></td><td class="name" onclick="toggle('isClassMethod0')"><a name="isClassMethod0Anchor">isClassMethod</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isClassMethod0"><pre>Returns true when the Objective-C method declaration is a class method.
-Given
+Example
+matcher = objcMethodDecl(isClassMethod())
+matches
@interface I + (void)foo; @end
+but not
@interface I - (void)bar; @end
-
-The matcher objcMethodDecl(isClassMethod())
-matches @interface I + (void)foo; @end
-but does not match interface I + (void)foo; @end
</pre></td></tr>
@@ -7133,14 +5270,6 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
extern int vb; // Doesn't match, as it doesn't define the variable.
void fa() {}
void fb(); // Doesn't match, as it has no body.
-
-The matcher tagDecl(isDefinition())
-matches A
-The matcher varDecl(isDefinition())
-matches va
-The matcher functionDecl(isDefinition())
-matches fa
-
@interface X
- (void)ma; // Doesn't match, interface is declaration.
@end
@@ -7148,9 +5277,6 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
- (void)ma {}
@end
-The matcher objcMethodDecl(isDefinition())
-matches - (void)ma {}
-
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>>
</pre></td></tr>
@@ -7159,39 +5285,33 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>></td><td class="name" onclick="toggle('isInstanceMethod0')"><a name="isInstanceMethod0Anchor">isInstanceMethod</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isInstanceMethod0"><pre>Returns true when the Objective-C method declaration is an instance method.
-Given
+Example
+matcher = objcMethodDecl(isInstanceMethod())
+matches
@interface I - (void)bar; @end
+but not
@interface I + (void)foo; @end
-
-The matcher objcMethodDecl(isInstanceMethod())
-matches @interface I - (void)bar; @end
-but does not match @interface I - (void)foo; @end
-
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>></td><td class="name" onclick="toggle('hasDefaultArgument0')"><a name="hasDefaultArgument0Anchor">hasDefaultArgument</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasDefaultArgument0"><pre>Matches a declaration that has default arguments.
-Given
- void x(int val) {}
- void y(int val = 0) {}
-
-
-The matcher parmVarDecl(hasDefaultArgument())
-matches int val = 0.
+Example matches y (matcher = parmVarDecl(hasDefaultArgument()))
+void x(int val) {}
+void y(int val = 0) {}
Deprecated. Use hasInitializer() instead to be able to
match on the contents of the default argument. For example:
-Given
- void x(int val = 7) {}
- void y(int val = 42) {}
-
+void x(int val = 7) {}
+void y(int val = 42) {}
+parmVarDecl(hasInitializer(integerLiteral(equals(42))))
+ matches the parameter of y
-The matcher
-parmVarDecl(hasInitializer(integerLiteral(equals(42)))),
-matches int val = 42.
+A matcher such as
+ parmVarDecl(hasInitializer(anything()))
+is equivalent to parmVarDecl(hasDefaultArgument()).
</pre></td></tr>
@@ -7206,9 +5326,9 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
void f(int a, int b, int c) {
}
-The matcher parmVarDecl(isAtPosition(0)) matches
-a. The matcher parmVarDecl(isAtPosition(1))
-matches b.
+``parmVarDecl(isAtPosition(0))`` matches ``int a``.
+
+``parmVarDecl(isAtPosition(1))`` matches ``int b``.
</pre></td></tr>
@@ -7218,9 +5338,8 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
Given
class Y { public: void x(); };
void z() { Y* y; y->x(); }
-
-The matcher cxxMemberCallExpr(on(hasType(asString("Y *"))))
-matches y->x()
+cxxMemberCallExpr(on(hasType(asString("class Y *"))))
+ matches y->x()
</pre></td></tr>
@@ -7231,11 +5350,10 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
Given
class X { int a; int b; };
-
-The matcher cxxRecordDecl(
+cxxRecordDecl(
has(fieldDecl(hasName("a"), hasType(type().bind("t")))),
has(fieldDecl(hasName("b"), hasType(type(equalsBoundNode("t"))))))
- matches X, as a and b have the same type.
+ matches the class X, as a and b have the same type.
Note that when multiple matches are involved via forEach* matchers,
equalsBoundNodes acts as a filter.
@@ -7254,15 +5372,12 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
Given
typedef const int const_int;
- const_int i = 0;
- int *const j = nullptr;
+ const_int i;
+ int *const j;
int *volatile k;
int m;
-
-
-The matcher varDecl(hasType(hasLocalQualifiers())) matches only
-j and k. is
-const-qualified but the qualifier is not local.
+varDecl(hasType(hasLocalQualifiers())) matches only j and k.
+i is const-qualified but the qualifier is not local.
</pre></td></tr>
@@ -7273,11 +5388,9 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
void a(char);
void b(wchar_t);
void c(double);
-
-
-The matcher
functionDecl(hasAnyParameter(hasType(isAnyCharacter())))
-a, b, but not </pre></td></tr>
+matches "a(char)", "b(wchar_t)", but not "c(double)".
+</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>></td><td class="name" onclick="toggle('isAnyPointer0')"><a name="isAnyPointer0Anchor">isAnyPointer</a></td><td></td></tr>
@@ -7293,9 +5406,8 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
Foo *f;
int j;
-
-The matcher varDecl(hasType(isAnyPointer()))
-int *i and Foo *f, but not int j.
+varDecl(hasType(isAnyPointer()))
+ matches "int *i" and "Foo *f", but not "int j".
</pre></td></tr>
@@ -7309,11 +5421,9 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
void c(const int);
void d(const int*);
void e(int const) {};
-The matcher
functionDecl(hasAnyParameter(hasType(isConstQualified())))
- matches b, c and
- e.
- It does not match as there
+ matches "void b(int const)", "void c(const int)" and
+ "void e(int const) {}". It does not match d as there
is no top-level const on the parameter type "const int *".
</pre></td></tr>
@@ -7325,8 +5435,8 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
void a(int);
void b(long);
void c(double);
-The matcher functionDecl(hasAnyParameter(hasType(isInteger())))
-a, b, but not c.
+functionDecl(hasAnyParameter(hasType(isInteger())))
+matches "a(int)", "b(long)", but not "c(double)".
</pre></td></tr>
@@ -7337,9 +5447,8 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
void a(int);
void b(unsigned long);
void c(double);
-The matcher
-functionDecl(hasAnyParameter(hasType(isSignedInteger()))) matches
-a, but not and not
+functionDecl(hasAnyParameter(hasType(isSignedInteger())))
+matches "a(int)", but not "b(unsigned long)" and "c(double)".
</pre></td></tr>
@@ -7350,10 +5459,8 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
void a(int);
void b(unsigned long);
void c(double);
-The matcher
functionDecl(hasAnyParameter(hasType(isUnsignedInteger())))
-matches b,
-but does not match a and c.
+matches "b(unsigned long)", but not "a(int)" and "c(double)".
</pre></td></tr>
@@ -7367,11 +5474,9 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
void c(volatile int);
void d(volatile int*);
void e(int volatile) {};
-The matcher
functionDecl(hasAnyParameter(hasType(isVolatileQualified())))
- matches b, c and
- e.
- It does not match as there
+ matches "void b(int volatile)", "void c(volatile int)" and
+ "void e(int volatile) {}". It does not match d as there
is no top-level volatile on the parameter type "volatile int *".
</pre></td></tr>
@@ -7383,11 +5488,10 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
Given
class X { int a; int b; };
-
-The matcher cxxRecordDecl(
+cxxRecordDecl(
has(fieldDecl(hasName("a"), hasType(type().bind("t")))),
has(fieldDecl(hasName("b"), hasType(type(equalsBoundNode("t"))))))
- matches X, as a and b have the same type.
+ matches the class X, as a and b have the same type.
Note that when multiple matches are involved via forEach* matchers,
equalsBoundNodes acts as a filter.
@@ -7412,15 +5516,6 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
Does not match if only part of the statement is expanded from that macro or
if different parts of the statement are expanded from different
appearances of the macro.
-
-Given
- #define A 0
- #define B A
- int c = B;
-
-The matcher integerLiteral(isExpandedFromMacro("A"))
-matches the literal expanded at the initializer B of the variable
-c .
</pre></td></tr>
@@ -7428,25 +5523,12 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="isExpansionInFileMatching1"><pre>Matches AST nodes that were expanded within files whose name is
partially matching a given regex.
-Given the headers Y.h
- #pragma once
- typedef int my_y_int;
-and X.h
- #pragma once
- typedef int my_x_int;
-and the source code
- #include "X.h"
- #include "Y.h"
- typedef int my_main_file_int;
- my_main_file_int a = 0;
- my_x_int b = 1;
- my_y_int c = 2;
-
-The matcher
-typedefDecl(isExpansionInFileMatching("Y.h"))
-matches typedef int my_y_int,
-but does not match typedef int my_main_file_int or
-typedef int my_x_int.
+Example matches Y but not X
+ (matcher = cxxRecordDecl(isExpansionInFileMatching("AST.*"))
+ #include "ASTMatcher.h"
+ class X {};
+ASTMatcher.h:
+ class Y {};
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>>
@@ -7459,18 +5541,12 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('isExpansionInMainFile1')"><a name="isExpansionInMainFile1Anchor">isExpansionInMainFile</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isExpansionInMainFile1"><pre>Matches AST nodes that were expanded within the main-file.
-Given the header Y.h
- #pragma once
- typedef int my_header_int;
-and the source file
- #include "Y.h"
- typedef int my_main_file_int;
- my_main_file_int a = 0;
- my_header_int b = 1;
-
-The matcher typedefDecl(isExpansionInMainFile())
-matches typedef int my_main_file_int,
-but does not match typedef int my_header_int.
+Example matches X but not Y
+ (matcher = cxxRecordDecl(isExpansionInMainFile())
+ #include <Y.h>
+ class X {};
+Y.h:
+ class Y {};
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>>
</pre></td></tr>
@@ -7479,17 +5555,12 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('isExpansionInSystemHeader1')"><a name="isExpansionInSystemHeader1Anchor">isExpansionInSystemHeader</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isExpansionInSystemHeader1"><pre>Matches AST nodes that were expanded within system-header-files.
-Given the header SystemHeader.h
- #pragma once
- int header();
-and the source code
+Example matches Y but not X
+ (matcher = cxxRecordDecl(isExpansionInSystemHeader())
#include <SystemHeader.h>
- static int main_file();
-
-
-The matcher functionDecl(isExpansionInSystemHeader())
-matches int header(),
-but does not match static int main_file().
+ class X {};
+SystemHeader.h:
+ class Y {};
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>>
</pre></td></tr>
@@ -7500,18 +5571,14 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
Given
int j;
- template<typename T> void A(T t) { T i; }
- void foo() {
- A(0);
- A(0U);
- }
-
-The matcher declStmt(isInTemplateInstantiation())
-matches T i; twice, once for int and once for
-int}.
-The matcher declStmt(unless(isInTemplateInstantiation())) will
-match T i; once inside the template definition, but not for any of
-the instantiated bodies.
+ template<typename T> void A(T t) { T i; j += 42;}
+ A(0);
+ A(0U);
+declStmt(isInTemplateInstantiation())
+ matches 'int i;' and 'unsigned i'.
+unless(stmt(isInTemplateInstantiation()))
+ will NOT match j += 42; as it's shared between the template definition and
+ instantiation.
</pre></td></tr>
@@ -7525,28 +5592,21 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
char *s = "abcd";
wchar_t *ws = L"abcd";
char *w = "a";
-
-The matcher constantArrayType(hasSize(42))
-matches int[42] twice.
-The matcher stringLiteral(hasSize(4))
-matches "abcd" and L"abcd".
+constantArrayType(hasSize(42))
+ matches "int a[42]" and "int b[2 * 21]"
+stringLiteral(hasSize(4))
+ matches "abcd", L"abcd"
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>></td><td class="name" onclick="toggle('isClass0')"><a name="isClass0Anchor">isClass</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isClass0"><pre>Matches TagDecl object that are spelled with "class."
-Given
+Example matches C, but not S, U or E.
struct S {};
class C {};
union U {};
- enum E { Ok };
-
-The matcher tagDecl(isClass())
-matches class C,
-but does not match struct S,
-union U
-or enum E.
+ enum E {};
</pre></td></tr>
@@ -7560,14 +5620,6 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
extern int vb; // Doesn't match, as it doesn't define the variable.
void fa() {}
void fb(); // Doesn't match, as it has no body.
-
-The matcher tagDecl(isDefinition())
-matches A
-The matcher varDecl(isDefinition())
-matches va
-The matcher functionDecl(isDefinition())
-matches fa
-
@interface X
- (void)ma; // Doesn't match, interface is declaration.
@end
@@ -7575,9 +5627,6 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
- (void)ma {}
@end
-The matcher objcMethodDecl(isDefinition())
-matches - (void)ma {}
-
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>>
</pre></td></tr>
@@ -7586,16 +5635,11 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>></td><td class="name" onclick="toggle('isEnum0')"><a name="isEnum0Anchor">isEnum</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isEnum0"><pre>Matches TagDecl object that are spelled with "enum."
-Given
+Example matches E, but not C, S or U.
struct S {};
class C {};
union U {};
- enum E { Ok };
-
-The matcher tagDecl(isEnum())
-matches enum E { Ok },
-but does not match struct S {},
-class C {} or union U {}.
+ enum E {};
</pre></td></tr>
@@ -7606,30 +5650,18 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
struct S {};
class C {};
union U {};
- enum E { Ok };
-
-The matcher tagDecl(isStruct())
-matches struct S,
-but does not match class C,
-union U
-or enum E.
+ enum E {};
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>></td><td class="name" onclick="toggle('isUnion0')"><a name="isUnion0Anchor">isUnion</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isUnion0"><pre>Matches TagDecl object that are spelled with "union."
-Given
+Example matches U, but not C, S or E.
struct S {};
class C {};
union U {};
- enum E { Ok };
-
-The matcher tagDecl(isUnion())
-matches union U,
-does not match struct S,
-class C
-or enum E.
+ enum E {};
</pre></td></tr>
@@ -7643,12 +5675,9 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
Given
template<int T> struct C {};
C<42> c;
-
-The matcher classTemplateSpecializationDecl(
+classTemplateSpecializationDecl(
hasAnyTemplateArgument(equalsIntegralValue("42")))
-matches the implicitly declared specialization
-struct C<42> from the instantiation for the type of the
-variable c .
+ matches the implicit instantiation of C in C<42>.
</pre></td></tr>
@@ -7658,12 +5687,10 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
Given
template<int T> struct C {};
C<42> c;
-
-The matcher classTemplateSpecializationDecl(
+classTemplateSpecializationDecl(
hasAnyTemplateArgument(isIntegral()))
-matches the implicitly declared specialization
-struct C<42> from the instantiation for the type of the
-variable c .
+ matches the implicit instantiation of C in C<42>
+ with isIntegral() matching 42.
</pre></td></tr>
@@ -7673,10 +5700,8 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
Given
template<typename T> struct C {};
C<int> c;
-
-The matcher
classTemplateSpecializationDecl(templateArgumentCountIs(1))
-matches struct C<int>.
+ matches C<int>.
</pre></td></tr>
@@ -7685,15 +5710,6 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
Does not match if only part of the statement is expanded from that macro or
if different parts of the statement are expanded from different
appearances of the macro.
-
-Given
- #define A 0
- #define B A
- int c = B;
-
-The matcher integerLiteral(isExpandedFromMacro("A"))
-matches the literal expanded at the initializer B of the variable
-c .
</pre></td></tr>
@@ -7701,25 +5717,12 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="isExpansionInFileMatching2"><pre>Matches AST nodes that were expanded within files whose name is
partially matching a given regex.
-Given the headers Y.h
- #pragma once
- typedef int my_y_int;
-and X.h
- #pragma once
- typedef int my_x_int;
-and the source code
- #include "X.h"
- #include "Y.h"
- typedef int my_main_file_int;
- my_main_file_int a = 0;
- my_x_int b = 1;
- my_y_int c = 2;
-
-The matcher
-typedefDecl(isExpansionInFileMatching("Y.h"))
-matches typedef int my_y_int,
-but does not match typedef int my_main_file_int or
-typedef int my_x_int.
+Example matches Y but not X
+ (matcher = cxxRecordDecl(isExpansionInFileMatching("AST.*"))
+ #include "ASTMatcher.h"
+ class X {};
+ASTMatcher.h:
+ class Y {};
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>>
@@ -7732,18 +5735,12 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>></td><td class="name" onclick="toggle('isExpansionInMainFile2')"><a name="isExpansionInMainFile2Anchor">isExpansionInMainFile</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isExpansionInMainFile2"><pre>Matches AST nodes that were expanded within the main-file.
-Given the header Y.h
- #pragma once
- typedef int my_header_int;
-and the source file
- #include "Y.h"
- typedef int my_main_file_int;
- my_main_file_int a = 0;
- my_header_int b = 1;
-
-The matcher typedefDecl(isExpansionInMainFile())
-matches typedef int my_main_file_int,
-but does not match typedef int my_header_int.
+Example matches X but not Y
+ (matcher = cxxRecordDecl(isExpansionInMainFile())
+ #include <Y.h>
+ class X {};
+Y.h:
+ class Y {};
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>>
</pre></td></tr>
@@ -7752,17 +5749,12 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>></td><td class="name" onclick="toggle('isExpansionInSystemHeader2')"><a name="isExpansionInSystemHeader2Anchor">isExpansionInSystemHeader</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isExpansionInSystemHeader2"><pre>Matches AST nodes that were expanded within system-header-files.
-Given the header SystemHeader.h
- #pragma once
- int header();
-and the source code
+Example matches Y but not X
+ (matcher = cxxRecordDecl(isExpansionInSystemHeader())
#include <SystemHeader.h>
- static int main_file();
-
-
-The matcher functionDecl(isExpansionInSystemHeader())
-matches int header(),
-but does not match static int main_file().
+ class X {};
+SystemHeader.h:
+ class Y {};
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>>
</pre></td></tr>
@@ -7773,9 +5765,8 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
Given
struct S { bool func(); };
-
-The matcher functionDecl(returns(booleanType()))
-func
+functionDecl(returns(booleanType()))
+ matches "bool func();"
</pre></td></tr>
@@ -7786,11 +5777,10 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
Given
class X { int a; int b; };
-
-The matcher cxxRecordDecl(
+cxxRecordDecl(
has(fieldDecl(hasName("a"), hasType(type().bind("t")))),
has(fieldDecl(hasName("b"), hasType(type(equalsBoundNode("t"))))))
- matches X, as a and b have the same type.
+ matches the class X, as a and b have the same type.
Note that when multiple matches are involved via forEach* matchers,
equalsBoundNodes acts as a filter.
@@ -7816,9 +5806,8 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
Given
int i;
float f;
-The matcher type(realFloatingPointType())
-matches float
-but does not match int.
+realFloatingPointType()
+ matches "float f" but not "int i"
</pre></td></tr>
@@ -7827,10 +5816,8 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
Given
struct S { void func(); };
-
-
-The matcher functionDecl(returns(voidType()))
-func
+functionDecl(returns(voidType()))
+ matches "void func();"
</pre></td></tr>
@@ -7839,10 +5826,9 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
Given
int x;
- int s = sizeof(x) + alignof(x);
-
-The matcher unaryExprOrTypeTraitExpr(ofKind(UETT_SizeOf))
-matches sizeof(x)
+ int s = sizeof(x) + alignof(x)
+unaryExprOrTypeTraitExpr(ofKind(UETT_SizeOf))
+ matches sizeof(x)
If the matcher is use from clang-query, UnaryExprOrTypeTrait parameter
should be passed as a quoted string. e.g., ofKind("UETT_SizeOf").
@@ -7853,26 +5839,9 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="hasAnyOperatorName3"><pre>Matches operator expressions (binary or unary) that have any of the
specified names.
-It provides a compact way of writing if an operator has any of the specified
-names:
-The matcher
hasAnyOperatorName("+", "-")
-Is equivalent to
- hasOperatorName("-"))}
-
-Given
-void foo(bool a, bool b) {
- !(a || b);
- }
-
-void bar(bool a, bool b) {
- a && b;
- }
-
-The matcher binaryOperator(hasAnyOperatorName("||", "&&"))
-matches a || b and a && b.
-The matcher unaryOperator(hasAnyOperatorName("-", "!"))
-matches !(a || b).
+ Is equivalent to
+ anyOf(hasOperatorName("+"), hasOperatorName("-"))
</pre></td></tr>
@@ -7880,22 +5849,15 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="hasOperatorName4"><pre>Matches the operator Name of operator expressions and fold expressions
(binary or unary).
-Given
-void foo(bool a, bool b) {
- !(a || b);
- }
-
-The matcher binaryOperator(hasOperatorName("||"))
-matches a || b
+Example matches a || b (matcher = binaryOperator(hasOperatorName("||")))
+ !(a || b)
-Given
+Example matches `(0 + ... + args)`
+ (matcher = cxxFoldExpr(hasOperatorName("+")))
template <typename... Args>
auto sum(Args... args) {
return (0 + ... + args);
}
-
-The matcher cxxFoldExpr(hasOperatorName("+"))
- matches (0 + ... + args).
</pre></td></tr>
@@ -7914,57 +5876,40 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
};
template <class T>
class Z {
- void x() {
- this->m;
- this->t;
- this->t->m;
- }
- int m;
- T* t;
+ void x() { this->m; }
};
-
-The matcher memberExpr(isArrow())
-matches this->x, x, a,
-this->b, this->m and two times this->t,
-once for the standalone member expression, and once for the member
-expression that later accesses m .
-Additionally, it does not match this->t->t.
-The matcher cxxDependentScopeMemberExpr(isArrow())
-matches this->t->m, but not this->m or this->t.
-The matcher unresolvedMemberExpr(isArrow())
-matches this->f<T>, f<T>
+memberExpr(isArrow())
+ matches this->x, x, y.x, a, this->b
+cxxDependentScopeMemberExpr(isArrow())
+ matches this->m
+unresolvedMemberExpr(isArrow())
+ matches this->f<T>, f<T>
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>></td><td class="name" onclick="toggle('hasAutomaticStorageDuration0')"><a name="hasAutomaticStorageDuration0Anchor">hasAutomaticStorageDuration</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasAutomaticStorageDuration0"><pre>Matches a variable declaration that has automatic storage duration.
-Given
+Example matches x, but not y, z, or a.
+(matcher = varDecl(hasAutomaticStorageDuration())
void f() {
int x;
static int y;
thread_local int z;
}
int a;
-
-The matcher varDecl(hasAutomaticStorageDuration())
-matches x
-but does not match y, z or
-a
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>></td><td class="name" onclick="toggle('hasGlobalStorage0')"><a name="hasGlobalStorage0Anchor">hasGlobalStorage</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasGlobalStorage0"><pre>Matches a variable declaration that does not have local storage.
-Given
+Example matches y and z (matcher = varDecl(hasGlobalStorage())
void f() {
int x;
static int y;
}
int z;
-The matcher varDecl(hasGlobalStorage())
-matches y and z
</pre></td></tr>
@@ -7972,14 +5917,12 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="hasLocalStorage0"><pre>Matches a variable declaration that has function scope and is a
non-static local variable.
-Given
+Example matches x (matcher = varDecl(hasLocalStorage())
void f() {
int x;
static int y;
}
int z;
-The matcher varDecl(hasLocalStorage())
-matches x
</pre></td></tr>
@@ -7996,28 +5939,22 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
int a;
static int b;
extern int c;
-
-The matcher varDecl(hasStaticStorageDuration())
-matches y, a, b and
-c
+varDecl(hasStaticStorageDuration())
+ matches the function declaration y, a, b and c.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>></td><td class="name" onclick="toggle('hasThreadStorageDuration0')"><a name="hasThreadStorageDuration0Anchor">hasThreadStorageDuration</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasThreadStorageDuration0"><pre>Matches a variable declaration that has thread storage duration.
-Given
+Example matches z, but not x, z, or a.
+(matcher = varDecl(hasThreadStorageDuration())
void f() {
int x;
static int y;
thread_local int z;
}
int a;
-
-The matcher varDecl(hasThreadStorageDuration())
-matches z
-but does not match x, z or
-a
</pre></td></tr>
@@ -8025,34 +5962,29 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="isConstexpr0"><pre>Matches constexpr variable and function declarations,
and if constexpr.
-Given
+Given:
constexpr int foo = 42;
constexpr int bar();
void baz() { if constexpr(1 > 0) {} }
-
-The matcher varDecl(isConstexpr())
-matches foo.
-The matcher functionDecl(isConstexpr())
-matches bar.
-The matcher ifStmt(isConstexpr())
-matches if constexpr(1 > 0) {}.
+varDecl(isConstexpr())
+ matches the declaration of foo.
+functionDecl(isConstexpr())
+ matches the declaration of bar.
+ifStmt(isConstexpr())
+ matches the if statement in baz.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>></td><td class="name" onclick="toggle('isConstinit0')"><a name="isConstinit0Anchor">isConstinit</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isConstinit0"><pre>Matches constinit variable declarations.
-Given
+Given:
constinit int foo = 42;
constinit const char* bar = "bar";
int baz = 42;
[[clang::require_constant_initialization]] int xyz = 42;
-
-The matcher varDecl(isConstinit())
-matches the declaration of foo
-and bar,
-but does not match baz or
-xyz.
+varDecl(isConstinit())
+ matches the declaration of `foo` and `bar`, but not `baz` and `xyz`.
</pre></td></tr>
@@ -8066,14 +5998,6 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
extern int vb; // Doesn't match, as it doesn't define the variable.
void fa() {}
void fb(); // Doesn't match, as it has no body.
-
-The matcher tagDecl(isDefinition())
-matches A
-The matcher varDecl(isDefinition())
-matches va
-The matcher functionDecl(isDefinition())
-matches fa
-
@interface X
- (void)ma; // Doesn't match, interface is declaration.
@end
@@ -8081,9 +6005,6 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
- (void)ma {}
@end
-The matcher objcMethodDecl(isDefinition())
-matches - (void)ma {}
-
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>>
</pre></td></tr>
@@ -8093,15 +6014,12 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="isExceptionVariable0"><pre>Matches a variable declaration that is an exception variable from
a C++ catch block, or an Objective-C statement.
-Given
+Example matches x (matcher = varDecl(isExceptionVariable())
void f(int y) {
try {
} catch (int x) {
}
}
-
-The matcher varDecl(isExceptionVariable())
-matches x
</pre></td></tr>
@@ -8112,9 +6030,8 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
Given
template<typename T> void A(T t) { }
template<> void A(int N) { }
-
-The matcher functionDecl(isExplicitTemplateSpecialization())
- matches the specialization template<> void A(int N) { }.
+functionDecl(isExplicitTemplateSpecialization())
+ matches the specialization A<int>().
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>>
</pre></td></tr>
@@ -8123,21 +6040,17 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>></td><td class="name" onclick="toggle('isExternC1')"><a name="isExternC1Anchor">isExternC</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isExternC1"><pre>Matches extern "C" function or variable declarations.
-Given
+Given:
extern "C" void f() {}
extern "C" { void g() {} }
void h() {}
extern "C" int x = 1;
extern "C" int y = 2;
int z = 3;
-
-The matcher functionDecl(isExternC())
-matches f
-and g.
-The matcher varDecl(isExternC())
-matches x
-and y,
-but does not match z.
+functionDecl(isExternC())
+ matches the declaration of f and g, but not the declaration of h.
+varDecl(isExternC())
+ matches the declaration of x and y, but not the declaration of z.
</pre></td></tr>
@@ -8145,11 +6058,8 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="isInitCapture0"><pre>Matches a variable serving as the implicit variable for a lambda init-
capture.
-Given
-auto f = [x = 3]() { return x; };
-
-The matcher varDecl(isInitCapture())
-matches x = 3.
+Example matches x (matcher = varDecl(isInitCapture()))
+auto f = [x=3]() { return x; };
</pre></td></tr>
@@ -8164,24 +6074,21 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
inline namespace m {}
}
inline int Foo = 5;
-
-The matcher functionDecl(isInline()) matches f.
-The matcher namespaceDecl(isInline()) matches m.
-The matcher varDecl(isInline()) matches Foo
+functionDecl(isInline()) will match ::f().
+namespaceDecl(isInline()) will match n::m.
+varDecl(isInline()) will match Foo;
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>></td><td class="name" onclick="toggle('isStaticLocal0')"><a name="isStaticLocal0Anchor">isStaticLocal</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isStaticLocal0"><pre>Matches a static variable with local scope.
-Given
+Example matches y (matcher = varDecl(isStaticLocal()))
void f() {
int x;
static int y;
}
static int z;
-The matcher varDecl(isStaticLocal())
-matches y
</pre></td></tr>
@@ -8189,15 +6096,15 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
<tr><td colspan="4" class="doc" id="isStaticStorageClass1"><pre>Matches variable/function declarations that have "static" storage
class specifier ("static" keyword) written in the source.
-Given
+Given:
static void f() {}
static int i = 0;
extern int j;
int k;
-The matcher functionDecl(isStaticStorageClass())
- matches f
-The matcher varDecl(isStaticStorageClass())
- matches i
+functionDecl(isStaticStorageClass())
+ matches the function declaration f.
+varDecl(isStaticStorageClass())
+ matches the variable declaration i.
</pre></td></tr>
@@ -8206,36 +6113,18 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
member variable template instantiations.
Given
- template <typename T> class X {};
- class A {};
- X<A> x;
-
-The matcher cxxRecordDecl(hasName("::X"),
-isTemplateInstantiation())
-matches class X<class A>.
- template <typename T> class X {};
- class A {};
- template class X<A>;
-
-The matcher cxxRecordDecl(hasName("::X"),
-isTemplateInstantiation())
-matches template class X<A>
- template <typename T> class X {};
- class A {};
- extern template class X<A>;
-
-The matcher cxxRecordDecl(hasName("::X"),
-isTemplateInstantiation())
-matches extern template class X<A>
+ template <typename T> class X {}; class A {}; X<A> x;
+or
+ template <typename T> class X {}; class A {}; template class X<A>;
+or
+ template <typename T> class X {}; class A {}; extern template class X<A>;
+cxxRecordDecl(hasName("::X"), isTemplateInstantiation())
+ matches the template instantiation of X<A>.
But given
- template <typename T> class X {};
- class A {};
- template <> class X<A> {};
- X<A> x;
-
-The matcher cxxRecordDecl(hasName("::X"),
-isTemplateInstantiation())
+ template <typename T> class X {}; class A {};
+ template <> class X<A> {}; X<A> x;
+cxxRecordDecl(hasName("::X"), isTemplateInstantiation())
does not match, as X<A> is an explicit template specialization.
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>>
@@ -8262,9 +6151,10 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td>Matcher<*></td><td class="name" onclick="toggle('binaryOperation0')"><a name="binaryOperation0Anchor">binaryOperation</a></td><td>Matcher<*>...Matcher<*></td></tr>
<tr><td colspan="4" class="doc" id="binaryOperation0"><pre>Matches nodes which can be used with binary operators.
-A comparison of two expressions might be represented in the clang AST as a
-binaryOperator, a cxxOperatorCallExpr or a
-cxxRewrittenBinaryOperator, depending on
+The code
+ var1 != var2;
+might be represented in the clang AST as a binaryOperator, a
+cxxOperatorCallExpr or a cxxRewrittenBinaryOperator, depending on
* whether the types of var1 and var2 are fundamental (binaryOperator) or at
least one is a class type (cxxOperatorCallExpr)
@@ -8278,6 +6168,12 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
compatible.
Given
+ binaryOperation(
+ hasOperatorName("!="),
+ hasLHS(expr().bind("lhs")),
+ hasRHS(expr().bind("rhs"))
+ )
+matches each use of "!=" in:
struct S{
bool operator!=(const S&) const;
};
@@ -8291,28 +6187,25 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
template<typename T>
void templ()
{
- 3 != 4;
+ 1 != 2;
T() != S();
}
struct HasOpEq
{
- friend bool
- operator==(const HasOpEq &, const HasOpEq&) noexcept = default;
+ bool operator==(const HasOpEq &) const;
};
void inverse()
{
- HasOpEq e1;
- HasOpEq e2;
- if (e1 != e2)
+ HasOpEq s1;
+ HasOpEq s2;
+ if (s1 != s2)
return;
}
struct HasSpaceship
{
- friend bool
- operator<=>(const HasSpaceship &,
- const HasSpaceship&) noexcept = default;
+ bool operator<=>(const HasOpEq &) const;
};
void use_spaceship()
@@ -8322,15 +6215,6 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
if (s1 != s2)
return;
}
-
-
-The matcher binaryOperation(
- hasOperatorName("!="),
- hasLHS(expr().bind("lhs")),
- hasRHS(expr().bind("rhs"))
- )
-matches 1 != 2, S() != S(), 3 != 4,
-T() != S(), e1 != e2 and s1 != s2.
</pre></td></tr>
@@ -8340,18 +6224,14 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Unlike anyOf, eachOf will generate a match result for each
matching submatcher.
-Given
- void f(int a, int b);
-
-
-The matcher functionDecl(hasAnyParameter(
-eachOf(parmVarDecl(hasName("a")).bind("v"),
- parmVarDecl(hasName("b")).bind("v"))))
-matches void f(int a, int b),
-with parmVarDecl(hasName("a")) matching a
-for one match,
-and with parmVarDecl(hasName("b")) matching
-b for the other match.
+For example, in:
+ class A { int a; int b; };
+The matcher:
+ cxxRecordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
+ has(fieldDecl(hasName("b")).bind("v"))))
+will generate two results binding "v", the first of which binds
+the field declaration of a, the second the field declaration of
+b.
Usable as: Any Matcher
</pre></td></tr>
@@ -8364,14 +6244,10 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
For example, in:
class A { class B {}; class C {}; };
-
-The matcher
-cxxRecordDecl(hasName("::A"),
+The matcher:
+ cxxRecordDecl(hasName("::A"),
findAll(cxxRecordDecl(isDefinition()).bind("m")))
-matches A three times,
-with cxxRecordDecl(isDefinition()).bind("m")
-matching A,
-B and C.
+will generate results for A, B and C.
Usable as: Any Matcher
</pre></td></tr>
@@ -8381,71 +6257,24 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="forEachDescendant0"><pre>Matches AST nodes that have descendant AST nodes that match the
provided matcher.
-Given
+Example matches X, A, A::X, B, B::C, B::C::X
+ (matcher = cxxRecordDecl(forEachDescendant(cxxRecordDecl(hasName("X")))))
class X {};
class A { class X {}; }; // Matches A, because A::X is a class of name
// X inside A.
class B { class C { class X {}; }; };
-The matcher
-cxxRecordDecl(forEachDescendant(cxxRecordDecl(hasName("X"))))
-matches X, A,
-B, class B::C
-and class B::C::X
-
DescendantT must be an AST base type.
As opposed to 'hasDescendant', 'forEachDescendant' will cause a match for
each result that matches instead of only on the first one.
Note: Recursively combined ForEachDescendant can cause many matches:
- struct A {
- struct B {
- struct C {};
- struct D {};
- };
- };
-
-
-The matcher cxxRecordDecl(forEachDescendant(cxxRecordDecl(
- forEachDescendant(cxxRecordDecl().bind("inner"))
- ).bind("middle")))
-will match 9 times:
-It matches the definition of A with the definition of
-B in the middle and the injected class name of
-B as the innermost cxxRecordDecl.
-
-It matches the definition of A with the definition of
-C in the middle and the definition of
-B as the innermost cxxRecordDecl.
-
-It matches the definition of A with the definition of
-C in the middle and the injected class name of
-B as the innermost cxxRecordDecl.
-
-It matches the definition of A with the definition of
-B in the middle and the definition of
-D as the innermost cxxRecordDecl.
-
-It matches the definition of A with the definition of
-B in the middle and the injected class name of
-D as the innermost cxxRecordDecl.
-
-It matches the definition of A with the definition of
-C in the middle and the injected class name of
-C as the innermost cxxRecordDecl.
-
-It matches the definition of A with the definition of
-D in the middle and the injected class name of
-D as the innermost cxxRecordDecl.
-
-It matches the definition of B with the definition of
-C in the middle and the injected class name of
-C as the innermost cxxRecordDecl.
-
-It matches the definition of B with the definition of
-D in the middle and the injected class name of
-D as the innermost cxxRecordDecl.
+ cxxRecordDecl(forEachDescendant(cxxRecordDecl(
+ forEachDescendant(cxxRecordDecl())
+ )))
+will match 10 times (plus injected class name matches) on:
+ class A { class B { class C { class D { class E {}; }; }; }; };
Usable as: Any Matcher
</pre></td></tr>
@@ -8455,22 +6284,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="forEach0"><pre>Matches AST nodes that have child AST nodes that match the
provided matcher.
-Given
+Example matches X, Y, Y::X, Z::Y, Z::Y::X
+ (matcher = cxxRecordDecl(forEach(cxxRecordDecl(hasName("X")))
class X {};
class Y { class X {}; }; // Matches Y, because Y::X is a class of name X
// inside Y.
class Z { class Y { class X {}; }; }; // Does not match Z.
-The matcher cxxRecordDecl(forEach(cxxRecordDecl(hasName("X"))))
-matches class X,
-class Y,
-class Y::X,
-class Z::Y::X and class Z::Y
-
ChildT must be an AST base type.
As opposed to 'has', 'forEach' will cause a match for each result that
- matches instead of only on the first one.
+matches instead of only on the first one.
Usable as: Any Matcher
</pre></td></tr>
@@ -8483,10 +6307,7 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
void f() { if (true) { int x = 42; } }
void g() { for (;;) { int x = 43; } }
-
-The matcher expr(integerLiteral(hasAncestor(ifStmt())))
-matches 42
-but does not match 43
+expr(integerLiteral(hasAncestor(ifStmt()))) matches 42, but not 43.
Usable as: Any Matcher
</pre></td></tr>
@@ -8496,16 +6317,12 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasDescendant0"><pre>Matches AST nodes that have descendant AST nodes that match the
provided matcher.
-Given
+Example matches X, Y, Z
+ (matcher = cxxRecordDecl(hasDescendant(cxxRecordDecl(hasName("X")))))
class X {}; // Matches X, because X::X is a class of name X inside X.
class Y { class X {}; };
class Z { class Y { class X {}; }; };
-The matcher
-cxxRecordDecl(hasDescendant(cxxRecordDecl(hasName("X"))))
-matches class X {}, class Y { class X {}; }
-and class Z { class Y { class X {}; }; }.
-
DescendantT must be an AST base type.
Usable as: Any Matcher
@@ -8516,29 +6333,19 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="has0"><pre>Matches AST nodes that have child AST nodes that match the
provided matcher.
-Given
+Example matches X, Y
+ (matcher = cxxRecordDecl(has(cxxRecordDecl(hasName("X")))
class X {}; // Matches X, because X::X is a class of name X inside X.
class Y { class X {}; };
class Z { class Y { class X {}; }; }; // Does not match Z.
-The matcher cxxRecordDecl(has(cxxRecordDecl(hasName("X"))))
-matches class X {} three times,
-and class Y { class X {}; } two times.
-
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:
-
-Given
- int x =0;
- double y = static_cast<double>(x);
-
-The matcher
-cxxStaticCastExpr(has(ignoringParenImpCasts(declRefExpr()))).
-matches static_cast<double>(x)
+probably consider using ignoringParenImpCasts like:
+has(ignoringParenImpCasts(expr())).
</pre></td></tr>
@@ -8548,9 +6355,7 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
void f() { for (;;) { int x = 42; if (true) { int x = 43; } } }
-
-The matcher compoundStmt(hasParent(ifStmt()))
-matches { int x = 43; }
+compoundStmt(hasParent(ifStmt())) matches "{ int x = 43; }".
Usable as: Any Matcher
</pre></td></tr>
@@ -8564,7 +6369,7 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
which should match both are typically duplicated. This matcher
removes the need for duplication.
-Given
+Given code
struct ConstructorTakesInt
{
ConstructorTakesInt(int i) {}
@@ -8584,11 +6389,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
ConstructorTakesInt cti(42);
}
-
The matcher
-expr(invocation(hasArgument(0, integerLiteral(equals(42)))))
-matches the expressions callTakesInt(42)
-and cti(42).
+invocation(hasArgument(0, integerLiteral(equals(42))))
+matches the expression in both doCall and doConstruct
</pre></td></tr>
@@ -8599,12 +6402,18 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Useful when additional information which may or may not present about a main
matching node is desired.
-Given
- int a = 0;
- int b;
-
-The matcher varDecl(optionally(hasInitializer(expr())))
-matches int a = 0 and int b.
+For example, in:
+ class Foo {
+ int bar;
+ }
+The matcher:
+ cxxRecordDecl(
+ optionally(has(
+ fieldDecl(hasName("bar")).bind("var")
+ ))).bind("record")
+will produce a result binding for both "record" and "var".
+The matcher will produce a "record" binding for even if there is no data
+member named "bar" in that class.
Usable as: Any Matcher
</pre></td></tr>
@@ -8619,10 +6428,10 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
int i = 3.0;
}
The matcher
-traverse(TK_IgnoreUnlessSpelledInSource,
+ traverse(TK_IgnoreUnlessSpelledInSource,
varDecl(hasInitializer(floatLiteral().bind("init")))
)
- matches int i = 3.0 with "init" bound to 3.0.
+matches the variable declaration with "init" bound to the "3.0".
</pre></td></tr>
@@ -8630,13 +6439,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasCondition5"><pre>Matches the condition expression of an if statement, for loop,
switch statement or conditional operator.
-Given
-void foo() {
+Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
if (true) {}
-}
-
-The matcher ifStmt(hasCondition(cxxBoolLiteral(equals(true))))
-if (true) {}
</pre></td></tr>
@@ -8645,19 +6449,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
(binary or ternary).
Example matches b
- void foo(bool condition, int a, int b) {
- condition ? a : b;
- condition ?: b;
- }
-
-The matcher
-conditionalOperator(hasFalseExpression(expr().bind("false")))
-matches condition ? a : b,
-with expr() matching b.
-The matcher
-binaryConditionalOperator(hasFalseExpression(expr().bind("false")))
-matches condition ?: b,
-with expr() matching b.
+ condition ? a : b
+ condition ?: b
</pre></td></tr>
@@ -8665,31 +6458,16 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasTrueExpression0"><pre>Matches the true branch expression of a conditional operator.
Example 1 (conditional ternary operator): matches a
-Given
- void foo(bool condition, int a, int b) {
- condition ? a : b;
- }
-
-The matcher
-conditionalOperator(hasTrueExpression(expr().bind("true")))
-matches condition ? a : b,
-with expr() matching a.
+ condition ? a : b
Example 2 (conditional binary operator): matches opaqueValueExpr(condition)
-Given
- void foo(bool condition, int a, int b) {
- condition ?: b;
- }
-
-The matcher binaryConditionalOperator(hasTrueExpression(expr()))
-matches condition ?: b,
-with expr() matching conditoin.
+ condition ?: b
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>></td><td class="name" onclick="toggle('hasDeclaration15')"><a name="hasDeclaration15Anchor">hasDeclaration</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration15"><pre>Matches a node if the declaration associated with that node
- matches the given matcher.
+matches the given matcher.
The associated declaration is:
- for type nodes, the declaration of the underlying type
@@ -8699,25 +6477,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
- for CXXNewExpr, the declaration of the operator new
- for ObjCIvarExpr, the declaration of the ivar
-Given
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
class X {};
typedef X Y;
Y y;
-
-For type nodes, hasDeclaration will generally match the declaration of the
-sugared type, i.e., the matcher
-varDecl(hasType(qualType(hasDeclaration(decl().bind("d"))))),
-matches Y y, with
-the matcher decl() matching
-typedef X Y;.
-A common use case is to match the underlying, desugared type.
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
This can be achieved by using the hasUnqualifiedDesugaredType matcher:
-varDecl(hasType(hasUnqualifiedDesugaredType(
- recordType(hasDeclaration(decl().bind("d"))))))
-matches Y y.
-In this matcher, the matcher decl() will match the
-CXXRecordDecl
-class X {};.
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>>,
@@ -8735,7 +6505,7 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
int i[5];
void f() { i[1] = 42; }
-The matcher arraySubscriptExpr(hasBase(implicitCastExpr(
+arraySubscriptExpression(hasBase(implicitCastExpr(
hasSourceExpression(declRefExpr()))))
matches i[1] with the declRefExpr() matching i
</pre></td></tr>
@@ -8747,7 +6517,7 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
int i[5];
void f() { i[1] = 42; }
-The matcher arraySubscriptExpr(hasIndex(integerLiteral()))
+arraySubscriptExpression(hasIndex(integerLiteral()))
matches i[1] with the integerLiteral() matching 1
</pre></td></tr>
@@ -8755,30 +6525,16 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ArraySubscriptExpr.html">ArraySubscriptExpr</a>></td><td class="name" onclick="toggle('hasLHS3')"><a name="hasLHS3Anchor">hasLHS</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasLHS3"><pre>Matches the left hand side of binary operator expressions.
-Given
-void foo(bool a, bool b) {
- a || b;
-}
-
-The matcher binaryOperator(hasLHS(expr().bind("lhs")))
-matches a || b,
-with expr()
-matching a.
+Example matches a (matcher = binaryOperator(hasLHS()))
+ a || b
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ArraySubscriptExpr.html">ArraySubscriptExpr</a>></td><td class="name" onclick="toggle('hasRHS3')"><a name="hasRHS3Anchor">hasRHS</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasRHS3"><pre>Matches the right hand side of binary operator expressions.
-Given
-void foo(bool a, bool b) {
- a || b;
-}
-
-The matcher binaryOperator(hasRHS(expr().bind("rhs")))
-matches a || b,
-with expr()
-matching b.
+Example matches b (matcher = binaryOperator(hasRHS()))
+ a || b
</pre></td></tr>
@@ -8790,10 +6546,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
struct A {};
A a[7];
int b[7];
-
-
-The matcher arrayType(hasElementType(builtinType()))
-int[7]
+arrayType(hasElementType(builtinType()))
+ matches "int b[7]"
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ArrayType.html">ArrayType</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ComplexType.html">ComplexType</a>>
</pre></td></tr>
@@ -8805,8 +6559,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
_Atomic(int) i;
_Atomic(float) f;
-The matcher atomicType(hasValueType(isInteger()))
-_Atomic(int).
+atomicType(hasValueType(isInteger()))
+ matches "_Atomic(int) i"
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AtomicType.html">AtomicType</a>>
</pre></td></tr>
@@ -8821,10 +6575,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
auto a = 1;
auto b = 2.0;
-
-The matcher
-varDecl(hasType(autoType(hasDeducedType(isInteger()))))
-matches auto a = 1, but does not match auto b = 2.0.
+autoType(hasDeducedType(isInteger()))
+ matches "auto a"
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AutoType.html">AutoType</a>>
</pre></td></tr>
@@ -8836,54 +6588,21 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
namespace X { void b(); }
using X::b;
-
-The matcher usingDecl(hasAnyUsingShadowDecl(hasName("b")))
- matches using X::b
-</pre></td></tr>
+usingDecl(hasAnyUsingShadowDecl(hasName("b"))))
+ matches using X::b </pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>></td><td class="name" onclick="toggle('hasEitherOperand0')"><a name="hasEitherOperand0Anchor">hasEitherOperand</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasEitherOperand0"><pre>Matches if either the left hand side or the right hand side of a
binary operator or fold expression matches.
-
-Given
- struct S {};
- bool operator ==(const S&, const S&);
-
- void f(int a, const S&lhs, const S&rhs) {
- a + 0;
- lhs == rhs;
- lhs != rhs;
- }
-
- template <typename ...Ts>
- auto sum(Ts... args) {
- return (0 + ... + args);
- }
-
-
-The matcher binaryOperator(hasEitherOperand(integerLiteral()))
-matches a + 0.
-The matcher cxxOperatorCallExpr(hasEitherOperand(declRefExpr(to(
-parmVarDecl(hasName("lhs")))))) matches lhs == rhs and
-lhs != rhs.
-The matcher cxxFoldExpr(hasEitherOperand(integerLiteral()))
-matches (0 + ... + args).
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>></td><td class="name" onclick="toggle('hasLHS0')"><a name="hasLHS0Anchor">hasLHS</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasLHS0"><pre>Matches the left hand side of binary operator expressions.
-Given
-void foo(bool a, bool b) {
- a || b;
-}
-
-The matcher binaryOperator(hasLHS(expr().bind("lhs")))
-matches a || b,
-with expr()
-matching a.
+Example matches a (matcher = binaryOperator(hasLHS()))
+ a || b
</pre></td></tr>
@@ -8891,40 +6610,27 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasOperands0"><pre>Matches if both matchers match with opposite sides of the binary operator
or fold expression.
-Given
-void foo() {
- 1 + 2; // Match
- 2 + 1; // Match
- 1 + 1; // No match
- 2 + 2; // No match
-}
-The matcher binaryOperator(hasOperands(integerLiteral(equals(1)),
- integerLiteral(equals(2))))
-matches 1 + 2 and 2 + 1,
-but does not match 1 + 1
-or 2 + 2.
+Example matcher = binaryOperator(hasOperands(integerLiteral(equals(1),
+ integerLiteral(equals(2)))
+ 1 + 2 // Match
+ 2 + 1 // Match
+ 1 + 1 // No match
+ 2 + 2 // No match
</pre></td></tr>
-<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>></td><td class="name" onclick="toggle('hasRHS0')"><a name="hasRHS0Anchor">hasRHS</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="hasRHS0"><pre>Matches the right hand side of binary operator expressions.
-
-Given
-void foo(bool a, bool b) {
- a || b;
-}
+<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>></td><td class="name" onclick="toggle('hasRHS0')"><a name="hasRHS0Anchor">hasRHS</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasRHS0"><pre>Matches the right hand side of binary operator expressions.
-The matcher binaryOperator(hasRHS(expr().bind("rhs")))
-matches a || b,
-with expr()
-matching b.
+Example matches b (matcher = binaryOperator(hasRHS()))
+ a || b
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BindingDecl.html">BindingDecl</a>></td><td class="name" onclick="toggle('forDecomposition0')"><a name="forDecomposition0Anchor">forDecomposition</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="forDecomposition0"><pre>Matches the DecompositionDecl the binding belongs to.
-Given
+For example, in:
void foo()
{
int arr[3];
@@ -8932,10 +6638,10 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
f = 42;
}
-
-The matcher bindingDecl(hasName("f"),
- forDecomposition(decompositionDecl()))
-matches f in 'auto &[f, s, t]'.
+The matcher:
+ bindingDecl(hasName("f"),
+ forDecomposition(decompositionDecl())
+matches 'f' in 'auto &[f, s, t]'.
</pre></td></tr>
@@ -8947,26 +6653,23 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
class X { void f(int x, int y, int z) {} };
-
-The matcher cxxMethodDecl(hasAnyParameter(hasName("y")))
- matches f
+cxxMethodDecl(hasAnyParameter(hasName("y")))
+ matches f(int x, int y, int z) {}
with hasAnyParameter(...)
matching int y
For ObjectiveC, given
@interface I - (void) f:(int) y; @end
-
the matcher objcMethodDecl(hasAnyParameter(hasName("y")))
- matches the declaration of method f with hasParameter
+matches the declaration of method f with hasParameter
matching y.
For blocks, given
b = ^(int y) { printf("%d", y) };
-
the matcher blockDecl(hasAnyParameter(hasName("y")))
- matches the declaration of the block b with hasParameter
+matches the declaration of the block b with hasParameter
matching y.
</pre></td></tr>
@@ -8977,18 +6680,15 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
class X { void f(int x) {} };
-
-The matcher
-cxxMethodDecl(hasParameter(0, hasType(asString("int"))))
-matches f
+cxxMethodDecl(hasParameter(0, hasType(varDecl())))
+ matches f(int x) {}
with hasParameter(...)
-matching int x.
+ matching int x
For ObjectiveC, given
@interface I - (void) f:(int) y; @end
-
-The matcher objcMethodDecl(hasParameter(0, hasName("y")))
+the matcher objcMethodDecl(hasParameter(0, hasName("y")))
matches the declaration of method f with hasParameter
matching y.
</pre></td></tr>
@@ -8997,26 +6697,19 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html">BlockDecl</a>></td><td class="name" onclick="toggle('hasTypeLoc0')"><a name="hasTypeLoc0Anchor">hasTypeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr>
<tr><td colspan="4" class="doc" id="hasTypeLoc0"><pre>Matches if the type location of a node matches the inner matcher.
-Given
+Examples:
int x;
-The matcher declaratorDecl(hasTypeLoc(loc(asString("int"))))
-matches int x.
-
-Given
-struct point { point(double, double); };
-point p = point(1.0, -1.0);
+declaratorDecl(hasTypeLoc(loc(asString("int"))))
+ matches int x
-The matcher
-cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("point"))))
-matches point(1.0, -1.0).
+auto x = int(3);
+cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("int"))))
+ matches int(3)
-Given
struct Foo { Foo(int, int); };
-Foo x = Foo(1, 2);
-
-The matcher cxxTemporaryObjectExpr(hasTypeLoc(
- loc(asString("Foo"))))
-matches Foo(1, 2).
+auto x = Foo(1, 2);
+cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo"))))
+ matches Foo(1, 2)
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html">BlockDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>,
@@ -9035,14 +6728,10 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
int *a;
- const int *b;
- int * const c = nullptr;
- const float *f;
-
-The matcher pointerType(pointee(isConstQualified(), isInteger()))
-matches const int *,
-but does not match int * const
-or const float *.
+ int const *b;
+ float const *f;
+pointerType(pointee(isConstQualified(), isInteger()))
+ matches "int const *b"
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockPointerType.html">BlockPointerType</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html">MemberPointerType</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1PointerType.html">PointerType</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ReferenceType.html">ReferenceType</a>>
@@ -9052,26 +6741,19 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>></td><td class="name" onclick="toggle('hasTypeLoc1')"><a name="hasTypeLoc1Anchor">hasTypeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr>
<tr><td colspan="4" class="doc" id="hasTypeLoc1"><pre>Matches if the type location of a node matches the inner matcher.
-Given
+Examples:
int x;
-The matcher declaratorDecl(hasTypeLoc(loc(asString("int"))))
-matches int x.
-
-Given
-struct point { point(double, double); };
-point p = point(1.0, -1.0);
+declaratorDecl(hasTypeLoc(loc(asString("int"))))
+ matches int x
-The matcher
-cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("point"))))
-matches point(1.0, -1.0).
+auto x = int(3);
+cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("int"))))
+ matches int(3)
-Given
struct Foo { Foo(int, int); };
-Foo x = Foo(1, 2);
-
-The matcher cxxTemporaryObjectExpr(hasTypeLoc(
- loc(asString("Foo"))))
-matches Foo(1, 2).
+auto x = Foo(1, 2);
+cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo"))))
+ matches Foo(1, 2)
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html">BlockDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>,
@@ -9094,31 +6776,21 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
X, while varDecl(hasType(cxxRecordDecl(hasName("X")))) matches the
declaration of x.
+Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
+ and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
+ and friend class X (matcher = friendDecl(hasType("X"))
+ and public virtual X (matcher = cxxBaseSpecifier(hasType(
+ cxxRecordDecl(hasName("X"))))
class X {};
void y(X &x) { x; X z; }
class Y { friend class X; };
class Z : public virtual X {};
-The matcher expr(hasType(cxxRecordDecl(hasName("X"))))
-matches x and z.
-The matcher varDecl(hasType(cxxRecordDecl(hasName("X"))))
-matches z.
-The matcher friendDecl(hasType(asString("class X")))
-matches friend class X.
-The matcher cxxRecordDecl(hasAnyBase(cxxBaseSpecifier(hasType(
-asString("X"))).bind("b"))) matches
-class Z : public virtual X {},
-with cxxBaseSpecifier(...)
-matching public virtual X.
-
-Given
+Example matches class Derived
+(matcher = cxxRecordDecl(hasAnyBase(hasType(cxxRecordDecl(hasName("Base"))))))
class Base {};
class Derived : Base {};
-The matcher
-cxxRecordDecl(hasAnyBase(hasType(cxxRecordDecl(hasName("Base")))))
-matches class Derived : Base {}.
-
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FriendDecl.html">FriendDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>>
</pre></td></tr>
@@ -9128,25 +6800,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasType4"><pre>Matches if the expression's or declaration's type matches a type
matcher.
-Exmaple
+Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
+ and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
+ and U (matcher = typedefDecl(hasType(asString("int")))
+ and friend class X (matcher = friendDecl(hasType("X"))
+ and public virtual X (matcher = cxxBaseSpecifier(hasType(
+ asString("class X")))
class X {};
void y(X &x) { x; X z; }
typedef int U;
class Y { friend class X; };
class Z : public virtual X {};
-
-The matcher expr(hasType(cxxRecordDecl(hasName("X"))))
-matches x and z.
-The matcher varDecl(hasType(cxxRecordDecl(hasName("X"))))
-matches z
-The matcher typedefDecl(hasType(asString("int")))
-matches typedef int U
-The matcher friendDecl(hasType(asString("class X")))
-matches friend class X
-The matcher cxxRecordDecl(hasAnyBase(cxxBaseSpecifier(hasType(
-asString("X"))).bind("b"))) matches class Z : public virtual X {},
-with cxxBaseSpecifier(...)
-matching public virtual X.
</pre></td></tr>
@@ -9156,10 +6820,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
void f(int i);
int y;
- void foo() {
- f(y);
- }
-The matcher callExpr(
+ f(y);
+callExpr(
forEachArgumentWithParam(
declRefExpr(to(varDecl(hasName("y")))),
parmVarDecl(hasType(isInteger()))
@@ -9182,15 +6844,14 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
void f(int i);
- void foo(int y) {
- f(y);
- void (*f_ptr)(int) = f;
- f_ptr(y);
- }
-The matcher callExpr(
+ int y;
+ f(y);
+ void (*f_ptr)(int) = f;
+ f_ptr(y);
+callExpr(
forEachArgumentWithParamType(
declRefExpr(to(varDecl(hasName("y")))),
- qualType(isInteger()).bind("type")
+ qualType(isInteger()).bind("type)
))
matches f(y) and f_ptr(y)
with declRefExpr(...)
@@ -9205,19 +6866,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
expression, or an ObjC-message-send expression.
Given
- void x(int, int, int) { int y = 42; x(1, y, 42); }
-The matcher
-callExpr(hasAnyArgument(ignoringImplicit(declRefExpr()))) matches
-x(1, y, 42) with hasAnyArgument(...)
+ void x(int, int, int) { int y; x(1, y, 42); }
+callExpr(hasAnyArgument(declRefExpr()))
+ matches x(1, y, 42)
+with hasAnyArgument(...)
matching y
For ObjectiveC, given
@interface I - (void) f:(int) y; @end
void foo(I *i) { [i f:12]; }
-
-The matcher
objcMessageExpr(hasAnyArgument(integerLiteral(equals(12))))
-matches [i f:12]
+ matches [i f:12]
</pre></td></tr>
@@ -9225,17 +6884,15 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasArgument1"><pre>Matches the n'th argument of a call expression or a constructor
call expression.
-Given
+Example matches y in x(y)
+ (matcher = callExpr(hasArgument(0, declRefExpr())))
void x(int) { int y; x(y); }
-The matcher callExpr(hasArgument(0, declRefExpr().bind("arg")))
-matches x(y),
-with declRefExpr() matching y.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>></td><td class="name" onclick="toggle('hasDeclaration13')"><a name="hasDeclaration13Anchor">hasDeclaration</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration13"><pre>Matches a node if the declaration associated with that node
- matches the given matcher.
+matches the given matcher.
The associated declaration is:
- for type nodes, the declaration of the underlying type
@@ -9245,25 +6902,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
- for CXXNewExpr, the declaration of the operator new
- for ObjCIvarExpr, the declaration of the ivar
-Given
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
class X {};
typedef X Y;
Y y;
-
-For type nodes, hasDeclaration will generally match the declaration of the
-sugared type, i.e., the matcher
-varDecl(hasType(qualType(hasDeclaration(decl().bind("d"))))),
-matches Y y, with
-the matcher decl() matching
-typedef X Y;.
-A common use case is to match the underlying, desugared type.
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
This can be achieved by using the hasUnqualifiedDesugaredType matcher:
-varDecl(hasType(hasUnqualifiedDesugaredType(
- recordType(hasDeclaration(decl().bind("d"))))))
-matches Y y.
-In this matcher, the matcher decl() will match the
-CXXRecordDecl
-class X {};.
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>>,
@@ -9280,12 +6929,10 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
class A { A() : i(42), j(42) {} int i; int j; };
-
-The matcher cxxConstructorDecl(forEachConstructorInitializer(
- forField(fieldDecl().bind("x"))))
-matches the constructor of A twice, with
-fieldDecl() matching i and
-j respectively.
+cxxConstructorDecl(forEachConstructorInitializer(
+ forField(decl().bind("x"))
+))
+ will trigger two matches, binding for 'i' and 'j' respectively.
</pre></td></tr>
@@ -9297,11 +6944,10 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Foo() : foo_(1) { }
int foo_;
};
-
-The matcher cxxRecordDecl(has(cxxConstructorDecl(
+cxxRecordDecl(has(cxxConstructorDecl(
hasAnyConstructorInitializer(anything())
)))
-matches Foo, hasAnyConstructorInitializer matches foo_(1)
+ record matches Foo, hasAnyConstructorInitializer matches foo_(1)
</pre></td></tr>
@@ -9313,11 +6959,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Foo() : foo_(1) { }
int foo_;
};
-
-The matcher
cxxRecordDecl(has(cxxConstructorDecl(hasAnyConstructorInitializer(
forField(hasName("foo_"))))))
-matches Foo
+ matches Foo
with forField matching foo_
</pre></td></tr>
@@ -9325,26 +6969,19 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>></td><td class="name" onclick="toggle('hasTypeLoc2')"><a name="hasTypeLoc2Anchor">hasTypeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr>
<tr><td colspan="4" class="doc" id="hasTypeLoc2"><pre>Matches if the type location of a node matches the inner matcher.
-Given
+Examples:
int x;
-The matcher declaratorDecl(hasTypeLoc(loc(asString("int"))))
-matches int x.
-
-Given
-struct point { point(double, double); };
-point p = point(1.0, -1.0);
+declaratorDecl(hasTypeLoc(loc(asString("int"))))
+ matches int x
-The matcher
-cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("point"))))
-matches point(1.0, -1.0).
+auto x = int(3);
+cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("int"))))
+ matches int(3)
-Given
struct Foo { Foo(int, int); };
-Foo x = Foo(1, 2);
-
-The matcher cxxTemporaryObjectExpr(hasTypeLoc(
- loc(asString("Foo"))))
-matches Foo(1, 2).
+auto x = Foo(1, 2);
+cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo"))))
+ matches Foo(1, 2)
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html">BlockDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>,
@@ -9365,11 +7002,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Foo() : foo_(1) { }
int foo_;
};
-
-The matcher
cxxRecordDecl(has(cxxConstructorDecl(hasAnyConstructorInitializer(
withInitializer(integerLiteral(equals(1)))))))
-matches Foo
+ matches Foo
with withInitializer matching (1)
</pre></td></tr>
@@ -9384,14 +7019,11 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
int m;
int f(X x) { x.m; return m; }
};
-
-
-The matcher
memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))))
-matches x.m, but not m; however,
-The matcher memberExpr(hasObjectExpression(hasType(pointsTo(
-cxxRecordDecl(hasName("X"))))))
-matches m (aka. this->m), but not x.m.
+ matches `x.m`, but not `m`; however,
+memberExpr(hasObjectExpression(hasType(pointsTo(
+ cxxRecordDecl(hasName("X"))))))
+ matches `m` (aka. `this->m`), but not `x.m`.
</pre></td></tr>
@@ -9401,20 +7033,12 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
class Y { void x() { this->x(); x(); Y y; y.x(); } };
void f() { f(); }
-
-The matcher callExpr(callee(expr().bind("callee")))
-matches this->x(), x(), y.x(), f()
-with expr() inside of callee
-matching this->x, x,
-y.x, f respectively
+callExpr(callee(expr()))
+ matches this->x(), x(), y.x(), f()
+with callee(...)
+ matching this->x, x, y.x, f respectively
Given
- struct Dummy {};
- // makes sure there is a callee, otherwise there would be no callee,
- // just a builtin operator
- Dummy operator+(Dummy, Dummy);
- // not defining a '*' operator
-
template <typename... Args>
auto sum(Args... args) {
return (0 + ... + args);
@@ -9424,14 +7048,10 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
auto multiply(Args... args) {
return (args * ... * 1);
}
-
-The matcher cxxFoldExpr(callee(expr().bind("op")))
-matches (0 + ... + args)
-with callee(...) matching *,
-but does not match (args * ... * 1).
-A CXXFoldExpr only has an UnresolvedLookupExpr as a callee.
-When there are no define operators that could be used instead of builtin
-ones, then there will be no callee .
+cxxFoldExpr(callee(expr()))
+ matches (args * ... * 1)
+with callee(...)
+ matching *
Note: Callee cannot take the more general internal::Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>>
because this introduces ambiguous overloads with calls to Callee taking a
@@ -9443,37 +7063,16 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFoldExpr.html">CXXFoldExpr</a>></td><td class="name" onclick="toggle('hasEitherOperand2')"><a name="hasEitherOperand2Anchor">hasEitherOperand</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasEitherOperand2"><pre>Matches if either the left hand side or the right hand side of a
binary operator or fold expression matches.
-
-Given
- struct S {};
- bool operator ==(const S&, const S&);
-
- void f(int a, const S&lhs, const S&rhs) {
- a + 0;
- lhs == rhs;
- lhs != rhs;
- }
-
- template <typename ...Ts>
- auto sum(Ts... args) {
- return (0 + ... + args);
- }
-
-
-The matcher binaryOperator(hasEitherOperand(integerLiteral()))
-matches a + 0.
-The matcher cxxOperatorCallExpr(hasEitherOperand(declRefExpr(to(
-parmVarDecl(hasName("lhs")))))) matches lhs == rhs and
-lhs != rhs.
-The matcher cxxFoldExpr(hasEitherOperand(integerLiteral()))
-matches (0 + ... + args).
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFoldExpr.html">CXXFoldExpr</a>></td><td class="name" onclick="toggle('hasFoldInit0')"><a name="hasFoldInit0Anchor">hasFoldInit</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMacher</td></tr>
<tr><td colspan="4" class="doc" id="hasFoldInit0"><pre>Matches the operand that does not contain the parameter pack.
-Given
+Example matches `(0 + ... + args)` and `(args * ... * 1)`
+ (matcher = cxxFoldExpr(hasFoldInit(expr())))
+ with hasFoldInit(...)
+ matching `0` and `1` respectively
template <typename... Args>
auto sum(Args... args) {
return (0 + ... + args);
@@ -9483,27 +7082,14 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
auto multiply(Args... args) {
return (args * ... * 1);
}
-
-
-The matcher cxxFoldExpr(hasFoldInit(expr().bind("init")))
-matches (0 + ... + args) and (args * ... * 1)
-with hasFoldInit(expr().bind("init")) matching
-0 and 1.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFoldExpr.html">CXXFoldExpr</a>></td><td class="name" onclick="toggle('hasLHS4')"><a name="hasLHS4Anchor">hasLHS</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasLHS4"><pre>Matches the left hand side of binary operator expressions.
-Given
-void foo(bool a, bool b) {
- a || b;
-}
-
-The matcher binaryOperator(hasLHS(expr().bind("lhs")))
-matches a || b,
-with expr()
-matching a.
+Example matches a (matcher = binaryOperator(hasLHS()))
+ a || b
</pre></td></tr>
@@ -9511,25 +7097,22 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasOperands2"><pre>Matches if both matchers match with opposite sides of the binary operator
or fold expression.
-Given
-void foo() {
- 1 + 2; // Match
- 2 + 1; // Match
- 1 + 1; // No match
- 2 + 2; // No match
-}
-The matcher binaryOperator(hasOperands(integerLiteral(equals(1)),
- integerLiteral(equals(2))))
-matches 1 + 2 and 2 + 1,
-but does not match 1 + 1
-or 2 + 2.
+Example matcher = binaryOperator(hasOperands(integerLiteral(equals(1),
+ integerLiteral(equals(2)))
+ 1 + 2 // Match
+ 2 + 1 // Match
+ 1 + 1 // No match
+ 2 + 2 // No match
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFoldExpr.html">CXXFoldExpr</a>></td><td class="name" onclick="toggle('hasPattern0')"><a name="hasPattern0Anchor">hasPattern</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMacher</td></tr>
<tr><td colspan="4" class="doc" id="hasPattern0"><pre>Matches the operand that contains the parameter pack.
-Given
+Example matches `(0 + ... + args)`
+ (matcher = cxxFoldExpr(hasPattern(expr())))
+ with hasPattern(...)
+ matching `args`
template <typename... Args>
auto sum(Args... args) {
return (0 + ... + args);
@@ -9539,27 +7122,14 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
auto multiply(Args... args) {
return (args * ... * 1);
}
-
-
-The matcher cxxFoldExpr(hasPattern(expr().bind("pattern")))
-matches (0 + ... + args) and (args * ... * 1),
-with hasPattern(expr().bind("pattern")) matching
-args two times.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFoldExpr.html">CXXFoldExpr</a>></td><td class="name" onclick="toggle('hasRHS4')"><a name="hasRHS4Anchor">hasRHS</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasRHS4"><pre>Matches the right hand side of binary operator expressions.
-Given
-void foo(bool a, bool b) {
- a || b;
-}
-
-The matcher binaryOperator(hasRHS(expr().bind("rhs")))
-matches a || b,
-with expr()
-matching b.
+Example matches b (matcher = binaryOperator(hasRHS()))
+ a || b
</pre></td></tr>
@@ -9570,32 +7140,27 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
other declarations of the same function or coroutine.
Given
-void foo() {
for (;;) {}
-}
-The matcher forStmt(hasBody(compoundStmt().bind("body")))
-matches for (;;) {}
+forStmt(hasBody(compoundStmt()))
+ matches 'for (;;) {}'
with compoundStmt()
- matching {}
+ matching '{}'
Given
void f();
void f() {}
-The matcher functionDecl(hasBody(compoundStmt().bind("compound")))
-f
+functionDecl(hasBody(compoundStmt()))
+ matches 'void f() {}'
with compoundStmt()
-matching {}
-but does not match void f();
+ matching '{}'
+ but does not match 'void f();'
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXForRangeStmt.html">CXXForRangeStmt</a>></td><td class="name" onclick="toggle('hasInitStatement2')"><a name="hasInitStatement2Anchor">hasInitStatement</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasInitStatement2"><pre>Matches selection statements with initializer.
-Given
- struct vec { int* begin(); int* end(); };
- int foobar();
- vec& get_range();
+Given:
void foo() {
if (int i = foobar(); i > 0) {}
switch (int i = foobar(); i) {}
@@ -9606,71 +7171,51 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
switch (foobar()) {}
for (auto& x : get_range()) {}
}
-
-The matcher ifStmt(hasInitStatement(anything()))
- matches the if statement if (int i = foobar(); i > 0) {}
- in foo but not if (foobar() > 0) {} in bar.
-The matcher switchStmt(hasInitStatement(anything()))
- matches the switch statement switch (int i = foobar(); i) {}
- in foo but not switch (foobar()) {} in bar.
-The matcher cxxForRangeStmt(hasInitStatement(anything()))
- matches the range for statement
- for (auto& a = get_range(); auto& x : a) {} in foo
- but not for (auto& x : get_range()) {} in bar.
+ifStmt(hasInitStatement(anything()))
+ matches the if statement in foo but not in bar.
+switchStmt(hasInitStatement(anything()))
+ matches the switch statement in foo but not in bar.
+cxxForRangeStmt(hasInitStatement(anything()))
+ matches the range for statement in foo but not in bar.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXForRangeStmt.html">CXXForRangeStmt</a>></td><td class="name" onclick="toggle('hasLoopVariable0')"><a name="hasLoopVariable0Anchor">hasLoopVariable</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasLoopVariable0"><pre>Matches the initialization statement of a for loop.
-Given
- void foo() {
- int a[42] = {};
+Example:
+ forStmt(hasLoopVariable(anything()))
+matches 'int x' in
for (int x : a) { }
- }
-
-The matcher cxxForRangeStmt(hasLoopVariable(anything()))
-matches for (int x : a) { }
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXForRangeStmt.html">CXXForRangeStmt</a>></td><td class="name" onclick="toggle('hasRangeInit0')"><a name="hasRangeInit0Anchor">hasRangeInit</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasRangeInit0"><pre>Matches the range initialization statement of a for loop.
-Given
- void foo() {
- int a[42] = {};
+Example:
+ forStmt(hasRangeInit(anything()))
+matches 'a' in
for (int x : a) { }
- }
-
-The matcher cxxForRangeStmt(hasRangeInit(anything()))
-matches for (int x : a) { }
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>></td><td class="name" onclick="toggle('hasTypeLoc3')"><a name="hasTypeLoc3Anchor">hasTypeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr>
<tr><td colspan="4" class="doc" id="hasTypeLoc3"><pre>Matches if the type location of a node matches the inner matcher.
-Given
+Examples:
int x;
-The matcher declaratorDecl(hasTypeLoc(loc(asString("int"))))
-matches int x.
-
-Given
-struct point { point(double, double); };
-point p = point(1.0, -1.0);
+declaratorDecl(hasTypeLoc(loc(asString("int"))))
+ matches int x
-The matcher
-cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("point"))))
-matches point(1.0, -1.0).
+auto x = int(3);
+cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("int"))))
+ matches int(3)
-Given
struct Foo { Foo(int, int); };
-Foo x = Foo(1, 2);
-
-The matcher cxxTemporaryObjectExpr(hasTypeLoc(
- loc(asString("Foo"))))
-matches Foo(1, 2).
+auto x = Foo(1, 2);
+cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo"))))
+ matches Foo(1, 2)
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html">BlockDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>,
@@ -9690,16 +7235,13 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
class Y { public: void m(); };
Y g();
- class X : public Y { public: void g(); };
+ class X : public Y { void g(); };
void z(Y y, X x) { y.m(); x.m(); x.g(); (g()).m(); }
-
-The matcher cxxMemberCallExpr(onImplicitObjectArgument(hasType(
+cxxMemberCallExpr(onImplicitObjectArgument(hasType(
cxxRecordDecl(hasName("Y")))))
-matches y.m(), x.m() and (g()).m()
-but does not match x.g().
-The matcher cxxMemberCallExpr(on(callExpr()))
-only matches (g()).m(), because the parens are ignored.
-FIXME: should they be ignored? (ignored bc of `on`)
+ matches `y.m()`, `x.m()` and (`g()).m()`, but not `x.g()`).
+cxxMemberCallExpr(on(callExpr()))
+ only matches `(g()).m()` (the parens are ignored).
FIXME: Overload to allow directly matching types?
</pre></td></tr>
@@ -9714,15 +7256,12 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Y g();
class X : public Y {};
void z(Y y, X x) { y.m(); (g()).m(); x.m(); }
-
-The matcher
cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("Y")))))
- matches y.m() and (g()).m().
-The matcher
+ matches `y.m()` and `(g()).m()`.
cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("X")))))
- matches x.m().
-The matcher cxxMemberCallExpr(on(callExpr()))
- matches (g()).m().
+ matches `x.m()`.
+cxxMemberCallExpr(on(callExpr()))
+ matches `(g()).m()`.
FIXME: Overload to allow directly matching types?
</pre></td></tr>
@@ -9730,35 +7269,24 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMemberCallExpr.html">CXXMemberCallExpr</a>></td><td class="name" onclick="toggle('thisPointerType1')"><a name="thisPointerType1Anchor">thisPointerType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="thisPointerType1"><pre>Overloaded to match the type's declaration.
-
-Given
- class Y { public: void m(); };
- class X : public Y { public: void g(); };
- void z() { Y y; y.m(); Y *p; p->m(); X x; x.m(); x.g(); }
-
-The matcher cxxMemberCallExpr(thisPointerType(
- cxxRecordDecl(hasName("Y"))))
- matches y.m(), p->m() and x.m().
-The matcher cxxMemberCallExpr(thisPointerType(
- cxxRecordDecl(hasName("X"))))
- matches x.g().
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMemberCallExpr.html">CXXMemberCallExpr</a>></td><td class="name" onclick="toggle('thisPointerType0')"><a name="thisPointerType0Anchor">thisPointerType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="thisPointerType0"><pre>Matches if the type of the expression's implicit object argument either
- matches the InnerMatcher, or is a pointer to a type that matches the
+matches the InnerMatcher, or is a pointer to a type that matches the
InnerMatcher.
Given
- class Y { public: void m() const; };
- class X : public Y { public: void g(); };
- void z() { const Y y; y.m(); const Y *p; p->m(); X x; x.m(); x.g(); }
-
-The matcher
-cxxMemberCallExpr(thisPointerType(isConstQualified()))
-matches y.m(), x.m() and p->m(),
-but not x.g().
+ class Y { public: void m(); };
+ class X : public Y { void g(); };
+ void z() { Y y; y.m(); Y *p; p->m(); X x; x.m(); x.g(); }
+cxxMemberCallExpr(thisPointerType(hasDeclaration(
+ cxxRecordDecl(hasName("Y")))))
+ matches `y.m()`, `p->m()` and `x.m()`.
+cxxMemberCallExpr(thisPointerType(hasDeclaration(
+ cxxRecordDecl(hasName("X")))))
+ matches `x.g()`.
</pre></td></tr>
@@ -9770,27 +7298,19 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
class A { virtual void f(); };
class B : public A { void f(); };
class C : public B { void f(); };
-
-The matcher cxxMethodDecl(ofClass(hasName("C")),
- forEachOverridden(cxxMethodDecl().bind("b")))
-matches void f() of C ,
-with cxxMethodDecl() matching
-virtual void f() of A ,
-but the matcher does not match void f() of B because
-it is not overridden by C::f.
+cxxMethodDecl(ofClass(hasName("C")),
+ forEachOverridden(cxxMethodDecl().bind("b"))).bind("d")
+ matches once, with "b" binding "A::f" and "d" binding "C::f" (Note
+ that B::f is not overridden by C::f).
The check can produce multiple matches in case of multiple inheritance, e.g.
class A1 { virtual void f(); };
class A2 { virtual void f(); };
class C : public A1, public A2 { void f(); };
-
-The matcher cxxMethodDecl(ofClass(hasName("C")),
- forEachOverridden(cxxMethodDecl().bind("b")))
-matches void f() of C with the inner
-cxxMethodDecl() matching virtual void f()
-inside of A1 , and void f() of C with the inner
-cxxMethodDecl() matching virtual void f()
-inside of A2.
+cxxMethodDecl(ofClass(hasName("C")),
+ forEachOverridden(cxxMethodDecl().bind("b"))).bind("d")
+ matches twice, once with "b" binding "A1::f" and "d" binding "C::f", and
+ once with "b" binding "A2::f" and "d" binding "C::f".
</pre></td></tr>
@@ -9802,52 +7322,40 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
FIXME: What other kind of declarations would we need to generalize
this to?
-Given
+Example matches A() in the last line
+ (matcher = cxxConstructExpr(hasDeclaration(cxxMethodDecl(
+ ofClass(hasName("A"))))))
class A {
public:
A();
- void foo();
};
-
-The matcher cxxMethodDecl(ofClass(hasName("A")))
-matches A() and void foo().
+ A a = A();
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>></td><td class="name" onclick="toggle('hasAnyPlacementArg0')"><a name="hasAnyPlacementArg0Anchor">hasAnyPlacementArg</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasAnyPlacementArg0"><pre>Matches any placement new expression arguments.
-Given
- void* operator new(decltype(sizeof(void*)), void*);
- struct MyClass { int x; };
- unsigned char Storage[sizeof(MyClass) * 10];
+Given:
MyClass *p1 = new (Storage) MyClass();
-
-
-The matcher cxxNewExpr(hasAnyPlacementArg(anything()))
-matches new (Storage) MyClass().
+cxxNewExpr(hasAnyPlacementArg(anything()))
+ matches the expression 'new (Storage, 16) MyClass()'.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>></td><td class="name" onclick="toggle('hasArraySize0')"><a name="hasArraySize0Anchor">hasArraySize</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasArraySize0"><pre>Matches array new expressions with a given array size.
-Given
- void* operator new(decltype(sizeof(void*)));
- struct MyClass { int x; };
+Given:
MyClass *p1 = new MyClass[10];
-
-
-The matcher
-cxxNewExpr(hasArraySize(
- ignoringImplicit(integerLiteral(equals(10)))))
-matches new MyClass[10].
+cxxNewExpr(hasArraySize(integerLiteral(equals(10))))
+ matches the expression 'new MyClass[10]'.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>></td><td class="name" onclick="toggle('hasDeclaration12')"><a name="hasDeclaration12Anchor">hasDeclaration</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration12"><pre>Matches a node if the declaration associated with that node
- matches the given matcher.
+matches the given matcher.
The associated declaration is:
- for type nodes, the declaration of the underlying type
@@ -9857,25 +7365,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
- for CXXNewExpr, the declaration of the operator new
- for ObjCIvarExpr, the declaration of the ivar
-Given
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
class X {};
typedef X Y;
Y y;
-
-For type nodes, hasDeclaration will generally match the declaration of the
-sugared type, i.e., the matcher
-varDecl(hasType(qualType(hasDeclaration(decl().bind("d"))))),
-matches Y y, with
-the matcher decl() matching
-typedef X Y;.
-A common use case is to match the underlying, desugared type.
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
This can be achieved by using the hasUnqualifiedDesugaredType matcher:
-varDecl(hasType(hasUnqualifiedDesugaredType(
- recordType(hasDeclaration(decl().bind("d"))))))
-matches Y y.
-In this matcher, the matcher decl() will match the
-CXXRecordDecl
-class X {};.
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>>,
@@ -9890,42 +7390,29 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>></td><td class="name" onclick="toggle('hasPlacementArg0')"><a name="hasPlacementArg0Anchor">hasPlacementArg</a></td><td>unsigned Index, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasPlacementArg0"><pre>Matches placement new expression arguments.
-Given
- void *operator new(decltype(sizeof(void*)), int, void*);
- struct MyClass { int x; };
- unsigned char Storage[sizeof(MyClass) * 10];
- MyClass *p1 = new (16, Storage) MyClass();
-
-
-The matcher cxxNewExpr(hasPlacementArg(0,
- integerLiteral(equals(16))))
-matches new (16, Storage) MyClass().
+Given:
+ MyClass *p1 = new (Storage, 16) MyClass();
+cxxNewExpr(hasPlacementArg(1, integerLiteral(equals(16))))
+ matches the expression 'new (Storage, 16) MyClass()'.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>></td><td class="name" onclick="toggle('hasTypeLoc4')"><a name="hasTypeLoc4Anchor">hasTypeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr>
<tr><td colspan="4" class="doc" id="hasTypeLoc4"><pre>Matches if the type location of a node matches the inner matcher.
-Given
+Examples:
int x;
-The matcher declaratorDecl(hasTypeLoc(loc(asString("int"))))
-matches int x.
-
-Given
-struct point { point(double, double); };
-point p = point(1.0, -1.0);
+declaratorDecl(hasTypeLoc(loc(asString("int"))))
+ matches int x
-The matcher
-cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("point"))))
-matches point(1.0, -1.0).
+auto x = int(3);
+cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("int"))))
+ matches int(3)
-Given
struct Foo { Foo(int, int); };
-Foo x = Foo(1, 2);
-
-The matcher cxxTemporaryObjectExpr(hasTypeLoc(
- loc(asString("Foo"))))
-matches Foo(1, 2).
+auto x = Foo(1, 2);
+cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo"))))
+ matches Foo(1, 2)
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html">BlockDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>,
@@ -9941,45 +7428,14 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>></td><td class="name" onclick="toggle('hasEitherOperand1')"><a name="hasEitherOperand1Anchor">hasEitherOperand</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasEitherOperand1"><pre>Matches if either the left hand side or the right hand side of a
binary operator or fold expression matches.
-
-Given
- struct S {};
- bool operator ==(const S&, const S&);
-
- void f(int a, const S&lhs, const S&rhs) {
- a + 0;
- lhs == rhs;
- lhs != rhs;
- }
-
- template <typename ...Ts>
- auto sum(Ts... args) {
- return (0 + ... + args);
- }
-
-
-The matcher binaryOperator(hasEitherOperand(integerLiteral()))
-matches a + 0.
-The matcher cxxOperatorCallExpr(hasEitherOperand(declRefExpr(to(
-parmVarDecl(hasName("lhs")))))) matches lhs == rhs and
-lhs != rhs.
-The matcher cxxFoldExpr(hasEitherOperand(integerLiteral()))
-matches (0 + ... + args).
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>></td><td class="name" onclick="toggle('hasLHS1')"><a name="hasLHS1Anchor">hasLHS</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasLHS1"><pre>Matches the left hand side of binary operator expressions.
-Given
-void foo(bool a, bool b) {
- a || b;
-}
-
-The matcher binaryOperator(hasLHS(expr().bind("lhs")))
-matches a || b,
-with expr()
-matching a.
+Example matches a (matcher = binaryOperator(hasLHS()))
+ a || b
</pre></td></tr>
@@ -9987,64 +7443,44 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasOperands1"><pre>Matches if both matchers match with opposite sides of the binary operator
or fold expression.
-Given
-void foo() {
- 1 + 2; // Match
- 2 + 1; // Match
- 1 + 1; // No match
- 2 + 2; // No match
-}
-The matcher binaryOperator(hasOperands(integerLiteral(equals(1)),
- integerLiteral(equals(2))))
-matches 1 + 2 and 2 + 1,
-but does not match 1 + 1
-or 2 + 2.
+Example matcher = binaryOperator(hasOperands(integerLiteral(equals(1),
+ integerLiteral(equals(2)))
+ 1 + 2 // Match
+ 2 + 1 // Match
+ 1 + 1 // No match
+ 2 + 2 // No match
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>></td><td class="name" onclick="toggle('hasRHS1')"><a name="hasRHS1Anchor">hasRHS</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasRHS1"><pre>Matches the right hand side of binary operator expressions.
-Given
-void foo(bool a, bool b) {
- a || b;
-}
-
-The matcher binaryOperator(hasRHS(expr().bind("rhs")))
-matches a || b,
-with expr()
-matching b.
+Example matches b (matcher = binaryOperator(hasRHS()))
+ a || b
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>></td><td class="name" onclick="toggle('hasUnaryOperand1')"><a name="hasUnaryOperand1Anchor">hasUnaryOperand</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasUnaryOperand1"><pre>Matches if the operand of a unary operator matches.
-void foo() {
- !true;
-}
-
-The matcher
-unaryOperator(hasUnaryOperand(cxxBoolLiteral(equals(true))))
-matches !true.
+Example matches true (matcher = hasUnaryOperand(
+ cxxBoolLiteral(equals(true))))
+ !true
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>></td><td class="name" onclick="toggle('hasAnyBase0')"><a name="hasAnyBase0Anchor">hasAnyBase</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>> BaseSpecMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasAnyBase0"><pre>Matches C++ classes that have a direct or indirect base matching BaseSpecMatcher.
-Given
- class Foo {};
+Example:
+matcher hasAnyBase(hasType(cxxRecordDecl(hasName("SpecialBase"))))
+ class Foo;
class Bar : Foo {};
class Baz : Bar {};
- class SpecialBase {};
+ class SpecialBase;
class Proxy : SpecialBase {}; // matches Proxy
class IndirectlyDerived : Proxy {}; //matches IndirectlyDerived
-
-The matcher
-cxxRecordDecl(hasAnyBase(hasType(cxxRecordDecl(hasName("SpecialBase")))))
-matches Proxy and IndirectlyDerived
FIXME: Refactor this and isDerivedFrom to reuse implementation.
</pre></td></tr>
@@ -10052,31 +7488,26 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>></td><td class="name" onclick="toggle('hasDirectBase0')"><a name="hasDirectBase0Anchor">hasDirectBase</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>> BaseSpecMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDirectBase0"><pre>Matches C++ classes that have a direct base matching BaseSpecMatcher.
-Given
- class Foo {};
+Example:
+matcher hasDirectBase(hasType(cxxRecordDecl(hasName("SpecialBase"))))
+ class Foo;
class Bar : Foo {};
class Baz : Bar {};
- class SpecialBase {};
+ class SpecialBase;
class Proxy : SpecialBase {}; // matches Proxy
class IndirectlyDerived : Proxy {}; // doesn't match
-
-The matcher
-cxxRecordDecl(hasDirectBase(hasType(cxxRecordDecl(hasName("SpecialBase")))))
-matches Proxy
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>></td><td class="name" onclick="toggle('hasMethod0')"><a name="hasMethod0Anchor">hasMethod</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasMethod0"><pre>Matches the first method of a class or struct that satisfies InnerMatcher.
-Given
+Given:
class A { void func(); };
class B { void member(); };
-
-The matcher cxxRecordDecl(hasMethod(hasName("func")))
-matches the declaration of class A { void func(); }
-but does not match class B { void member(); }
+cxxRecordDecl(hasMethod(hasName("func"))) matches the declaration of
+A but not B.
</pre></td></tr>
@@ -10088,29 +7519,22 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Note that a class is not considered to be derived from itself.
Example matches Y, Z, C (Base == hasName("X"))
- class X {};
+ class X;
class Y : public X {}; // directly derived
class Z : public Y {}; // indirectly derived
typedef X A;
typedef A B;
class C : public B {}; // derived from a typedef of X
- class Foo {};
- typedef Foo Alias;
- class Bar : public Alias {};
- // derived from a type that Alias is a typedef of Foo
-
-
-The matcher cxxRecordDecl(isDerivedFrom(hasName("X")))
-matches Y, Z and C.
-The matcher cxxRecordDecl(isDerivedFrom(hasName("Foo")))
-matches Bar.
+In the following example, Bar matches isDerivedFrom(hasName("X")):
+ class Foo;
+ typedef Foo X;
+ class Bar : public Foo {}; // derived from a type that X is a typedef of
In the following example, Bar matches isDerivedFrom(hasName("NSObject"))
@interface NSObject @end
@interface Bar : NSObject @end
-
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCInterfaceDecl.html">ObjCInterfaceDecl</a>>
</pre></td></tr>
@@ -10121,90 +7545,38 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Note that a class is not considered to be derived from itself.
-Given
- class X {};
+Example matches Y, C (Base == hasName("X"))
+ class X;
class Y : public X {}; // directly derived
class Z : public Y {}; // indirectly derived
typedef X A;
typedef A B;
class C : public B {}; // derived from a typedef of X
-The matcher
-cxxRecordDecl(isDirectlyDerivedFrom(namedDecl(hasName("X"))))
-matches Y and C (Base == hasName("X")
-
In the following example, Bar matches isDerivedFrom(hasName("X")):
- class Foo {};
+ class Foo;
typedef Foo X;
class Bar : public Foo {}; // derived from a type that X is a typedef of
-
-The matcher cxxRecordDecl(isDerivedFrom(hasName("X")))
-matches Bar
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>></td><td class="name" onclick="toggle('isSameOrDerivedFrom0')"><a name="isSameOrDerivedFrom0Anchor">isSameOrDerivedFrom</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>> Base</td></tr>
<tr><td colspan="4" class="doc" id="isSameOrDerivedFrom0"><pre>Similar to isDerivedFrom(), but also matches classes that directly
match Base.
-
-Given
- class X {};
- class Y : public X {}; // directly derived
- class Z : public Y {}; // indirectly derived
- typedef X A;
- typedef A B;
- class C : public B {}; // derived from a typedef of X
-
-The matcher
-cxxRecordDecl(isSameOrDerivedFrom(cxxRecordDecl(hasName("X"))),
-isDefinition())
-matches class X {}, class Y : public X {},
-class Z : public Y {} and class C : public B {}.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRewrittenBinaryOperator.html">CXXRewrittenBinaryOperator</a>></td><td class="name" onclick="toggle('hasEitherOperand3')"><a name="hasEitherOperand3Anchor">hasEitherOperand</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasEitherOperand3"><pre>Matches if either the left hand side or the right hand side of a
binary operator or fold expression matches.
-
-Given
- struct S {};
- bool operator ==(const S&, const S&);
-
- void f(int a, const S&lhs, const S&rhs) {
- a + 0;
- lhs == rhs;
- lhs != rhs;
- }
-
- template <typename ...Ts>
- auto sum(Ts... args) {
- return (0 + ... + args);
- }
-
-
-The matcher binaryOperator(hasEitherOperand(integerLiteral()))
-matches a + 0.
-The matcher cxxOperatorCallExpr(hasEitherOperand(declRefExpr(to(
-parmVarDecl(hasName("lhs")))))) matches lhs == rhs and
-lhs != rhs.
-The matcher cxxFoldExpr(hasEitherOperand(integerLiteral()))
-matches (0 + ... + args).
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRewrittenBinaryOperator.html">CXXRewrittenBinaryOperator</a>></td><td class="name" onclick="toggle('hasLHS2')"><a name="hasLHS2Anchor">hasLHS</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasLHS2"><pre>Matches the left hand side of binary operator expressions.
-Given
-void foo(bool a, bool b) {
- a || b;
-}
-
-The matcher binaryOperator(hasLHS(expr().bind("lhs")))
-matches a || b,
-with expr()
-matching a.
+Example matches a (matcher = binaryOperator(hasLHS()))
+ a || b
</pre></td></tr>
@@ -10212,59 +7584,39 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasOperands3"><pre>Matches if both matchers match with opposite sides of the binary operator
or fold expression.
-Given
-void foo() {
- 1 + 2; // Match
- 2 + 1; // Match
- 1 + 1; // No match
- 2 + 2; // No match
-}
-The matcher binaryOperator(hasOperands(integerLiteral(equals(1)),
- integerLiteral(equals(2))))
-matches 1 + 2 and 2 + 1,
-but does not match 1 + 1
-or 2 + 2.
+Example matcher = binaryOperator(hasOperands(integerLiteral(equals(1),
+ integerLiteral(equals(2)))
+ 1 + 2 // Match
+ 2 + 1 // Match
+ 1 + 1 // No match
+ 2 + 2 // No match
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRewrittenBinaryOperator.html">CXXRewrittenBinaryOperator</a>></td><td class="name" onclick="toggle('hasRHS2')"><a name="hasRHS2Anchor">hasRHS</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasRHS2"><pre>Matches the right hand side of binary operator expressions.
-Given
-void foo(bool a, bool b) {
- a || b;
-}
-
-The matcher binaryOperator(hasRHS(expr().bind("rhs")))
-matches a || b,
-with expr()
-matching b.
+Example matches b (matcher = binaryOperator(hasRHS()))
+ a || b
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXTemporaryObjectExpr.html">CXXTemporaryObjectExpr</a>></td><td class="name" onclick="toggle('hasTypeLoc5')"><a name="hasTypeLoc5Anchor">hasTypeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr>
<tr><td colspan="4" class="doc" id="hasTypeLoc5"><pre>Matches if the type location of a node matches the inner matcher.
-Given
+Examples:
int x;
-The matcher declaratorDecl(hasTypeLoc(loc(asString("int"))))
-matches int x.
-
-Given
-struct point { point(double, double); };
-point p = point(1.0, -1.0);
+declaratorDecl(hasTypeLoc(loc(asString("int"))))
+ matches int x
-The matcher
-cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("point"))))
-matches point(1.0, -1.0).
+auto x = int(3);
+cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("int"))))
+ matches int(3)
-Given
struct Foo { Foo(int, int); };
-Foo x = Foo(1, 2);
-
-The matcher cxxTemporaryObjectExpr(hasTypeLoc(
- loc(asString("Foo"))))
-matches Foo(1, 2).
+auto x = Foo(1, 2);
+cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo"))))
+ matches Foo(1, 2)
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html">BlockDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>,
@@ -10282,19 +7634,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
expression, or an ObjC-message-send expression.
Given
- void x(int, int, int) { int y = 42; x(1, y, 42); }
-The matcher
-callExpr(hasAnyArgument(ignoringImplicit(declRefExpr()))) matches
-x(1, y, 42) with hasAnyArgument(...)
+ void x(int, int, int) { int y; x(1, y, 42); }
+callExpr(hasAnyArgument(declRefExpr()))
+ matches x(1, y, 42)
+with hasAnyArgument(...)
matching y
For ObjectiveC, given
@interface I - (void) f:(int) y; @end
void foo(I *i) { [i f:12]; }
-
-The matcher
objcMessageExpr(hasAnyArgument(integerLiteral(equals(12))))
-matches [i f:12]
+ matches [i f:12]
</pre></td></tr>
@@ -10302,37 +7652,28 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasArgument2"><pre>Matches the n'th argument of a call expression or a constructor
call expression.
-Given
+Example matches y in x(y)
+ (matcher = callExpr(hasArgument(0, declRefExpr())))
void x(int) { int y; x(y); }
-The matcher callExpr(hasArgument(0, declRefExpr().bind("arg")))
-matches x(y),
-with declRefExpr() matching y.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html">CXXUnresolvedConstructExpr</a>></td><td class="name" onclick="toggle('hasTypeLoc6')"><a name="hasTypeLoc6Anchor">hasTypeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr>
<tr><td colspan="4" class="doc" id="hasTypeLoc6"><pre>Matches if the type location of a node matches the inner matcher.
-Given
+Examples:
int x;
-The matcher declaratorDecl(hasTypeLoc(loc(asString("int"))))
-matches int x.
-
-Given
-struct point { point(double, double); };
-point p = point(1.0, -1.0);
+declaratorDecl(hasTypeLoc(loc(asString("int"))))
+ matches int x
-The matcher
-cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("point"))))
-matches point(1.0, -1.0).
+auto x = int(3);
+cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("int"))))
+ matches int(3)
-Given
struct Foo { Foo(int, int); };
-Foo x = Foo(1, 2);
-
-The matcher cxxTemporaryObjectExpr(hasTypeLoc(
- loc(asString("Foo"))))
-matches Foo(1, 2).
+auto x = Foo(1, 2);
+cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo"))))
+ matches Foo(1, 2)
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html">BlockDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>,
@@ -10350,23 +7691,19 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
given matcher; or 2) if the Obj-C message expression's callee's method
declaration matches the given matcher.
-Example 1
+Example matches y.x() (matcher = callExpr(callee(
+ cxxMethodDecl(hasName("x")))))
class Y { public: void x(); };
void z() { Y y; y.x(); }
-The matcher callExpr(callee(cxxMethodDecl(hasName("x"))))
-matches y.x()
+Example 2. Matches [I foo] with
+objcMessageExpr(callee(objcMethodDecl(hasName("foo"))))
-Example 2
@interface I: NSObject
+(void)foo;
@end
...
[I foo]
-
-The matcher
-objcMessageExpr(callee(objcMethodDecl(hasName("foo"))))
-matches [I foo]
</pre></td></tr>
@@ -10376,20 +7713,12 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
class Y { void x() { this->x(); x(); Y y; y.x(); } };
void f() { f(); }
-
-The matcher callExpr(callee(expr().bind("callee")))
-matches this->x(), x(), y.x(), f()
-with expr() inside of callee
-matching this->x, x,
-y.x, f respectively
+callExpr(callee(expr()))
+ matches this->x(), x(), y.x(), f()
+with callee(...)
+ matching this->x, x, y.x, f respectively
Given
- struct Dummy {};
- // makes sure there is a callee, otherwise there would be no callee,
- // just a builtin operator
- Dummy operator+(Dummy, Dummy);
- // not defining a '*' operator
-
template <typename... Args>
auto sum(Args... args) {
return (0 + ... + args);
@@ -10399,14 +7728,10 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
auto multiply(Args... args) {
return (args * ... * 1);
}
-
-The matcher cxxFoldExpr(callee(expr().bind("op")))
-matches (0 + ... + args)
-with callee(...) matching *,
-but does not match (args * ... * 1).
-A CXXFoldExpr only has an UnresolvedLookupExpr as a callee.
-When there are no define operators that could be used instead of builtin
-ones, then there will be no callee .
+cxxFoldExpr(callee(expr()))
+ matches (args * ... * 1)
+with callee(...)
+ matching *
Note: Callee cannot take the more general internal::Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>>
because this introduces ambiguous overloads with calls to Callee taking a
@@ -10421,10 +7746,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
void f(int i);
int y;
- void foo() {
- f(y);
- }
-The matcher callExpr(
+ f(y);
+callExpr(
forEachArgumentWithParam(
declRefExpr(to(varDecl(hasName("y")))),
parmVarDecl(hasType(isInteger()))
@@ -10447,15 +7770,14 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
void f(int i);
- void foo(int y) {
- f(y);
- void (*f_ptr)(int) = f;
- f_ptr(y);
- }
-The matcher callExpr(
+ int y;
+ f(y);
+ void (*f_ptr)(int) = f;
+ f_ptr(y);
+callExpr(
forEachArgumentWithParamType(
declRefExpr(to(varDecl(hasName("y")))),
- qualType(isInteger()).bind("type")
+ qualType(isInteger()).bind("type)
))
matches f(y) and f_ptr(y)
with declRefExpr(...)
@@ -10470,19 +7792,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
expression, or an ObjC-message-send expression.
Given
- void x(int, int, int) { int y = 42; x(1, y, 42); }
-The matcher
-callExpr(hasAnyArgument(ignoringImplicit(declRefExpr()))) matches
-x(1, y, 42) with hasAnyArgument(...)
+ void x(int, int, int) { int y; x(1, y, 42); }
+callExpr(hasAnyArgument(declRefExpr()))
+ matches x(1, y, 42)
+with hasAnyArgument(...)
matching y
For ObjectiveC, given
@interface I - (void) f:(int) y; @end
void foo(I *i) { [i f:12]; }
-
-The matcher
objcMessageExpr(hasAnyArgument(integerLiteral(equals(12))))
-matches [i f:12]
+ matches [i f:12]
</pre></td></tr>
@@ -10490,17 +7810,15 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasArgument0"><pre>Matches the n'th argument of a call expression or a constructor
call expression.
-Given
+Example matches y in x(y)
+ (matcher = callExpr(hasArgument(0, declRefExpr())))
void x(int) { int y; x(y); }
-The matcher callExpr(hasArgument(0, declRefExpr().bind("arg")))
-matches x(y),
-with declRefExpr() matching y.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>></td><td class="name" onclick="toggle('hasDeclaration14')"><a name="hasDeclaration14Anchor">hasDeclaration</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration14"><pre>Matches a node if the declaration associated with that node
- matches the given matcher.
+matches the given matcher.
The associated declaration is:
- for type nodes, the declaration of the underlying type
@@ -10510,25 +7828,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
- for CXXNewExpr, the declaration of the operator new
- for ObjCIvarExpr, the declaration of the ivar
-Given
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
class X {};
typedef X Y;
Y y;
-
-For type nodes, hasDeclaration will generally match the declaration of the
-sugared type, i.e., the matcher
-varDecl(hasType(qualType(hasDeclaration(decl().bind("d"))))),
-matches Y y, with
-the matcher decl() matching
-typedef X Y;.
-A common use case is to match the underlying, desugared type.
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
This can be achieved by using the hasUnqualifiedDesugaredType matcher:
-varDecl(hasType(hasUnqualifiedDesugaredType(
- recordType(hasDeclaration(decl().bind("d"))))))
-matches Y y.
-In this matcher, the matcher decl() will match the
-CXXRecordDecl
-class X {};.
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>>,
@@ -10545,12 +7855,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
extension, matches the constant given in the statement.
Given
- void foo() {
- switch (1) { case 1: break; case 1+1: break; case 3 ... 4: break; }
- }
-The matcher
-caseStmt(hasCaseConstant(constantExpr(has(integerLiteral()))))
-matches case 1: break.
+ switch (1) { case 1: case 1+1: case 3 ... 4: ; }
+caseStmt(hasCaseConstant(integerLiteral()))
+ matches "case 1:"
</pre></td></tr>
@@ -10558,23 +7865,14 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasSourceExpression0"><pre>Matches if the cast's source expression
or opaque value's source expression matches the given matcher.
-Given
- struct URL { URL(const char*); };
- URL url = "a string";
-
-The matcher castExpr(hasSourceExpression(cxxConstructExpr()))
-matches "a string".
-
-Given
-void foo(bool b) {
- int a = b ?: 1;
-}
+Example 1: matches "a string"
+(matcher = castExpr(hasSourceExpression(cxxConstructExpr())))
+class URL { URL(string); };
+URL url = "a string";
-The matcher
-opaqueValueExpr(hasSourceExpression(
- implicitCastExpr(has(
- implicitCastExpr(has(declRefExpr()))))))
-matches b twice, for the conditiona and the true expression.
+Example 2: matches 'b' (matcher =
+opaqueValueExpr(hasSourceExpression(implicitCastExpr(declRefExpr())))
+int a = b ?: 1;
</pre></td></tr>
@@ -10594,22 +7892,13 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
template <typename T, typename U>
void f(T&& t, U&& u) {}
- void foo() {
- bool B = false;
- f(R, B);
- }
-
-The matcher
-templateSpecializationType(forEachTemplateArgument(isExpr(expr().bind("t_arg"))))
-matches Matrix<int, R * 2, R * 4> twice, with
-expr() matching R * 2 and
-R * 4.
-The matcher
-functionDecl(forEachTemplateArgument(refersToType(qualType().bind("type"))))
-matches the specialization of f twice,
-with qualType() matching
-unsigned and
-bool.
+ bool B = false;
+ f(R, B);
+templateSpecializationType(forEachTemplateArgument(isExpr(expr())))
+ matches twice, with expr() matching 'R * 2' and 'R * 4'
+functionDecl(forEachTemplateArgument(refersToType(builtinType())))
+ matches the specialization f<unsigned, bool> twice, for 'unsigned'
+ and 'bool'
</pre></td></tr>
@@ -10622,11 +7911,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
template<typename T> class A {};
A<int> a;
-
-The matcher
-varDecl(hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
-templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
-hasTypeLoc(loc(asString("int"))))))))) matches A<int> a.
+varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
+ hasTypeLoc(loc(asString("int")))))))
+ matches `A<int> a`.
</pre></td></tr>
@@ -10640,19 +7927,15 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
template<> class A<double> {};
A<int> a;
- template<typename T> void f() {};
+ template<typename T> f() {};
void func() { f<int>(); };
+classTemplateSpecializationDecl(hasAnyTemplateArgument(
+ refersToType(asString("int"))))
+ matches the specialization A<int>
-The matcher classTemplateSpecializationDecl(
- hasAnyTemplateArgument(
- refersToType(asString("int"))))
-matches class A<int>.
-
-The matcher
-functionDecl(hasAnyTemplateArgument(
- refersToType(asString("int"))))
-matches the instantiation of f.
+functionDecl(hasAnyTemplateArgument(refersToType(asString("int"))))
+ matches the specialization f<int>
</pre></td></tr>
@@ -10660,14 +7943,11 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasSpecializedTemplate0"><pre>Matches the specialized template of a specialization declaration.
Given
- template<typename T> class A {}; // #1
- template<> class A<int> {}; // #2
-
-The matcher
-classTemplateSpecializationDecl(hasSpecializedTemplate(classTemplateDecl().bind("ctd")))
-matches template<> class A<int> {},
-with classTemplateDecl() matching the class template
-declaration template <typename T> class A {}.
+ template<typename T> class A {}; #1
+ template<> class A<int> {}; #2
+classTemplateSpecializationDecl(hasSpecializedTemplate(classTemplateDecl()))
+ matches '#2' with classTemplateDecl() matching the class template
+ declaration of 'A' at #1.
</pre></td></tr>
@@ -10680,12 +7960,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
template<typename T, typename U> class A {};
A<double, int> b;
A<int, double> c;
-
-The matcher
-varDecl(hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
-templateSpecializationTypeLoc(hasTemplateArgumentLoc(0,
-hasTypeLoc(loc(asString("double")))))))))
-matches A<double, int> b, but not double> c}.
+varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(0,
+ hasTypeLoc(loc(asString("double")))))))
+ matches `A<double, int> b`, but not `A<int, double> c`.
</pre></td></tr>
@@ -10696,20 +7973,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
template<typename T, typename U> class A {};
- A<double, int> b;
- A<int, double> c;
+ A<bool, int> b;
+ A<int, bool> c;
template<typename T> void f() {}
void func() { f<int>(); };
-
-The matcher
classTemplateSpecializationDecl(hasTemplateArgument(
1, refersToType(asString("int"))))
-matches the specialization class A<double, int>.
+ matches the specialization A<bool, int>
-The matcher functionDecl(hasTemplateArgument(0,
- refersToType(asString("int"))))
-matches the specialization of f.
+functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))
+ matches the specialization f<int>
</pre></td></tr>
@@ -10721,10 +7995,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
struct A {};
A a[7];
int b[7];
-
-
-The matcher arrayType(hasElementType(builtinType()))
-int[7]
+arrayType(hasElementType(builtinType()))
+ matches "int b[7]"
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ArrayType.html">ArrayType</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ComplexType.html">ComplexType</a>>
</pre></td></tr>
@@ -10733,26 +8005,19 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>></td><td class="name" onclick="toggle('hasTypeLoc7')"><a name="hasTypeLoc7Anchor">hasTypeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr>
<tr><td colspan="4" class="doc" id="hasTypeLoc7"><pre>Matches if the type location of a node matches the inner matcher.
-Given
+Examples:
int x;
-The matcher declaratorDecl(hasTypeLoc(loc(asString("int"))))
-matches int x.
-
-Given
-struct point { point(double, double); };
-point p = point(1.0, -1.0);
+declaratorDecl(hasTypeLoc(loc(asString("int"))))
+ matches int x
-The matcher
-cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("point"))))
-matches point(1.0, -1.0).
+auto x = int(3);
+cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("int"))))
+ matches int(3)
-Given
struct Foo { Foo(int, int); };
-Foo x = Foo(1, 2);
-
-The matcher cxxTemporaryObjectExpr(hasTypeLoc(
- loc(asString("Foo"))))
-matches Foo(1, 2).
+auto x = Foo(1, 2);
+cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo"))))
+ matches Foo(1, 2)
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html">BlockDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>,
@@ -10770,12 +8035,11 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
a given matcher. Also matches StmtExprs that have CompoundStmt as children.
Given
-void foo() { { {}; 1+2; } }
-The matcher
-compoundStmt(hasAnySubstatement(compoundStmt().bind("compound")))
-{ {}; 1+2; } and { { {}; 1+2; } }
+ { {}; 1+2; }
+hasAnySubstatement(compoundStmt())
+ matches '{ {}; 1+2; }'
with compoundStmt()
-matching {} and { {}; 1+2; }.
+ matching '{}'
</pre></td></tr>
@@ -10786,35 +8050,25 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
other declarations of the same function or coroutine.
Given
-void foo() {
for (;;) {}
-}
-The matcher forStmt(hasBody(compoundStmt().bind("body")))
-matches for (;;) {}
+forStmt(hasBody(compoundStmt()))
+ matches 'for (;;) {}'
with compoundStmt()
- matching {}
+ matching '{}'
Given
void f();
void f() {}
-The matcher functionDecl(hasBody(compoundStmt().bind("compound")))
-f
+functionDecl(hasBody(compoundStmt()))
+ matches 'void f() {}'
with compoundStmt()
-matching {}
-but does not match void f();
+ matching '{}'
+ but does not match 'void f();'
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DecayedType.html">DecayedType</a>></td><td class="name" onclick="toggle('hasDecayedType0')"><a name="hasDecayedType0Anchor">hasDecayedType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>> InnerType</td></tr>
<tr><td colspan="4" class="doc" id="hasDecayedType0"><pre>Matches the decayed type, whoes decayed type matches InnerMatcher
-
-Given
- void f(int i[]) {
- i[1] = 0;
- }
-
-The matcher parmVarDecl(hasType(decayedType()))
-matches int i[].
</pre></td></tr>
@@ -10827,17 +8081,15 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
template<typename T> class A {};
A<int> a;
-
-The matcher
-varDecl(hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
-templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
-hasTypeLoc(loc(asString("int"))))))))) matches A<int> a.
+varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
+ hasTypeLoc(loc(asString("int")))))))
+ matches `A<int> a`.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>></td><td class="name" onclick="toggle('hasDeclaration11')"><a name="hasDeclaration11Anchor">hasDeclaration</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration11"><pre>Matches a node if the declaration associated with that node
- matches the given matcher.
+matches the given matcher.
The associated declaration is:
- for type nodes, the declaration of the underlying type
@@ -10847,25 +8099,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
- for CXXNewExpr, the declaration of the operator new
- for ObjCIvarExpr, the declaration of the ivar
-Given
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
class X {};
typedef X Y;
Y y;
-
-For type nodes, hasDeclaration will generally match the declaration of the
-sugared type, i.e., the matcher
-varDecl(hasType(qualType(hasDeclaration(decl().bind("d"))))),
-matches Y y, with
-the matcher decl() matching
-typedef X Y;.
-A common use case is to match the underlying, desugared type.
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
This can be achieved by using the hasUnqualifiedDesugaredType matcher:
-varDecl(hasType(hasUnqualifiedDesugaredType(
- recordType(hasDeclaration(decl().bind("d"))))))
-matches Y y.
-In this matcher, the matcher decl() will match the
-CXXRecordDecl
-class X {};.
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>>,
@@ -10886,12 +8130,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
template<typename T, typename U> class A {};
A<double, int> b;
A<int, double> c;
-
-The matcher
-varDecl(hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
-templateSpecializationTypeLoc(hasTemplateArgumentLoc(0,
-hasTypeLoc(loc(asString("double")))))))))
-matches A<double, int> b, but not double> c}.
+varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(0,
+ hasTypeLoc(loc(asString("double")))))))
+ matches `A<double, int> b`, but not `A<int, double> c`.
</pre></td></tr>
@@ -10899,20 +8140,18 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="throughUsingDecl0"><pre>Matches if a node refers to a declaration through a specific
using shadow declaration.
-Given
+Examples:
namespace a { int f(); }
using a::f;
int x = f();
-
-The matcher declRefExpr(throughUsingDecl(anything()))
-matches f
+declRefExpr(throughUsingDecl(anything()))
+ matches f
namespace a { class X{}; }
using a::X;
X x;
-
-The matcher typeLoc(loc(usingType(throughUsingDecl(anything()))))
-matches X
+typeLoc(loc(usingType(throughUsingDecl(anything()))))
+ matches X
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1UsingType.html">UsingType</a>>
</pre></td></tr>
@@ -10922,14 +8161,10 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="to0"><pre>Matches a DeclRefExpr that refers to a declaration that matches the
specified matcher.
-Given
- void foo() {
- bool x;
- if (x) {}
- }
-
-The matcher declRefExpr(to(varDecl(hasName("x"))))
-matches x inside the condition of the if-stmt.
+Example matches x in if(x)
+ (matcher = declRefExpr(to(varDecl(hasName("x")))))
+ bool x;
+ if (x) {}
</pre></td></tr>
@@ -10939,19 +8174,16 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Note that this does not work for global declarations because the AST
breaks up multiple-declaration DeclStmt's into multiple single-declaration
DeclStmt's.
-
-Given non-global declarations
- void foo() {
- int a, b = 0;
- int c;
- int d = 2, e;
- }
-The matcher declStmt(containsDeclaration(
+Example: Given non-global declarations
+ int a, b = 0;
+ int c;
+ int d = 2, e;
+declStmt(containsDeclaration(
0, varDecl(hasInitializer(anything()))))
-matches int d = 2, e;.
-The matcher declStmt(containsDeclaration(1, varDecl()))
-matches int a, b = 0; and int d = 2, e;
-but does not match int c;.
+ matches only 'int d = 2, e;', and
+declStmt(containsDeclaration(1, varDecl()))
+ matches 'int a, b = 0' as well as 'int d = 2, e;'
+ but 'int c;' is not matched.
</pre></td></tr>
@@ -10959,39 +8191,29 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasSingleDecl0"><pre>Matches the Decl of a DeclStmt which has a single declaration.
Given
- void foo() {
- int a, b;
- int c;
- }
-The matcher declStmt(hasSingleDecl(anything()))
-matches int c;
-but does not match int a, b;
+ int a, b;
+ int c;
+declStmt(hasSingleDecl(anything()))
+ matches 'int c;' but not 'int a, b;'.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclaratorDecl.html">DeclaratorDecl</a>></td><td class="name" onclick="toggle('hasTypeLoc8')"><a name="hasTypeLoc8Anchor">hasTypeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr>
<tr><td colspan="4" class="doc" id="hasTypeLoc8"><pre>Matches if the type location of a node matches the inner matcher.
-Given
+Examples:
int x;
-The matcher declaratorDecl(hasTypeLoc(loc(asString("int"))))
-matches int x.
-
-Given
-struct point { point(double, double); };
-point p = point(1.0, -1.0);
+declaratorDecl(hasTypeLoc(loc(asString("int"))))
+ matches int x
-The matcher
-cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("point"))))
-matches point(1.0, -1.0).
+auto x = int(3);
+cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("int"))))
+ matches int(3)
-Given
struct Foo { Foo(int, int); };
-Foo x = Foo(1, 2);
-
-The matcher cxxTemporaryObjectExpr(hasTypeLoc(
- loc(asString("Foo"))))
-matches Foo(1, 2).
+auto x = Foo(1, 2);
+cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo"))))
+ matches Foo(1, 2)
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html">BlockDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>,
@@ -11015,9 +8237,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
}
}
-
-The matcher cxxRecordDecl(hasDeclContext(namedDecl(hasName("M"))))
- matches the declaration of D.
+cxxRcordDecl(hasDeclContext(namedDecl(hasName("M")))) matches the
+declaration of class D.
</pre></td></tr>
@@ -11027,11 +8248,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
decltype(1) a = 1;
decltype(2.0) b = 2.0;
-
-
-The matcher decltypeType(hasUnderlyingType(isInteger()))
-matches the type decltype(1) of the variable
-declaration of a .
+decltypeType(hasUnderlyingType(isInteger()))
+ matches the type of "a"
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DecltypeType.html">DecltypeType</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1UsingType.html">UsingType</a>>
</pre></td></tr>
@@ -11048,17 +8266,16 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
f = 42;
}
-
-The matcher
- decompositionDecl(hasAnyBinding(bindingDecl(hasName("f")).bind("fBinding")))
-matches auto &[f, s, t] = arr with 'f' bound to "fBinding".
+The matcher:
+ decompositionDecl(hasAnyBinding(bindingDecl(hasName("f").bind("fBinding"))))
+matches the decomposition decl with 'f' bound to "fBinding".
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DecompositionDecl.html">DecompositionDecl</a>></td><td class="name" onclick="toggle('hasBinding0')"><a name="hasBinding0Anchor">hasBinding</a></td><td>unsigned N, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BindingDecl.html">BindingDecl</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasBinding0"><pre>Matches the Nth binding of a DecompositionDecl.
-Given
+For example, in:
void foo()
{
int arr[3];
@@ -11066,10 +8283,10 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
f = 42;
}
-
-The matcher decompositionDecl(hasBinding(0,
- bindingDecl(hasName("f")).bind("fBinding")))
-matches auto &[f, s, t] = arr with 'f' bound to "fBinding".
+The matcher:
+ decompositionDecl(hasBinding(0,
+ bindingDecl(hasName("f").bind("fBinding"))))
+matches the decomposition decl with 'f' bound to "fBinding".
</pre></td></tr>
@@ -11080,22 +8297,20 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
other declarations of the same function or coroutine.
Given
-void foo() {
for (;;) {}
-}
-The matcher forStmt(hasBody(compoundStmt().bind("body")))
-matches for (;;) {}
+forStmt(hasBody(compoundStmt()))
+ matches 'for (;;) {}'
with compoundStmt()
- matching {}
+ matching '{}'
Given
void f();
void f() {}
-The matcher functionDecl(hasBody(compoundStmt().bind("compound")))
-f
+functionDecl(hasBody(compoundStmt()))
+ matches 'void f() {}'
with compoundStmt()
-matching {}
-but does not match void f();
+ matching '{}'
+ but does not match 'void f();'
</pre></td></tr>
@@ -11103,13 +8318,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasCondition3"><pre>Matches the condition expression of an if statement, for loop,
switch statement or conditional operator.
-Given
-void foo() {
+Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
if (true) {}
-}
-
-The matcher ifStmt(hasCondition(cxxBoolLiteral(equals(true))))
-if (true) {}
</pre></td></tr>
@@ -11124,16 +8334,14 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
class D {};
class D d;
-
-The matcher
-elaboratedTypeLoc(hasNamedTypeLoc(templateSpecializationTypeLoc()))
- matches class C<int>, but not D}
+elaboratedTypeLoc(hasNamedTypeLoc(templateSpecializationTypeLoc()));
+ matches the `TypeLoc` of the variable declaration of `c`, but not `d`.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ElaboratedType.html">ElaboratedType</a>></td><td class="name" onclick="toggle('hasQualifier0')"><a name="hasQualifier0Anchor">hasQualifier</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifier.html">NestedNameSpecifier</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasQualifier0"><pre>Matches ElaboratedTypes whose qualifier, a NestedNameSpecifier,
- matches InnerMatcher if the qualifier exists.
+matches InnerMatcher if the qualifier exists.
Given
namespace N {
@@ -11143,11 +8351,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
}
N::M::D d;
-
-The matcher
-elaboratedType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N")))))
- matches the type N::M::D of the variable declaration
- of d.
+elaboratedType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N"))))
+matches the type of the variable declaration of d.
</pre></td></tr>
@@ -11157,20 +8362,20 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
namespace N {
namespace M {
- enum E { Ok };
+ class D {};
}
}
- N::M::E e = N::M::Ok;
-
+ N::M::D d;
-The matcher elaboratedType(namesType(enumType()))
-matches the type N::M::E of the declaration of e .
+elaboratedType(namesType(recordType(
+hasDeclaration(namedDecl(hasName("D")))))) matches the type of the variable
+declaration of d.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>></td><td class="name" onclick="toggle('hasDeclaration10')"><a name="hasDeclaration10Anchor">hasDeclaration</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration10"><pre>Matches a node if the declaration associated with that node
- matches the given matcher.
+matches the given matcher.
The associated declaration is:
- for type nodes, the declaration of the underlying type
@@ -11180,25 +8385,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
- for CXXNewExpr, the declaration of the operator new
- for ObjCIvarExpr, the declaration of the ivar
-Given
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
class X {};
typedef X Y;
Y y;
-
-For type nodes, hasDeclaration will generally match the declaration of the
-sugared type, i.e., the matcher
-varDecl(hasType(qualType(hasDeclaration(decl().bind("d"))))),
-matches Y y, with
-the matcher decl() matching
-typedef X Y;.
-A common use case is to match the underlying, desugared type.
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
This can be achieved by using the hasUnqualifiedDesugaredType matcher:
-varDecl(hasType(hasUnqualifiedDesugaredType(
- recordType(hasDeclaration(decl().bind("d"))))))
-matches Y y.
-In this matcher, the matcher decl() will match the
-CXXRecordDecl
-class X {};.
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>>,
@@ -11215,37 +8412,25 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
(Note: Clang's AST refers to other conversions as "casts" too, and calls
actual casts "explicit" casts.)
-
- unsigned int a = (unsigned int)0;
-
-The matcher explicitCastExpr(hasDestinationType(
-qualType(isUnsignedInteger()))) matches (unsigned int)0.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ExplicitCastExpr.html">ExplicitCastExpr</a>></td><td class="name" onclick="toggle('hasTypeLoc9')"><a name="hasTypeLoc9Anchor">hasTypeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr>
<tr><td colspan="4" class="doc" id="hasTypeLoc9"><pre>Matches if the type location of a node matches the inner matcher.
-Given
+Examples:
int x;
-The matcher declaratorDecl(hasTypeLoc(loc(asString("int"))))
-matches int x.
-
-Given
-struct point { point(double, double); };
-point p = point(1.0, -1.0);
+declaratorDecl(hasTypeLoc(loc(asString("int"))))
+ matches int x
-The matcher
-cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("point"))))
-matches point(1.0, -1.0).
+auto x = int(3);
+cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("int"))))
+ matches int(3)
-Given
struct Foo { Foo(int, int); };
-Foo x = Foo(1, 2);
-
-The matcher cxxTemporaryObjectExpr(hasTypeLoc(
- loc(asString("Foo"))))
-matches Foo(1, 2).
+auto x = Foo(1, 2);
+cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo"))))
+ matches Foo(1, 2)
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html">BlockDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>,
@@ -11268,31 +8453,21 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
X, while varDecl(hasType(cxxRecordDecl(hasName("X")))) matches the
declaration of x.
+Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
+ and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
+ and friend class X (matcher = friendDecl(hasType("X"))
+ and public virtual X (matcher = cxxBaseSpecifier(hasType(
+ cxxRecordDecl(hasName("X"))))
class X {};
void y(X &x) { x; X z; }
class Y { friend class X; };
class Z : public virtual X {};
-The matcher expr(hasType(cxxRecordDecl(hasName("X"))))
-matches x and z.
-The matcher varDecl(hasType(cxxRecordDecl(hasName("X"))))
-matches z.
-The matcher friendDecl(hasType(asString("class X")))
-matches friend class X.
-The matcher cxxRecordDecl(hasAnyBase(cxxBaseSpecifier(hasType(
-asString("X"))).bind("b"))) matches
-class Z : public virtual X {},
-with cxxBaseSpecifier(...)
-matching public virtual X.
-
-Given
+Example matches class Derived
+(matcher = cxxRecordDecl(hasAnyBase(hasType(cxxRecordDecl(hasName("Base"))))))
class Base {};
class Derived : Base {};
-The matcher
-cxxRecordDecl(hasAnyBase(hasType(cxxRecordDecl(hasName("Base")))))
-matches class Derived : Base {}.
-
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FriendDecl.html">FriendDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>>
</pre></td></tr>
@@ -11302,25 +8477,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasType0"><pre>Matches if the expression's or declaration's type matches a type
matcher.
-Exmaple
+Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
+ and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
+ and U (matcher = typedefDecl(hasType(asString("int")))
+ and friend class X (matcher = friendDecl(hasType("X"))
+ and public virtual X (matcher = cxxBaseSpecifier(hasType(
+ asString("class X")))
class X {};
void y(X &x) { x; X z; }
typedef int U;
class Y { friend class X; };
class Z : public virtual X {};
-
-The matcher expr(hasType(cxxRecordDecl(hasName("X"))))
-matches x and z.
-The matcher varDecl(hasType(cxxRecordDecl(hasName("X"))))
-matches z
-The matcher typedefDecl(hasType(asString("int")))
-matches typedef int U
-The matcher friendDecl(hasType(asString("class X")))
-matches friend class X
-The matcher cxxRecordDecl(hasAnyBase(cxxBaseSpecifier(hasType(
-asString("X"))).bind("b"))) matches class Z : public virtual X {},
-with cxxBaseSpecifier(...)
-matching public virtual X.
</pre></td></tr>
@@ -11337,16 +8504,15 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
appear in the C++17 AST.
Given
+
struct H {};
H G();
void f() {
H D = G();
}
-
-The matcher
-varDecl(hasInitializer(ignoringElidableConstructorCall(callExpr())))
-matches H D = G().
+``varDecl(hasInitializer(ignoringElidableConstructorCall(callExpr())))``
+matches ``H D = G()`` in C++11 through C++17 (and beyond).
</pre></td></tr>
@@ -11357,25 +8523,19 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Parentheses and explicit casts are not discarded.
Given
int arr[5];
- const int a = 0;
+ int a = 0;
char b = 0;
const int c = a;
int *d = arr;
long e = (long) 0l;
-The matcher
-varDecl(hasInitializer(ignoringImpCasts(integerLiteral())))
-matches a and b,
-but does not match e.
-The matcher
-varDecl(hasInitializer(ignoringImpCasts(declRefExpr())))
-matches c and d.
-
-The matcher
-varDecl(hasInitializer(integerLiteral()))
-matches a,
-but does not match b or e.
-The matcher varDecl(hasInitializer(declRefExpr()))
-does not match c or d.
+The matchers
+ varDecl(hasInitializer(ignoringImpCasts(integerLiteral())))
+ varDecl(hasInitializer(ignoringImpCasts(declRefExpr())))
+would match the declarations for a, b, c, and d, but not e.
+While
+ varDecl(hasInitializer(integerLiteral()))
+ varDecl(hasInitializer(declRefExpr()))
+only match the declarations for a.
</pre></td></tr>
@@ -11384,34 +8544,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
nodes are stripped off.
Parentheses and explicit casts are not discarded.
-
Given
- void f(int param) {
- int a = 0;
- int b = param;
- const int c = 0;
- const int d = param;
- int e = (0U);
- int f = (int)0.0;
- const int g = ((int)(((0))));
- }
-
-The matcher
-varDecl(hasInitializer(ignoringImplicit(integerLiteral())))
-matches int a = 0 and const int c = 0,
-but not int e = (0U) and ((int)(((0))).
-The matcher
-varDecl(hasInitializer(integerLiteral()))
-matches int a = 0 and const int c = 0,
-but not int e = (0U) and ((int)(((0))).
-
-The matcher
-varDecl(hasInitializer(ignoringImplicit(declRefExpr())))
-matches int b = param and const int d = param.
-The matcher
-varDecl(hasInitializer(declRefExpr()))
-matches neither int b = param nor const int d = param,
-because an l-to-r-value cast happens.
+ class C {};
+ C a = C();
+ C b;
+ C c = b;
+The matchers
+ varDecl(hasInitializer(ignoringImplicit(cxxConstructExpr())))
+would match the declarations for a, b, and c.
+While
+ varDecl(hasInitializer(cxxConstructExpr()))
+only match the declarations for b and c.
</pre></td></tr>
@@ -11425,14 +8568,12 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
char b = (0);
void* c = reinterpret_cast<char*>(0);
char d = char(0);
-
The matcher
-varDecl(hasInitializer(ignoringParenCasts(integerLiteral())))
-matches a, b, c
-and d.
-The matcher
-varDecl(hasInitializer(integerLiteral()))
-matches a.
+ varDecl(hasInitializer(ignoringParenCasts(integerLiteral())))
+would match the declarations for a, b, c, and d.
+while
+ varDecl(hasInitializer(integerLiteral()))
+only match the declaration for a.
</pre></td></tr>
@@ -11448,21 +8589,14 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
const int c = a;
int *d = (arr);
long e = ((long) 0l);
-
-The matcher
-varDecl(hasInitializer(ignoringParenImpCasts(integerLiteral())))
-matches a and b,
-but does not match e.
-The matcher
-varDecl(hasInitializer(ignoringParenImpCasts(declRefExpr())))
-matches c and d.
-
-The matcher
-varDecl(hasInitializer(integerLiteral()))
-matches a,
-but does not match b or e.
-The matcher varDecl(hasInitializer(declRefExpr()))
-does not match c, or d.
+The matchers
+ varDecl(hasInitializer(ignoringParenImpCasts(integerLiteral())))
+ varDecl(hasInitializer(ignoringParenImpCasts(declRefExpr())))
+would match the declarations for a, b, c, and d, but not e.
+while
+ varDecl(hasInitializer(integerLiteral()))
+ varDecl(hasInitializer(declRefExpr()))
+would only match the declaration for a.
</pre></td></tr>
@@ -11472,9 +8606,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
const char* str = ("my-string");
The matcher
-implicitCastExpr(hasSourceExpression(ignoringParens(stringLiteral())))
-would match the implicit cast resulting from the assignment
-("my-string").
+ implicitCastExpr(hasSourceExpression(ignoringParens(stringLiteral())))
+would match the implicit cast resulting from the assignment.
</pre></td></tr>
@@ -11487,14 +8620,10 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
int b = 3;
int c;
};
-
-The matcher
fieldDecl(hasInClassInitializer(integerLiteral(equals(2))))
-matches a,
-but does not match b.
-The matcher fieldDecl(hasInClassInitializer(anything()))
-matches a and b,
-but does not match c.
+ matches 'int a;' but not 'int b;'.
+fieldDecl(hasInClassInitializer(anything()))
+ matches 'int a;' and 'int b;' but not 'int c;'.
</pre></td></tr>
@@ -11505,22 +8634,20 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
other declarations of the same function or coroutine.
Given
-void foo() {
for (;;) {}
-}
-The matcher forStmt(hasBody(compoundStmt().bind("body")))
-matches for (;;) {}
+forStmt(hasBody(compoundStmt()))
+ matches 'for (;;) {}'
with compoundStmt()
- matching {}
+ matching '{}'
Given
void f();
void f() {}
-The matcher functionDecl(hasBody(compoundStmt().bind("compound")))
-f
+functionDecl(hasBody(compoundStmt()))
+ matches 'void f() {}'
with compoundStmt()
-matching {}
-but does not match void f();
+ matching '{}'
+ but does not match 'void f();'
</pre></td></tr>
@@ -11528,38 +8655,28 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasCondition1"><pre>Matches the condition expression of an if statement, for loop,
switch statement or conditional operator.
-Given
-void foo() {
+Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
if (true) {}
-}
-
-The matcher ifStmt(hasCondition(cxxBoolLiteral(equals(true))))
-if (true) {}
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ForStmt.html">ForStmt</a>></td><td class="name" onclick="toggle('hasIncrement0')"><a name="hasIncrement0Anchor">hasIncrement</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasIncrement0"><pre>Matches the increment statement of a for loop.
-Given
-void foo(int N) {
- for (int x = 0; x < N; ++x) { }
-}
-The matcher
-forStmt(hasIncrement(unaryOperator(hasOperatorName("++"))))
-matches for (int x = 0; x < N; ++x) { }
+Example:
+ forStmt(hasIncrement(unaryOperator(hasOperatorName("++"))))
+matches '++x' in
+ for (x; x < N; ++x) { }
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ForStmt.html">ForStmt</a>></td><td class="name" onclick="toggle('hasLoopInit0')"><a name="hasLoopInit0Anchor">hasLoopInit</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasLoopInit0"><pre>Matches the initialization statement of a for loop.
-Given
-void foo(int N) {
+Example:
+ forStmt(hasLoopInit(declStmt()))
+matches 'int x = 0' in
for (int x = 0; x < N; ++x) { }
-}
-The matcher forStmt(hasLoopInit(declStmt()))
-matches for (int x = 0; x < N; ++x) { }
</pre></td></tr>
@@ -11573,31 +8690,21 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
X, while varDecl(hasType(cxxRecordDecl(hasName("X")))) matches the
declaration of x.
+Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
+ and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
+ and friend class X (matcher = friendDecl(hasType("X"))
+ and public virtual X (matcher = cxxBaseSpecifier(hasType(
+ cxxRecordDecl(hasName("X"))))
class X {};
void y(X &x) { x; X z; }
class Y { friend class X; };
class Z : public virtual X {};
-The matcher expr(hasType(cxxRecordDecl(hasName("X"))))
-matches x and z.
-The matcher varDecl(hasType(cxxRecordDecl(hasName("X"))))
-matches z.
-The matcher friendDecl(hasType(asString("class X")))
-matches friend class X.
-The matcher cxxRecordDecl(hasAnyBase(cxxBaseSpecifier(hasType(
-asString("X"))).bind("b"))) matches
-class Z : public virtual X {},
-with cxxBaseSpecifier(...)
-matching public virtual X.
-
-Given
+Example matches class Derived
+(matcher = cxxRecordDecl(hasAnyBase(hasType(cxxRecordDecl(hasName("Base"))))))
class Base {};
class Derived : Base {};
-The matcher
-cxxRecordDecl(hasAnyBase(hasType(cxxRecordDecl(hasName("Base")))))
-matches class Derived : Base {}.
-
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FriendDecl.html">FriendDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>>
</pre></td></tr>
@@ -11607,25 +8714,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasType1"><pre>Matches if the expression's or declaration's type matches a type
matcher.
-Exmaple
+Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
+ and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
+ and U (matcher = typedefDecl(hasType(asString("int")))
+ and friend class X (matcher = friendDecl(hasType("X"))
+ and public virtual X (matcher = cxxBaseSpecifier(hasType(
+ asString("class X")))
class X {};
void y(X &x) { x; X z; }
typedef int U;
class Y { friend class X; };
class Z : public virtual X {};
-
-The matcher expr(hasType(cxxRecordDecl(hasName("X"))))
-matches x and z.
-The matcher varDecl(hasType(cxxRecordDecl(hasName("X"))))
-matches z
-The matcher typedefDecl(hasType(asString("int")))
-matches typedef int U
-The matcher friendDecl(hasType(asString("class X")))
-matches friend class X
-The matcher cxxRecordDecl(hasAnyBase(cxxBaseSpecifier(hasType(
-asString("X"))).bind("b"))) matches class Z : public virtual X {},
-with cxxBaseSpecifier(...)
-matching public virtual X.
</pre></td></tr>
@@ -11645,22 +8744,13 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
template <typename T, typename U>
void f(T&& t, U&& u) {}
- void foo() {
- bool B = false;
- f(R, B);
- }
-
-The matcher
-templateSpecializationType(forEachTemplateArgument(isExpr(expr().bind("t_arg"))))
-matches Matrix<int, R * 2, R * 4> twice, with
-expr() matching R * 2 and
-R * 4.
-The matcher
-functionDecl(forEachTemplateArgument(refersToType(qualType().bind("type"))))
-matches the specialization of f twice,
-with qualType() matching
-unsigned and
-bool.
+ bool B = false;
+ f(R, B);
+templateSpecializationType(forEachTemplateArgument(isExpr(expr())))
+ matches twice, with expr() matching 'R * 2' and 'R * 4'
+functionDecl(forEachTemplateArgument(refersToType(builtinType())))
+ matches the specialization f<unsigned, bool> twice, for 'unsigned'
+ and 'bool'
</pre></td></tr>
@@ -11673,12 +8763,12 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
void f();
void f() {}
void g();
-The matcher functionDecl(hasAnyBody(compoundStmt()))
- matches f
- and f
+functionDecl(hasAnyBody(compoundStmt()))
+ matches both 'void f();'
+ and 'void f() {}'
with compoundStmt()
- matching {}
- but does not match void g();
+ matching '{}'
+ but does not match 'void g();'
</pre></td></tr>
@@ -11690,26 +8780,23 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
class X { void f(int x, int y, int z) {} };
-
-The matcher cxxMethodDecl(hasAnyParameter(hasName("y")))
- matches f
+cxxMethodDecl(hasAnyParameter(hasName("y")))
+ matches f(int x, int y, int z) {}
with hasAnyParameter(...)
matching int y
For ObjectiveC, given
@interface I - (void) f:(int) y; @end
-
the matcher objcMethodDecl(hasAnyParameter(hasName("y")))
- matches the declaration of method f with hasParameter
+matches the declaration of method f with hasParameter
matching y.
For blocks, given
b = ^(int y) { printf("%d", y) };
-
the matcher blockDecl(hasAnyParameter(hasName("y")))
- matches the declaration of the block b with hasParameter
+matches the declaration of the block b with hasParameter
matching y.
</pre></td></tr>
@@ -11723,11 +8810,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
template<typename T> class A {};
A<int> a;
-
-The matcher
-varDecl(hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
-templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
-hasTypeLoc(loc(asString("int"))))))))) matches A<int> a.
+varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
+ hasTypeLoc(loc(asString("int")))))))
+ matches `A<int> a`.
</pre></td></tr>
@@ -11741,19 +8826,15 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
template<> class A<double> {};
A<int> a;
- template<typename T> void f() {};
+ template<typename T> f() {};
void func() { f<int>(); };
+classTemplateSpecializationDecl(hasAnyTemplateArgument(
+ refersToType(asString("int"))))
+ matches the specialization A<int>
-The matcher classTemplateSpecializationDecl(
- hasAnyTemplateArgument(
- refersToType(asString("int"))))
-matches class A<int>.
-
-The matcher
-functionDecl(hasAnyTemplateArgument(
- refersToType(asString("int"))))
-matches the instantiation of f.
+functionDecl(hasAnyTemplateArgument(refersToType(asString("int"))))
+ matches the specialization f<int>
</pre></td></tr>
@@ -11764,22 +8845,20 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
other declarations of the same function or coroutine.
Given
-void foo() {
for (;;) {}
-}
-The matcher forStmt(hasBody(compoundStmt().bind("body")))
-matches for (;;) {}
+forStmt(hasBody(compoundStmt()))
+ matches 'for (;;) {}'
with compoundStmt()
- matching {}
+ matching '{}'
Given
void f();
void f() {}
-The matcher functionDecl(hasBody(compoundStmt().bind("compound")))
-f
+functionDecl(hasBody(compoundStmt()))
+ matches 'void f() {}'
with compoundStmt()
-matching {}
-but does not match void f();
+ matching '{}'
+ but does not match 'void f();'
</pre></td></tr>
@@ -11794,27 +8873,15 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
explicit S(double); // #2
operator int(); // #3
explicit operator bool(); // #4
- explicit(false) S(bool); // # 7
- explicit(true) S(char); // # 8
- explicit(b) S(float); // # 9
+ explicit(false) S(bool) // # 7
+ explicit(true) S(char) // # 8
+ explicit(b) S(S) // # 9
};
- S(int) -> S<true>; // #5
- explicit S(double) -> S<false>; // #6
-
-The matcher
-cxxConstructorDecl(hasExplicitSpecifier(constantExpr())) matches
-explicit(false) S(bool) and explicit(true) S(char),
-but does not match explicit(b) S(float), S(int) or
-explicit S(double).
-The matcher
-cxxConversionDecl(hasExplicitSpecifier(constantExpr())) does not
-match operator int() or explicit operator bool().
-Matcher
-The matcher
-cxxDeductionGuideDecl(hasExplicitSpecifier(declRefExpr()))
-matches the implicitly generated deduction guide
-auto (float) -> S<b> of the constructor
-S(float)}.
+ S(int) -> S<true> // #5
+ explicit S(double) -> S<false> // #6
+cxxConstructorDecl(hasExplicitSpecifier(constantExpr())) will match #7, #8 and #9, but not #1 or #2.
+cxxConversionDecl(hasExplicitSpecifier(constantExpr())) will not match #3 or #4.
+cxxDeductionGuideDecl(hasExplicitSpecifier(constantExpr())) will not match #5 or #6.
</pre></td></tr>
@@ -11824,18 +8891,15 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
class X { void f(int x) {} };
-
-The matcher
-cxxMethodDecl(hasParameter(0, hasType(asString("int"))))
-matches f
+cxxMethodDecl(hasParameter(0, hasType(varDecl())))
+ matches f(int x) {}
with hasParameter(...)
-matching int x.
+ matching int x
For ObjectiveC, given
@interface I - (void) f:(int) y; @end
-
-The matcher objcMethodDecl(hasParameter(0, hasName("y")))
+the matcher objcMethodDecl(hasParameter(0, hasName("y")))
matches the declaration of method f with hasParameter
matching y.
</pre></td></tr>
@@ -11847,9 +8911,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
int f() { return 5; }
void g() {}
-The matcher functionDecl(hasReturnTypeLoc(loc(asString("int"))))
- matches the declaration of f, but not
- </pre></td></tr>
+functionDecl(hasReturnTypeLoc(loc(asString("int"))))
+ matches the declaration of `f`, but not `g`.
+</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>></td><td class="name" onclick="toggle('hasTemplateArgumentLoc2')"><a name="hasTemplateArgumentLoc2Anchor">hasTemplateArgumentLoc</a></td><td>unsigned Index, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>> InnerMatcher</td></tr>
@@ -11861,12 +8925,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
template<typename T, typename U> class A {};
A<double, int> b;
A<int, double> c;
-
-The matcher
-varDecl(hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
-templateSpecializationTypeLoc(hasTemplateArgumentLoc(0,
-hasTypeLoc(loc(asString("double")))))))))
-matches A<double, int> b, but not double> c}.
+varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(0,
+ hasTypeLoc(loc(asString("double")))))))
+ matches `A<double, int> b`, but not `A<int, double> c`.
</pre></td></tr>
@@ -11877,31 +8938,27 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
template<typename T, typename U> class A {};
- A<double, int> b;
- A<int, double> c;
+ A<bool, int> b;
+ A<int, bool> c;
template<typename T> void f() {}
void func() { f<int>(); };
-
-The matcher
classTemplateSpecializationDecl(hasTemplateArgument(
1, refersToType(asString("int"))))
-matches the specialization class A<double, int>.
+ matches the specialization A<bool, int>
-The matcher functionDecl(hasTemplateArgument(0,
- refersToType(asString("int"))))
-matches the specialization of f.
+functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))
+ matches the specialization f<int>
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>></td><td class="name" onclick="toggle('returns0')"><a name="returns0Anchor">returns</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="returns0"><pre>Matches the return type of a function declaration.
-Given
+Given:
class X { int f() { return 1; } };
-
-The matcher cxxMethodDecl(returns(asString("int")))
- matches f
+cxxMethodDecl(returns(asString("int")))
+ matches int f() { return 1; }
</pre></td></tr>
@@ -11909,13 +8966,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasCondition0"><pre>Matches the condition expression of an if statement, for loop,
switch statement or conditional operator.
-Given
-void foo() {
+Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
if (true) {}
-}
-
-The matcher ifStmt(hasCondition(cxxBoolLiteral(equals(true))))
-if (true) {}
</pre></td></tr>
@@ -11923,37 +8975,25 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasConditionVariableStatement0"><pre>Matches the condition variable statement in an if statement.
Given
-struct A {};
-A* GetAPointer();
-void foo() {
if (A* a = GetAPointer()) {}
-}
-
-The matcher ifStmt(hasConditionVariableStatement(declStmt()))
-if (A* a = GetAPointer()) {}
+hasConditionVariableStatement(...)
+ matches 'A* a = GetAPointer()'.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1IfStmt.html">IfStmt</a>></td><td class="name" onclick="toggle('hasElse0')"><a name="hasElse0Anchor">hasElse</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasElse0"><pre>Matches the else-statement of an if statement.
-Given
-void foo() {
+Examples matches the if statement
+ (matcher = ifStmt(hasElse(cxxBoolLiteral(equals(true)))))
if (false) false; else true;
-}
-
-The matcher ifStmt(hasElse(cxxBoolLiteral(equals(true))))
-if (false) false; else true
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1IfStmt.html">IfStmt</a>></td><td class="name" onclick="toggle('hasInitStatement0')"><a name="hasInitStatement0Anchor">hasInitStatement</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasInitStatement0"><pre>Matches selection statements with initializer.
-Given
- struct vec { int* begin(); int* end(); };
- int foobar();
- vec& get_range();
+Given:
void foo() {
if (int i = foobar(); i > 0) {}
switch (int i = foobar(); i) {}
@@ -11964,77 +9004,48 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
switch (foobar()) {}
for (auto& x : get_range()) {}
}
-
-The matcher ifStmt(hasInitStatement(anything()))
- matches the if statement if (int i = foobar(); i > 0) {}
- in foo but not if (foobar() > 0) {} in bar.
-The matcher switchStmt(hasInitStatement(anything()))
- matches the switch statement switch (int i = foobar(); i) {}
- in foo but not switch (foobar()) {} in bar.
-The matcher cxxForRangeStmt(hasInitStatement(anything()))
- matches the range for statement
- for (auto& a = get_range(); auto& x : a) {} in foo
- but not for (auto& x : get_range()) {} in bar.
+ifStmt(hasInitStatement(anything()))
+ matches the if statement in foo but not in bar.
+switchStmt(hasInitStatement(anything()))
+ matches the switch statement in foo but not in bar.
+cxxForRangeStmt(hasInitStatement(anything()))
+ matches the range for statement in foo but not in bar.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1IfStmt.html">IfStmt</a>></td><td class="name" onclick="toggle('hasThen0')"><a name="hasThen0Anchor">hasThen</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasThen0"><pre>Matches the then-statement of an if statement.
-Given
-void foo() {
+Examples matches the if statement
+ (matcher = ifStmt(hasThen(cxxBoolLiteral(equals(true)))))
if (false) true; else false;
-}
-
-The matcher ifStmt(hasThen(cxxBoolLiteral(equals(true))))
-if (false) true; else false
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ImplicitCastExpr.html">ImplicitCastExpr</a>></td><td class="name" onclick="toggle('hasImplicitDestinationType0')"><a name="hasImplicitDestinationType0Anchor">hasImplicitDestinationType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasImplicitDestinationType0"><pre>Matches implicit casts whose destination type matches a given
matcher.
-
-Given
- unsigned int a = 0;
-
-The matcher
-implicitCastExpr(hasImplicitDestinationType(
-qualType(isUnsignedInteger()))) matches 0.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1InitListExpr.html">InitListExpr</a>></td><td class="name" onclick="toggle('hasInit0')"><a name="hasInit0Anchor">hasInit</a></td><td>unsigned N, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasInit0"><pre>Matches the n'th item of an initializer list expression.
-Given
- int y = 42;
- int x{y};
-
-The matcher initListExpr(hasInit(0, expr()))
-matches {y}.
+Example matches y.
+ (matcher = initListExpr(hasInit(0, expr())))
+ int x{y}.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1InitListExpr.html">InitListExpr</a>></td><td class="name" onclick="toggle('hasSyntacticForm0')"><a name="hasSyntacticForm0Anchor">hasSyntacticForm</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasSyntacticForm0"><pre>Matches the syntactic form of init list expressions
(if expression have it).
-
-Given
- int a[] = { 1, 2 };
- struct B { int x, y; };
- struct B b = { 5, 6 };
-
-
-The matcher
-initListExpr(hasSyntacticForm(expr().bind("syntactic")))
-matches { 1, 2 } and { 5, 6 }.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>></td><td class="name" onclick="toggle('hasDeclaration9')"><a name="hasDeclaration9Anchor">hasDeclaration</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration9"><pre>Matches a node if the declaration associated with that node
- matches the given matcher.
+matches the given matcher.
The associated declaration is:
- for type nodes, the declaration of the underlying type
@@ -12044,25 +9055,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
- for CXXNewExpr, the declaration of the operator new
- for ObjCIvarExpr, the declaration of the ivar
-Given
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
class X {};
typedef X Y;
Y y;
-
-For type nodes, hasDeclaration will generally match the declaration of the
-sugared type, i.e., the matcher
-varDecl(hasType(qualType(hasDeclaration(decl().bind("d"))))),
-matches Y y, with
-the matcher decl() matching
-typedef X Y;.
-A common use case is to match the underlying, desugared type.
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
This can be achieved by using the hasUnqualifiedDesugaredType matcher:
-varDecl(hasType(hasUnqualifiedDesugaredType(
- recordType(hasDeclaration(decl().bind("d"))))))
-matches Y y.
-In this matcher, the matcher decl() will match the
-CXXRecordDecl
-class X {};.
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>>,
@@ -12076,7 +9079,7 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>></td><td class="name" onclick="toggle('hasDeclaration8')"><a name="hasDeclaration8Anchor">hasDeclaration</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration8"><pre>Matches a node if the declaration associated with that node
- matches the given matcher.
+matches the given matcher.
The associated declaration is:
- for type nodes, the declaration of the underlying type
@@ -12086,25 +9089,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
- for CXXNewExpr, the declaration of the operator new
- for ObjCIvarExpr, the declaration of the ivar
-Given
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
class X {};
typedef X Y;
Y y;
-
-For type nodes, hasDeclaration will generally match the declaration of the
-sugared type, i.e., the matcher
-varDecl(hasType(qualType(hasDeclaration(decl().bind("d"))))),
-matches Y y, with
-the matcher decl() matching
-typedef X Y;.
-A common use case is to match the underlying, desugared type.
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
This can be achieved by using the hasUnqualifiedDesugaredType matcher:
-varDecl(hasType(hasUnqualifiedDesugaredType(
- recordType(hasDeclaration(decl().bind("d"))))))
-matches Y y.
-In this matcher, the matcher decl() will match the
-CXXRecordDecl
-class X {};.
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>>,
@@ -12127,13 +9122,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
auto f = [x](){};
auto g = [x = 1](){};
}
-
-The matcher
-lambdaExpr(hasAnyCapture(
- lambdaCapture(capturesVar(hasName("x"))).bind("capture")))
-matches [x](){} and [x = 1](){}, with
-lambdaCapture(capturesVar(hasName("x"))).bind("capture")
-matching x and x = 1.
+In the matcher
+lambdaExpr(hasAnyCapture(lambdaCapture(capturesVar(hasName("x")))),
+capturesVar(hasName("x")) matches `x` and `x = 1`.
</pre></td></tr>
@@ -12142,18 +9133,13 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
int main() {
- int x;
- int y;
+ int x, y;
float z;
auto f = [=]() { return x + y + z; };
}
-
-The matcher lambdaExpr(forEachLambdaCapture(
- lambdaCapture(capturesVar(
- varDecl(hasType(isInteger())).bind("captured")))))
-matches [=]() { return x + y + z; } two times,
-with varDecl(hasType(isInteger())) matching
-int x and int y.
+lambdaExpr(forEachLambdaCapture(
+ lambdaCapture(capturesVar(varDecl(hasType(isInteger()))))))
+will trigger two matches, binding for 'x' and 'y' respectively.
</pre></td></tr>
@@ -12165,16 +9151,15 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
int t = 5;
auto f = [=](){ return t; };
}
-
-The matcher lambdaExpr(hasAnyCapture(lambdaCapture())) and
-lambdaExpr(hasAnyCapture(lambdaCapture(capturesVar(hasName("t")))))
- both match [=](){ return t; }.
+lambdaExpr(hasAnyCapture(lambdaCapture())) and
+lambdaExpr(hasAnyCapture(lambdaCapture(refersToVarDecl(hasName("t")))))
+ both match `[=](){ return t; }`.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>></td><td class="name" onclick="toggle('hasDeclaration7')"><a name="hasDeclaration7Anchor">hasDeclaration</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration7"><pre>Matches a node if the declaration associated with that node
- matches the given matcher.
+matches the given matcher.
The associated declaration is:
- for type nodes, the declaration of the underlying type
@@ -12184,25 +9169,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
- for CXXNewExpr, the declaration of the operator new
- for ObjCIvarExpr, the declaration of the ivar
-Given
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
class X {};
typedef X Y;
Y y;
-
-For type nodes, hasDeclaration will generally match the declaration of the
-sugared type, i.e., the matcher
-varDecl(hasType(qualType(hasDeclaration(decl().bind("d"))))),
-matches Y y, with
-the matcher decl() matching
-typedef X Y;.
-A common use case is to match the underlying, desugared type.
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
This can be achieved by using the hasUnqualifiedDesugaredType matcher:
-varDecl(hasType(hasUnqualifiedDesugaredType(
- recordType(hasDeclaration(decl().bind("d"))))))
-matches Y y.
-In this matcher, the matcher decl() will match the
-CXXRecordDecl
-class X {};.
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>>,
@@ -12224,14 +9201,11 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
int m;
int f(X x) { x.m; return m; }
};
-
-
-The matcher
memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))))
-matches x.m, but not m; however,
-The matcher memberExpr(hasObjectExpression(hasType(pointsTo(
-cxxRecordDecl(hasName("X"))))))
-matches m (aka. this->m), but not x.m.
+ matches `x.m`, but not `m`; however,
+memberExpr(hasObjectExpression(hasType(pointsTo(
+ cxxRecordDecl(hasName("X"))))))
+ matches `m` (aka. `this->m`), but not `x.m`.
</pre></td></tr>
@@ -12240,14 +9214,13 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
given matcher.
Given
- struct { int first = 0, second = 1; } first, second;
- int i = second.first;
- int j = first.second;
-
-
-The matcher memberExpr(member(hasName("first")))
-matches second.first
-but not </pre></td></tr>
+ struct { int first, second; } first, second;
+ int i(second.first);
+ int j(first.second);
+memberExpr(member(hasName("first")))
+ matches second.first
+ but not first.second (because the member name there is "second").
+</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html">MemberPointerType</a>></td><td class="name" onclick="toggle('pointee1')"><a name="pointee1Anchor">pointee</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td></tr>
@@ -12256,14 +9229,10 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
int *a;
- const int *b;
- int * const c = nullptr;
- const float *f;
-
-The matcher pointerType(pointee(isConstQualified(), isInteger()))
-matches const int *,
-but does not match int * const
-or const float *.
+ int const *b;
+ float const *f;
+pointerType(pointee(isConstQualified(), isInteger()))
+ matches "int const *b"
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockPointerType.html">BlockPointerType</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html">MemberPointerType</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1PointerType.html">PointerType</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ReferenceType.html">ReferenceType</a>>
@@ -12277,10 +9246,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
namespace N { template<class T> void f(T t); }
template <class T> void g() { using N::f; f(T()); }
-
-The matcher unresolvedLookupExpr(hasAnyDeclaration(
+unresolvedLookupExpr(hasAnyDeclaration(
namedDecl(hasUnderlyingDecl(hasName("::N::f")))))
- matches f in g().
+ matches the use of f in g() .
</pre></td></tr>
@@ -12290,29 +9258,14 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
struct A { struct B { struct C {}; }; };
A::B::C c;
-
-The matcher
-nestedNameSpecifierLoc(hasPrefix(loc(specifiesType(asString(
-"struct A"))))) matches A::B::.
+nestedNameSpecifierLoc(hasPrefix(loc(specifiesType(asString("struct A")))))
+ matches "A::"
</pre></td></tr>
-<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>></td><td class="name" onclick="toggle('loc1')"><a name="loc1Anchor">loc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifier.html">NestedNameSpecifier</a>> InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="loc1"><pre>Matches NestedNameSpecifierLocs for which the given inner
-NestedNameSpecifier-matcher matches.
-
-Given
- namespace ns {
- struct A { static void f(); };
- void A::f() {}
- void g() { A::f(); }
- }
- ns::A a;
-
-
-The matcher nestedNameSpecifierLoc(loc(specifiesType(
-hasDeclaration(namedDecl(hasName("A")))))) matches A::
-twice.
+<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>></td><td class="name" onclick="toggle('loc1')"><a name="loc1Anchor">loc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifier.html">NestedNameSpecifier</a>> InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="loc1"><pre>Matches NestedNameSpecifierLocs for which the given inner
+NestedNameSpecifier-matcher matches.
</pre></td></tr>
@@ -12323,10 +9276,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
struct A { struct B { struct C {}; }; };
A::B::C c;
-
-The matcher nestedNameSpecifierLoc(specifiesTypeLoc(loc(qualType(
+nestedNameSpecifierLoc(specifiesTypeLoc(loc(type(
hasDeclaration(cxxRecordDecl(hasName("A")))))))
-matches A::
+ matches "A::"
</pre></td></tr>
@@ -12336,10 +9288,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
struct A { struct B { struct C {}; }; };
A::B::C c;
-
-The matcher
-nestedNameSpecifier(hasPrefix(specifiesType(asString(
-"struct A")))) matches struct A::B
+nestedNameSpecifier(hasPrefix(specifiesType(asString("struct A")))) and
+ matches "A::"
</pre></td></tr>
@@ -12350,10 +9300,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
namespace ns { struct A {}; }
ns::A a;
-
-The matcher
-nestedNameSpecifier(specifiesNamespace(hasName("ns"))) matches
-ns.
+nestedNameSpecifier(specifiesNamespace(hasName("ns")))
+ matches "ns::"
</pre></td></tr>
@@ -12364,11 +9312,10 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
struct A { struct B { struct C {}; }; };
A::B::C c;
-
-The matcher nestedNameSpecifier(specifiesType(
+nestedNameSpecifier(specifiesType(
hasDeclaration(cxxRecordDecl(hasName("A")))
))
-matches A.
+ matches "A::"
</pre></td></tr>
@@ -12376,16 +9323,12 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasAnyClause0"><pre>Matches any clause in an OpenMP directive.
Given
- void foo() {
+
#pragma omp parallel
- ;
#pragma omp parallel default(none)
- ;
- }
-
-The matcher ompExecutableDirective(hasAnyClause(anything()))
-matches #pragma omp parallel default(none).
+``ompExecutableDirective(hasAnyClause(anything()))`` matches
+``omp parallel default(none)``.
</pre></td></tr>
@@ -12396,18 +9339,13 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
If it is, it will never match.
Given
- void foo() {
- #pragma omp parallel
- ;
- #pragma omp parallel
- {}
- }
+ #pragma omp parallel
+ ;
+ #pragma omp parallel
+ {}
-The matcher
-ompExecutableDirective(hasStructuredBlock(nullStmt().bind("stmt")))
-matches #pragma omp parallel,
-with stmtt() matching {}.
+``ompExecutableDirective(hasStructuredBlock(nullStmt()))`` will match ``;``
</pre></td></tr>
@@ -12419,29 +9357,22 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Note that a class is not considered to be derived from itself.
Example matches Y, Z, C (Base == hasName("X"))
- class X {};
+ class X;
class Y : public X {}; // directly derived
class Z : public Y {}; // indirectly derived
typedef X A;
typedef A B;
class C : public B {}; // derived from a typedef of X
- class Foo {};
- typedef Foo Alias;
- class Bar : public Alias {};
- // derived from a type that Alias is a typedef of Foo
-
-
-The matcher cxxRecordDecl(isDerivedFrom(hasName("X")))
-matches Y, Z and C.
-The matcher cxxRecordDecl(isDerivedFrom(hasName("Foo")))
-matches Bar.
+In the following example, Bar matches isDerivedFrom(hasName("X")):
+ class Foo;
+ typedef Foo X;
+ class Bar : public Foo {}; // derived from a type that X is a typedef of
In the following example, Bar matches isDerivedFrom(hasName("NSObject"))
@interface NSObject @end
@interface Bar : NSObject @end
-
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCInterfaceDecl.html">ObjCInterfaceDecl</a>>
</pre></td></tr>
@@ -12452,45 +9383,24 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Note that a class is not considered to be derived from itself.
-Given
- class X {};
+Example matches Y, C (Base == hasName("X"))
+ class X;
class Y : public X {}; // directly derived
class Z : public Y {}; // indirectly derived
typedef X A;
typedef A B;
class C : public B {}; // derived from a typedef of X
-The matcher
-cxxRecordDecl(isDirectlyDerivedFrom(namedDecl(hasName("X"))))
-matches Y and C (Base == hasName("X")
-
In the following example, Bar matches isDerivedFrom(hasName("X")):
- class Foo {};
+ class Foo;
typedef Foo X;
class Bar : public Foo {}; // derived from a type that X is a typedef of
-
-The matcher cxxRecordDecl(isDerivedFrom(hasName("X")))
-matches Bar
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCInterfaceDecl.html">ObjCInterfaceDecl</a>></td><td class="name" onclick="toggle('isSameOrDerivedFrom1')"><a name="isSameOrDerivedFrom1Anchor">isSameOrDerivedFrom</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>> Base</td></tr>
<tr><td colspan="4" class="doc" id="isSameOrDerivedFrom1"><pre>Similar to isDerivedFrom(), but also matches classes that directly
match Base.
-
-Given
- class X {};
- class Y : public X {}; // directly derived
- class Z : public Y {}; // indirectly derived
- typedef X A;
- typedef A B;
- class C : public B {}; // derived from a typedef of X
-
-The matcher
-cxxRecordDecl(isSameOrDerivedFrom(cxxRecordDecl(hasName("X"))),
-isDefinition())
-matches class X {}, class Y : public X {},
-class Z : public Y {} and class C : public B {}.
</pre></td></tr>
@@ -12499,23 +9409,19 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
given matcher; or 2) if the Obj-C message expression's callee's method
declaration matches the given matcher.
-Example 1
+Example matches y.x() (matcher = callExpr(callee(
+ cxxMethodDecl(hasName("x")))))
class Y { public: void x(); };
void z() { Y y; y.x(); }
-The matcher callExpr(callee(cxxMethodDecl(hasName("x"))))
-matches y.x()
+Example 2. Matches [I foo] with
+objcMessageExpr(callee(objcMethodDecl(hasName("foo"))))
-Example 2
@interface I: NSObject
+(void)foo;
@end
...
[I foo]
-
-The matcher
-objcMessageExpr(callee(objcMethodDecl(hasName("foo"))))
-matches [I foo]
</pre></td></tr>
@@ -12524,19 +9430,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
expression, or an ObjC-message-send expression.
Given
- void x(int, int, int) { int y = 42; x(1, y, 42); }
-The matcher
-callExpr(hasAnyArgument(ignoringImplicit(declRefExpr()))) matches
-x(1, y, 42) with hasAnyArgument(...)
+ void x(int, int, int) { int y; x(1, y, 42); }
+callExpr(hasAnyArgument(declRefExpr()))
+ matches x(1, y, 42)
+with hasAnyArgument(...)
matching y
For ObjectiveC, given
@interface I - (void) f:(int) y; @end
void foo(I *i) { [i f:12]; }
-
-The matcher
objcMessageExpr(hasAnyArgument(integerLiteral(equals(12))))
-matches [i f:12]
+ matches [i f:12]
</pre></td></tr>
@@ -12544,11 +9448,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasArgument3"><pre>Matches the n'th argument of a call expression or a constructor
call expression.
-Given
+Example matches y in x(y)
+ (matcher = callExpr(hasArgument(0, declRefExpr())))
void x(int) { int y; x(y); }
-The matcher callExpr(hasArgument(0, declRefExpr().bind("arg")))
-matches x(y),
-with declRefExpr() matching y.
</pre></td></tr>
@@ -12556,26 +9458,23 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasReceiver0"><pre>Matches if the Objective-C message is sent to an instance,
and the inner matcher matches on that instance.
-Given
+For example the method call in
NSString *x = @"hello";
[x containsString:@"h"];
-
-The matcher
+is matched by
objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x"))))))
-matches [x containsString:@"h"];
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>></td><td class="name" onclick="toggle('hasReceiverType0')"><a name="hasReceiverType0Anchor">hasReceiverType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasReceiverType0"><pre>Matches on the receiver of an ObjectiveC Message expression.
+Example
+matcher = objCMessageExpr(hasReceiverType(asString("UIWebView *")));
+matches the [webView ...] message invocation.
NSString *webViewJavaScript = ...
UIWebView *webView = ...
[webView stringByEvaluatingJavaScriptFromString:webViewJavascript];
-
-The matcher objCMessageExpr(hasReceiverType(asString("UIWebView
-*"))) matches
-[webViewstringByEvaluatingJavaScriptFromString:webViewJavascript];
</pre></td></tr>
@@ -12587,26 +9486,23 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
class X { void f(int x, int y, int z) {} };
-
-The matcher cxxMethodDecl(hasAnyParameter(hasName("y")))
- matches f
+cxxMethodDecl(hasAnyParameter(hasName("y")))
+ matches f(int x, int y, int z) {}
with hasAnyParameter(...)
matching int y
For ObjectiveC, given
@interface I - (void) f:(int) y; @end
-
the matcher objcMethodDecl(hasAnyParameter(hasName("y")))
- matches the declaration of method f with hasParameter
+matches the declaration of method f with hasParameter
matching y.
For blocks, given
b = ^(int y) { printf("%d", y) };
-
the matcher blockDecl(hasAnyParameter(hasName("y")))
- matches the declaration of the block b with hasParameter
+matches the declaration of the block b with hasParameter
matching y.
</pre></td></tr>
@@ -12617,18 +9513,15 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
class X { void f(int x) {} };
-
-The matcher
-cxxMethodDecl(hasParameter(0, hasType(asString("int"))))
-matches f
+cxxMethodDecl(hasParameter(0, hasType(varDecl())))
+ matches f(int x) {}
with hasParameter(...)
-matching int x.
+ matching int x
For ObjectiveC, given
@interface I - (void) f:(int) y; @end
-
-The matcher objcMethodDecl(hasParameter(0, hasName("y")))
+the matcher objcMethodDecl(hasParameter(0, hasName("y")))
matches the declaration of method f with hasParameter
matching y.
</pre></td></tr>
@@ -12637,26 +9530,19 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCPropertyDecl.html">ObjCPropertyDecl</a>></td><td class="name" onclick="toggle('hasTypeLoc10')"><a name="hasTypeLoc10Anchor">hasTypeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr>
<tr><td colspan="4" class="doc" id="hasTypeLoc10"><pre>Matches if the type location of a node matches the inner matcher.
-Given
+Examples:
int x;
-The matcher declaratorDecl(hasTypeLoc(loc(asString("int"))))
-matches int x.
-
-Given
-struct point { point(double, double); };
-point p = point(1.0, -1.0);
+declaratorDecl(hasTypeLoc(loc(asString("int"))))
+ matches int x
-The matcher
-cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("point"))))
-matches point(1.0, -1.0).
+auto x = int(3);
+cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("int"))))
+ matches int(3)
-Given
struct Foo { Foo(int, int); };
-Foo x = Foo(1, 2);
-
-The matcher cxxTemporaryObjectExpr(hasTypeLoc(
- loc(asString("Foo"))))
-matches Foo(1, 2).
+auto x = Foo(1, 2);
+cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo"))))
+ matches Foo(1, 2)
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html">BlockDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>,
@@ -12673,23 +9559,14 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasSourceExpression1"><pre>Matches if the cast's source expression
or opaque value's source expression matches the given matcher.
-Given
- struct URL { URL(const char*); };
- URL url = "a string";
-
-The matcher castExpr(hasSourceExpression(cxxConstructExpr()))
-matches "a string".
+Example 1: matches "a string"
+(matcher = castExpr(hasSourceExpression(cxxConstructExpr())))
+class URL { URL(string); };
+URL url = "a string";
-Given
-void foo(bool b) {
- int a = b ?: 1;
-}
-
-The matcher
-opaqueValueExpr(hasSourceExpression(
- implicitCastExpr(has(
- implicitCastExpr(has(declRefExpr()))))))
-matches b twice, for the conditiona and the true expression.
+Example 2: matches 'b' (matcher =
+opaqueValueExpr(hasSourceExpression(implicitCastExpr(declRefExpr())))
+int a = b ?: 1;
</pre></td></tr>
@@ -12704,11 +9581,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
foo(t);
bar(t);
}
-
-The matcher unresolvedLookupExpr(hasAnyDeclaration(
+unresolvedLookupExpr(hasAnyDeclaration(
functionTemplateDecl(hasName("foo"))))
-matches foo in foo(t);
-but does not match bar in bar(t);
+ matches foo in foo(t); but not bar in bar(t);
</pre></td></tr>
@@ -12719,10 +9594,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
int (*ptr_to_array)[4];
int (*ptr_to_func)(int);
-The matcher
-varDecl(hasType(pointsTo(parenType(innerType(functionType())))))
- matches ptr_to_func but not
- ptr_to_array.
+varDecl(hasType(pointsTo(parenType(innerType(functionType()))))) matches
+ptr_to_func but not ptr_to_array.
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ParenType.html">ParenType</a>>
</pre></td></tr>
@@ -12734,8 +9607,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
int* x;
-The matcher pointerTypeLoc(hasPointeeLoc(loc(asString("int"))))
- matches int*.
+pointerTypeLoc(hasPointeeLoc(loc(asString("int"))))
+ matches `int*`.
</pre></td></tr>
@@ -12745,14 +9618,10 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
int *a;
- const int *b;
- int * const c = nullptr;
- const float *f;
-
-The matcher pointerType(pointee(isConstQualified(), isInteger()))
-matches const int *,
-but does not match int * const
-or const float *.
+ int const *b;
+ float const *f;
+pointerType(pointee(isConstQualified(), isInteger()))
+ matches "int const *b"
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockPointerType.html">BlockPointerType</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html">MemberPointerType</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1PointerType.html">PointerType</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ReferenceType.html">ReferenceType</a>>
@@ -12762,22 +9631,19 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>></td><td class="name" onclick="toggle('hasCanonicalType0')"><a name="hasCanonicalType0Anchor">hasCanonicalType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasCanonicalType0"><pre>Matches QualTypes whose canonical type matches InnerMatcher.
-Given
+Given:
typedef int &int_ref;
int a;
int_ref b = a;
-The matcher varDecl(hasType(qualType(referenceType())))
-does not match int_ref b = a,
-but the matcher
-varDecl(hasType(qualType(hasCanonicalType(referenceType()))))
-does match int_ref b = a.
+varDecl(hasType(qualType(referenceType()))))) will not match the
+declaration of b but varDecl(hasType(qualType(hasCanonicalType(referenceType())))))) does.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>></td><td class="name" onclick="toggle('hasDeclaration6')"><a name="hasDeclaration6Anchor">hasDeclaration</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration6"><pre>Matches a node if the declaration associated with that node
- matches the given matcher.
+matches the given matcher.
The associated declaration is:
- for type nodes, the declaration of the underlying type
@@ -12787,25 +9653,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
- for CXXNewExpr, the declaration of the operator new
- for ObjCIvarExpr, the declaration of the ivar
-Given
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
class X {};
typedef X Y;
Y y;
-
-For type nodes, hasDeclaration will generally match the declaration of the
-sugared type, i.e., the matcher
-varDecl(hasType(qualType(hasDeclaration(decl().bind("d"))))),
-matches Y y, with
-the matcher decl() matching
-typedef X Y;.
-A common use case is to match the underlying, desugared type.
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
This can be achieved by using the hasUnqualifiedDesugaredType matcher:
-varDecl(hasType(hasUnqualifiedDesugaredType(
- recordType(hasDeclaration(decl().bind("d"))))))
-matches Y y.
-In this matcher, the matcher decl() will match the
-CXXRecordDecl
-class X {};.
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>>,
@@ -12823,56 +9681,30 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
void (*fp)(void);
The matcher
-varDecl(hasType(pointerType(pointee(ignoringParens(functionType())))))
-matches fp.
+ varDecl(hasType(pointerType(pointee(ignoringParens(functionType())))))
+would match the declaration for fp.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>></td><td class="name" onclick="toggle('pointsTo1')"><a name="pointsTo1Anchor">pointsTo</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="pointsTo1"><pre>Matches if the matched type is a pointer type and the pointee type
- matches the specified matcher.
-Overloaded to match the pointee type's declaration.
-
-Given
- class Y { public: void x(); };
- void z() { Y *y; y->x(); }
-
-The matcher cxxMemberCallExpr(on(hasType(pointsTo(
- cxxRecordDecl(hasName("Y"))))))
-matches y->x()
+<tr><td colspan="4" class="doc" id="pointsTo1"><pre>Overloaded to match the pointee type's declaration.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>></td><td class="name" onclick="toggle('pointsTo0')"><a name="pointsTo0Anchor">pointsTo</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="pointsTo0"><pre>Matches if the matched type is a pointer type and the pointee type
- matches the specified matcher.
+matches the specified matcher.
-Given
+Example matches y->x()
+ (matcher = cxxMemberCallExpr(on(hasType(pointsTo
+ cxxRecordDecl(hasName("Y")))))))
class Y { public: void x(); };
void z() { Y *y; y->x(); }
-
-The matcher cxxMemberCallExpr(on(hasType(pointsTo(
- qualType()))))
-matches y->x()
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>></td><td class="name" onclick="toggle('references1')"><a name="references1Anchor">references</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="references1"><pre>Matches if the matched type is a reference type and the referenced
-type matches the specified matcher.
-Overloaded to match the referenced type's declaration.
-
-Given
- class X {
- void a(X b) {
- X &x = b;
- const X &y = b;
- }
- };
-
-The matcher
-varDecl(hasType(references(cxxRecordDecl(hasName("X"))))) matches
-X &x = b and const X &y = b.
+<tr><td colspan="4" class="doc" id="references1"><pre>Overloaded to match the referenced type's declaration.
</pre></td></tr>
@@ -12880,17 +9712,14 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="references0"><pre>Matches if the matched type is a reference type and the referenced
type matches the specified matcher.
-Given
+Example matches X &x and const X &y
+ (matcher = varDecl(hasType(references(cxxRecordDecl(hasName("X"))))))
class X {
void a(X b) {
X &x = b;
const X &y = b;
}
};
-
-The matcher
-varDecl(hasType(references(qualType()))) matches
-X &x = b and const X &y = b.
</pre></td></tr>
@@ -12899,18 +9728,16 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
`InnerMatcher`.
Given
- int* const x = nullptr;
- const int y = 0;
-
-
-The matcher qualifiedTypeLoc(hasUnqualifiedLoc(pointerTypeLoc()))
-matches the type int* of the variable declaration but
-not </pre></td></tr>
+ int* const x;
+ const int y;
+qualifiedTypeLoc(hasUnqualifiedLoc(pointerTypeLoc()))
+ matches the `TypeLoc` of the variable declaration of `x`, but not `y`.
+</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>></td><td class="name" onclick="toggle('hasDeclaration5')"><a name="hasDeclaration5Anchor">hasDeclaration</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration5"><pre>Matches a node if the declaration associated with that node
- matches the given matcher.
+matches the given matcher.
The associated declaration is:
- for type nodes, the declaration of the underlying type
@@ -12920,25 +9747,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
- for CXXNewExpr, the declaration of the operator new
- for ObjCIvarExpr, the declaration of the ivar
-Given
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
class X {};
typedef X Y;
Y y;
-
-For type nodes, hasDeclaration will generally match the declaration of the
-sugared type, i.e., the matcher
-varDecl(hasType(qualType(hasDeclaration(decl().bind("d"))))),
-matches Y y, with
-the matcher decl() matching
-typedef X Y;.
-A common use case is to match the underlying, desugared type.
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
This can be achieved by using the hasUnqualifiedDesugaredType matcher:
-varDecl(hasType(hasUnqualifiedDesugaredType(
- recordType(hasDeclaration(decl().bind("d"))))))
-matches Y y.
-In this matcher, the matcher decl() will match the
-CXXRecordDecl
-class X {};.
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>>,
@@ -12957,10 +9776,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
int x = 3;
int& xx = x;
-
-
-The matcher referenceTypeLoc(hasReferentLoc(loc(asString("int"))))
- matches int&.
+referenceTypeLoc(hasReferentLoc(loc(asString("int"))))
+ matches `int&`.
</pre></td></tr>
@@ -12970,14 +9787,10 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
int *a;
- const int *b;
- int * const c = nullptr;
- const float *f;
-
-The matcher pointerType(pointee(isConstQualified(), isInteger()))
-matches const int *,
-but does not match int * const
-or const float *.
+ int const *b;
+ float const *f;
+pointerType(pointee(isConstQualified(), isInteger()))
+ matches "int const *b"
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockPointerType.html">BlockPointerType</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html">MemberPointerType</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1PointerType.html">PointerType</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ReferenceType.html">ReferenceType</a>>
@@ -12988,13 +9801,11 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasReturnValue0"><pre>Matches the return value expression of a return statement
Given
- int foo(int a, int b) {
- return a + b;
- }
-The matcher
-returnStmt(hasReturnValue(binaryOperator().bind("op"))) matches
-return a + b, with binaryOperator() matching
-a + b.
+ return a + b;
+hasReturnValue(binaryOperator())
+ matches 'return a + b'
+with binaryOperator()
+ matching 'a + b'
</pre></td></tr>
@@ -13003,25 +9814,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
a given matcher. Also matches StmtExprs that have CompoundStmt as children.
Given
-void foo() { { {}; 1+2; } }
-The matcher
-compoundStmt(hasAnySubstatement(compoundStmt().bind("compound")))
-{ {}; 1+2; } and { { {}; 1+2; } }
+ { {}; 1+2; }
+hasAnySubstatement(compoundStmt())
+ matches '{ {}; 1+2; }'
with compoundStmt()
-matching {} and { {}; 1+2; }.
+ matching '{}'
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('alignOfExpr0')"><a name="alignOfExpr0Anchor">alignOfExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html">UnaryExprOrTypeTraitExpr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="alignOfExpr0"><pre>Same as unaryExprOrTypeTraitExpr, but only matching
alignof.
-
-Given
- int align = alignof(int);
-
-
-The matcher alignOfExpr(expr())
-matches alignof(int).
</pre></td></tr>
@@ -13029,30 +9832,26 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="forCallable0"><pre>Matches declaration of the function, method, or block the statement
belongs to.
-Given
-struct F {
- F& operator=(const F& other) {
- []() { return 42 == 42; };
- return *this;
- }
-};
-
-The matcher returnStmt(forFunction(hasName("operator=")))
-matches return *this
-but does not match return 42 == 42.
+Given:
+F& operator=(const F& o) {
+ std::copy_if(o.begin(), o.end(), begin(), [](V v) { return v > 0; });
+ return *this;
+}
+returnStmt(forCallable(functionDecl(hasName("operator="))))
+ matches 'return *this'
+ but does not match 'return v > 0'
-Given
-void foo {
+Given:
+-(void) foo {
int x = 1;
dispatch_sync(queue, ^{ int y = 2; });
}
-
-The matcher declStmt(forCallable(objcMethodDecl()))
-matches int x = 1
-but does not match int y = 2.
-The matcher declStmt(forCallable(blockDecl()))
-matches int y = 2
-but does not match int x = 1.
+declStmt(forCallable(objcMethodDecl()))
+ matches 'int x = 1'
+ but does not match 'int y = 2'.
+whereas declStmt(forCallable(blockDecl()))
+ matches 'int y = 2'
+ but does not match 'int x = 1'.
</pre></td></tr>
@@ -13061,34 +9860,23 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Deprecated. Use forCallable() to correctly handle the situation when
the declaration is not a function (but a block or an Objective-C method).
-The matcher forFunction() not only fails to take non-functions
-into account but also may match the wrong declaration in their presence.
-
-Given
- struct F {
- F& operator=(const F& other) {
- []() { return 42 == 42; };
- return *this;
- }
- };
-
+forFunction() not only fails to take non-functions into account but also
+may match the wrong declaration in their presence.
-The matcher returnStmt(forFunction(hasName("operator=")))
-matches return *this
-but does not match return 42 == 42.
+Given:
+F& operator=(const F& o) {
+ std::copy_if(o.begin(), o.end(), begin(), [](V v) { return v > 0; });
+ return *this;
+}
+returnStmt(forFunction(hasName("operator=")))
+ matches 'return *this'
+ but does not match 'return v > 0'
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('sizeOfExpr0')"><a name="sizeOfExpr0Anchor">sizeOfExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html">UnaryExprOrTypeTraitExpr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="sizeOfExpr0"><pre>Same as unaryExprOrTypeTraitExpr, but only matching
sizeof.
-
-Given
- struct S { double x; double y; };
- int size = sizeof(struct S);
-
-The matcher sizeOfExpr(expr())
-matches sizeof(struct S).
</pre></td></tr>
@@ -13102,9 +9890,7 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
int i;
double j = F(i);
-
-The matcher substTemplateTypeParmType(hasReplacementType(type()))
-matches int.
+substTemplateTypeParmType(hasReplacementType(type())) matches int
</pre></td></tr>
@@ -13113,18 +9899,11 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
statement. This matcher may produce multiple matches.
Given
- void foo() {
- switch (1) { case 1: case 2: default: switch (2) { case 3: case 4: ; } }
- }
-The matcher
-switchStmt(forEachSwitchCase(caseStmt().bind("c")))
-matches four times, matching
-switch (1) { case 1: case 2: default: switch (2) { case 3:
-case 4: ; } } and
-switch (2) { case 3: case 4: ; }, with
-caseStmt() matching each of case 1:,
-case 2:, case 3:
-and case 4:.
+ switch (1) { case 1: case 2: default: switch (2) { case 3: case 4: ; } }
+switchStmt(forEachSwitchCase(caseStmt().bind("c"))).bind("s")
+ matches four times, with "c" binding each of "case 1:", "case 2:",
+"case 3:" and "case 4:", and "s" respectively binding "switch (1)",
+"switch (1)", "switch (2)" and "switch (2)".
</pre></td></tr>
@@ -13132,23 +9911,15 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasCondition4"><pre>Matches the condition expression of an if statement, for loop,
switch statement or conditional operator.
-Given
-void foo() {
+Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
if (true) {}
-}
-
-The matcher ifStmt(hasCondition(cxxBoolLiteral(equals(true))))
-if (true) {}
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1SwitchStmt.html">SwitchStmt</a>></td><td class="name" onclick="toggle('hasInitStatement1')"><a name="hasInitStatement1Anchor">hasInitStatement</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasInitStatement1"><pre>Matches selection statements with initializer.
-Given
- struct vec { int* begin(); int* end(); };
- int foobar();
- vec& get_range();
+Given:
void foo() {
if (int i = foobar(); i > 0) {}
switch (int i = foobar(); i) {}
@@ -13159,23 +9930,18 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
switch (foobar()) {}
for (auto& x : get_range()) {}
}
-
-The matcher ifStmt(hasInitStatement(anything()))
- matches the if statement if (int i = foobar(); i > 0) {}
- in foo but not if (foobar() > 0) {} in bar.
-The matcher switchStmt(hasInitStatement(anything()))
- matches the switch statement switch (int i = foobar(); i) {}
- in foo but not switch (foobar()) {} in bar.
-The matcher cxxForRangeStmt(hasInitStatement(anything()))
- matches the range for statement
- for (auto& a = get_range(); auto& x : a) {} in foo
- but not for (auto& x : get_range()) {} in bar.
+ifStmt(hasInitStatement(anything()))
+ matches the if statement in foo but not in bar.
+switchStmt(hasInitStatement(anything()))
+ matches the switch statement in foo but not in bar.
+cxxForRangeStmt(hasInitStatement(anything()))
+ matches the range for statement in foo but not in bar.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>></td><td class="name" onclick="toggle('hasDeclaration4')"><a name="hasDeclaration4Anchor">hasDeclaration</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration4"><pre>Matches a node if the declaration associated with that node
- matches the given matcher.
+matches the given matcher.
The associated declaration is:
- for type nodes, the declaration of the underlying type
@@ -13185,25 +9951,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
- for CXXNewExpr, the declaration of the operator new
- for ObjCIvarExpr, the declaration of the ivar
-Given
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
class X {};
typedef X Y;
Y y;
-
-For type nodes, hasDeclaration will generally match the declaration of the
-sugared type, i.e., the matcher
-varDecl(hasType(qualType(hasDeclaration(decl().bind("d"))))),
-matches Y y, with
-the matcher decl() matching
-typedef X Y;.
-A common use case is to match the underlying, desugared type.
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
This can be achieved by using the hasUnqualifiedDesugaredType matcher:
-varDecl(hasType(hasUnqualifiedDesugaredType(
- recordType(hasDeclaration(decl().bind("d"))))))
-matches Y y.
-In this matcher, the matcher decl() will match the
-CXXRecordDecl
-class X {};.
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>>,
@@ -13218,26 +9976,19 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>></td><td class="name" onclick="toggle('hasTypeLoc11')"><a name="hasTypeLoc11Anchor">hasTypeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr>
<tr><td colspan="4" class="doc" id="hasTypeLoc11"><pre>Matches if the type location of a node matches the inner matcher.
-Given
+Examples:
int x;
-The matcher declaratorDecl(hasTypeLoc(loc(asString("int"))))
-matches int x.
-
-Given
-struct point { point(double, double); };
-point p = point(1.0, -1.0);
+declaratorDecl(hasTypeLoc(loc(asString("int"))))
+ matches int x
-The matcher
-cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("point"))))
-matches point(1.0, -1.0).
+auto x = int(3);
+cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("int"))))
+ matches int(3)
-Given
struct Foo { Foo(int, int); };
-Foo x = Foo(1, 2);
-
-The matcher cxxTemporaryObjectExpr(hasTypeLoc(
- loc(asString("Foo"))))
-matches Foo(1, 2).
+auto x = Foo(1, 2);
+cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo"))))
+ matches Foo(1, 2)
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html">BlockDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>,
@@ -13257,13 +10008,10 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
struct B { int next; };
template<int(B::*next_ptr)> struct A {};
A<&B::next> a;
-
-The matcher
templateSpecializationType(hasAnyTemplateArgument(
- isExpr(hasDescendant(declRefExpr(to(fieldDecl(hasName("next")).bind("next")))))))
-matches the specialization A<&struct B::next>
-with fieldDecl(hasName("next")) matching
-B::next.
+ isExpr(hasDescendant(declRefExpr(to(fieldDecl(hasName("next"))))))))
+ matches the specialization A<&B::next> with fieldDecl(...) matching
+ B::next
</pre></td></tr>
@@ -13275,13 +10023,10 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
struct B { int next; };
template<int(B::*next_ptr)> struct A {};
A<&B::next> a;
-
-The matcher
classTemplateSpecializationDecl(hasAnyTemplateArgument(
- refersToDeclaration(fieldDecl(hasName("next")).bind("next"))))
-matches the specialization struct A<&B::next>
-with fieldDecl(hasName("next")) matching
-B::next.
+ refersToDeclaration(fieldDecl(hasName("next")))))
+ matches the specialization A<&B::next> with fieldDecl(...) matching
+ B::next
</pre></td></tr>
@@ -13291,12 +10036,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
template<int T> struct C {};
C<42> c;
-
-The matcher classTemplateSpecializationDecl(
+classTemplateSpecializationDecl(
hasAnyTemplateArgument(refersToIntegralType(asString("int"))))
-matches the implicitly declared specialization
-struct C<42> from the instantiation for the type of the
-variable c .
+ matches the implicit instantiation of C in C<42>.
</pre></td></tr>
@@ -13307,11 +10049,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
template<template <typename> class S> class X {};
template<typename T> class Y {};
X<Y> xi;
-
-The matcher
classTemplateSpecializationDecl(hasAnyTemplateArgument(
- refersToTemplate(templateName())))
-matches the specialization class X<Y>
+ refersToTemplate(templateName())))
+ matches the specialization X<Y>
</pre></td></tr>
@@ -13322,11 +10062,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
struct X {};
template<typename T> struct A {};
A<X> a;
-
-The matcher
classTemplateSpecializationDecl(hasAnyTemplateArgument(refersToType(
- recordType(hasDeclaration(recordDecl(hasName("X")))))))
-matches the specialization struct A<struct X>.
+ recordType(hasDeclaration(recordDecl(hasName("X")))))))
+matches the specialization of struct A generated by A<X>.
</pre></td></tr>
@@ -13339,11 +10077,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
template<typename T> class A {};
A<int> a;
-
-The matcher
-varDecl(hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
-templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
-hasTypeLoc(loc(asString("int"))))))))) matches A<int> a.
+varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
+ hasTypeLoc(loc(asString("int")))))))
+ matches `A<int> a`.
</pre></td></tr>
@@ -13356,12 +10092,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
template<typename T, typename U> class A {};
A<double, int> b;
A<int, double> c;
-
-The matcher
-varDecl(hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
-templateSpecializationTypeLoc(hasTemplateArgumentLoc(0,
-hasTypeLoc(loc(asString("double")))))))))
-matches A<double, int> b, but not double> c}.
+varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(0,
+ hasTypeLoc(loc(asString("double")))))))
+ matches `A<double, int> b`, but not `A<int, double> c`.
</pre></td></tr>
@@ -13381,22 +10114,13 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
template <typename T, typename U>
void f(T&& t, U&& u) {}
- void foo() {
- bool B = false;
- f(R, B);
- }
-
-The matcher
-templateSpecializationType(forEachTemplateArgument(isExpr(expr().bind("t_arg"))))
-matches Matrix<int, R * 2, R * 4> twice, with
-expr() matching R * 2 and
-R * 4.
-The matcher
-functionDecl(forEachTemplateArgument(refersToType(qualType().bind("type"))))
-matches the specialization of f twice,
-with qualType() matching
-unsigned and
-bool.
+ bool B = false;
+ f(R, B);
+templateSpecializationType(forEachTemplateArgument(isExpr(expr())))
+ matches twice, with expr() matching 'R * 2' and 'R * 4'
+functionDecl(forEachTemplateArgument(refersToType(builtinType())))
+ matches the specialization f<unsigned, bool> twice, for 'unsigned'
+ and 'bool'
</pre></td></tr>
@@ -13410,25 +10134,21 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
template<> class A<double> {};
A<int> a;
- template<typename T> void f() {};
+ template<typename T> f() {};
void func() { f<int>(); };
+classTemplateSpecializationDecl(hasAnyTemplateArgument(
+ refersToType(asString("int"))))
+ matches the specialization A<int>
-The matcher classTemplateSpecializationDecl(
- hasAnyTemplateArgument(
- refersToType(asString("int"))))
-matches class A<int>.
-
-The matcher
-functionDecl(hasAnyTemplateArgument(
- refersToType(asString("int"))))
-matches the instantiation of f.
+functionDecl(hasAnyTemplateArgument(refersToType(asString("int"))))
+ matches the specialization f<int>
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>></td><td class="name" onclick="toggle('hasDeclaration3')"><a name="hasDeclaration3Anchor">hasDeclaration</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration3"><pre>Matches a node if the declaration associated with that node
- matches the given matcher.
+matches the given matcher.
The associated declaration is:
- for type nodes, the declaration of the underlying type
@@ -13438,25 +10158,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
- for CXXNewExpr, the declaration of the operator new
- for ObjCIvarExpr, the declaration of the ivar
-Given
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
class X {};
typedef X Y;
Y y;
-
-For type nodes, hasDeclaration will generally match the declaration of the
-sugared type, i.e., the matcher
-varDecl(hasType(qualType(hasDeclaration(decl().bind("d"))))),
-matches Y y, with
-the matcher decl() matching
-typedef X Y;.
-A common use case is to match the underlying, desugared type.
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
This can be achieved by using the hasUnqualifiedDesugaredType matcher:
-varDecl(hasType(hasUnqualifiedDesugaredType(
- recordType(hasDeclaration(decl().bind("d"))))))
-matches Y y.
-In this matcher, the matcher decl() will match the
-CXXRecordDecl
-class X {};.
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>>,
@@ -13475,26 +10187,23 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
template<typename T, typename U> class A {};
- A<double, int> b;
- A<int, double> c;
+ A<bool, int> b;
+ A<int, bool> c;
template<typename T> void f() {}
void func() { f<int>(); };
-
-The matcher
classTemplateSpecializationDecl(hasTemplateArgument(
1, refersToType(asString("int"))))
-matches the specialization class A<double, int>.
+ matches the specialization A<bool, int>
-The matcher functionDecl(hasTemplateArgument(0,
- refersToType(asString("int"))))
-matches the specialization of f.
+functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))
+ matches the specialization f<int>
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>></td><td class="name" onclick="toggle('hasDeclaration2')"><a name="hasDeclaration2Anchor">hasDeclaration</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration2"><pre>Matches a node if the declaration associated with that node
- matches the given matcher.
+matches the given matcher.
The associated declaration is:
- for type nodes, the declaration of the underlying type
@@ -13504,25 +10213,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
- for CXXNewExpr, the declaration of the operator new
- for ObjCIvarExpr, the declaration of the ivar
-Given
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
class X {};
typedef X Y;
Y y;
-
-For type nodes, hasDeclaration will generally match the declaration of the
-sugared type, i.e., the matcher
-varDecl(hasType(qualType(hasDeclaration(decl().bind("d"))))),
-matches Y y, with
-the matcher decl() matching
-typedef X Y;.
-A common use case is to match the underlying, desugared type.
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
This can be achieved by using the hasUnqualifiedDesugaredType matcher:
-varDecl(hasType(hasUnqualifiedDesugaredType(
- recordType(hasDeclaration(decl().bind("d"))))))
-matches Y y.
-In this matcher, the matcher decl() will match the
-CXXRecordDecl
-class X {};.
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>>,
@@ -13537,37 +10238,25 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>></td><td class="name" onclick="toggle('loc0')"><a name="loc0Anchor">loc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="loc0"><pre>Matches TypeLocs for which the given inner
QualType-matcher matches.
-
- int a = 10;
-
-The matcher typeLoc(loc(qualType(isInteger())))
-matches the int of a .
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefNameDecl.html">TypedefNameDecl</a>></td><td class="name" onclick="toggle('hasTypeLoc12')"><a name="hasTypeLoc12Anchor">hasTypeLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr>
<tr><td colspan="4" class="doc" id="hasTypeLoc12"><pre>Matches if the type location of a node matches the inner matcher.
-Given
+Examples:
int x;
-The matcher declaratorDecl(hasTypeLoc(loc(asString("int"))))
-matches int x.
-
-Given
-struct point { point(double, double); };
-point p = point(1.0, -1.0);
+declaratorDecl(hasTypeLoc(loc(asString("int"))))
+ matches int x
-The matcher
-cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("point"))))
-matches point(1.0, -1.0).
+auto x = int(3);
+cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("int"))))
+ matches int(3)
-Given
struct Foo { Foo(int, int); };
-Foo x = Foo(1, 2);
-
-The matcher cxxTemporaryObjectExpr(hasTypeLoc(
- loc(asString("Foo"))))
-matches Foo(1, 2).
+auto x = Foo(1, 2);
+cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo"))))
+ matches Foo(1, 2)
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html">BlockDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFunctionalCastExpr.html">CXXFunctionalCastExpr</a>>,
@@ -13584,31 +10273,23 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasType2"><pre>Matches if the expression's or declaration's type matches a type
matcher.
-Exmaple
+Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
+ and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
+ and U (matcher = typedefDecl(hasType(asString("int")))
+ and friend class X (matcher = friendDecl(hasType("X"))
+ and public virtual X (matcher = cxxBaseSpecifier(hasType(
+ asString("class X")))
class X {};
void y(X &x) { x; X z; }
typedef int U;
class Y { friend class X; };
class Z : public virtual X {};
-
-The matcher expr(hasType(cxxRecordDecl(hasName("X"))))
-matches x and z.
-The matcher varDecl(hasType(cxxRecordDecl(hasName("X"))))
-matches z
-The matcher typedefDecl(hasType(asString("int")))
-matches typedef int U
-The matcher friendDecl(hasType(asString("class X")))
-matches friend class X
-The matcher cxxRecordDecl(hasAnyBase(cxxBaseSpecifier(hasType(
-asString("X"))).bind("b"))) matches class Z : public virtual X {},
-with cxxBaseSpecifier(...)
-matching public virtual X.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>></td><td class="name" onclick="toggle('hasDeclaration1')"><a name="hasDeclaration1Anchor">hasDeclaration</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration1"><pre>Matches a node if the declaration associated with that node
- matches the given matcher.
+matches the given matcher.
The associated declaration is:
- for type nodes, the declaration of the underlying type
@@ -13618,25 +10299,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
- for CXXNewExpr, the declaration of the operator new
- for ObjCIvarExpr, the declaration of the ivar
-Given
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
class X {};
typedef X Y;
Y y;
-
-For type nodes, hasDeclaration will generally match the declaration of the
-sugared type, i.e., the matcher
-varDecl(hasType(qualType(hasDeclaration(decl().bind("d"))))),
-matches Y y, with
-the matcher decl() matching
-typedef X Y;.
-A common use case is to match the underlying, desugared type.
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
This can be achieved by using the hasUnqualifiedDesugaredType matcher:
-varDecl(hasType(hasUnqualifiedDesugaredType(
- recordType(hasDeclaration(decl().bind("d"))))))
-matches Y y.
-In this matcher, the matcher decl() will match the
-CXXRecordDecl
-class X {};.
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>>,
@@ -13655,11 +10328,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
For example, in:
class A {};
using B = A;
- B b;
-
-The matcher
-varDecl(hasType(hasUnqualifiedDesugaredType(recordType())))
-matches B b.
+The matcher type(hasUnqualifiedDesugaredType(recordType())) matches
+both B and A.
</pre></td></tr>
@@ -13668,23 +10338,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
int a, c; float b; int s = sizeof(a) + sizeof(b) + alignof(c);
-
-The matcher
-unaryExprOrTypeTraitExpr(hasArgumentOfType(asString("int")))
-matches sizeof(a) and alignof(c)
+unaryExprOrTypeTraitExpr(hasArgumentOfType(asString("int"))
+ matches sizeof(a) and alignof(c)
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1UnaryOperator.html">UnaryOperator</a>></td><td class="name" onclick="toggle('hasUnaryOperand0')"><a name="hasUnaryOperand0Anchor">hasUnaryOperand</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasUnaryOperand0"><pre>Matches if the operand of a unary operator matches.
-void foo() {
- !true;
-}
-
-The matcher
-unaryOperator(hasUnaryOperand(cxxBoolLiteral(equals(true))))
-matches !true.
+Example matches true (matcher = hasUnaryOperand(
+ cxxBoolLiteral(equals(true))))
+ !true
</pre></td></tr>
@@ -13698,20 +10362,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
int m;
int f(X x) { x.m; return m; }
};
-
-
-The matcher
memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))))
-matches x.m, but not m; however,
-The matcher memberExpr(hasObjectExpression(hasType(pointsTo(
-cxxRecordDecl(hasName("X"))))))
-matches m (aka. this->m), but not x.m.
+ matches `x.m`, but not `m`; however,
+memberExpr(hasObjectExpression(hasType(pointsTo(
+ cxxRecordDecl(hasName("X"))))))
+ matches `m` (aka. `this->m`), but not `x.m`.
</pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>></td><td class="name" onclick="toggle('hasDeclaration0')"><a name="hasDeclaration0Anchor">hasDeclaration</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration0"><pre>Matches a node if the declaration associated with that node
- matches the given matcher.
+matches the given matcher.
The associated declaration is:
- for type nodes, the declaration of the underlying type
@@ -13721,25 +10382,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
- for CXXNewExpr, the declaration of the operator new
- for ObjCIvarExpr, the declaration of the ivar
-Given
+For type nodes, hasDeclaration will generally match the declaration of the
+sugared type. Given
class X {};
typedef X Y;
Y y;
-
-For type nodes, hasDeclaration will generally match the declaration of the
-sugared type, i.e., the matcher
-varDecl(hasType(qualType(hasDeclaration(decl().bind("d"))))),
-matches Y y, with
-the matcher decl() matching
-typedef X Y;.
-A common use case is to match the underlying, desugared type.
+in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+typedefDecl. A common use case is to match the underlying, desugared type.
This can be achieved by using the hasUnqualifiedDesugaredType matcher:
-varDecl(hasType(hasUnqualifiedDesugaredType(
- recordType(hasDeclaration(decl().bind("d"))))))
-matches Y y.
-In this matcher, the matcher decl() will match the
-CXXRecordDecl
-class X {};.
+ varDecl(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(decl())))))
+In this matcher, the decl will match the CXXRecordDecl of class X.
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AddrLabelExpr.html">AddrLabelExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>>,
@@ -13759,12 +10412,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
namespace X { int a; void b(); }
using X::a;
using X::b;
-
-The matcher
usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(functionDecl())))
- matches using X::b
- but not X::a}
-</pre></td></tr>
+ matches using X::b but not using X::a </pre></td></tr>
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1UsingType.html">UsingType</a>></td><td class="name" onclick="toggle('hasUnderlyingType1')"><a name="hasUnderlyingType1Anchor">hasUnderlyingType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td></tr>
@@ -13773,11 +10422,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
decltype(1) a = 1;
decltype(2.0) b = 2.0;
-
-
-The matcher decltypeType(hasUnderlyingType(isInteger()))
-matches the type decltype(1) of the variable
-declaration of a .
+decltypeType(hasUnderlyingType(isInteger()))
+ matches the type of "a"
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DecltypeType.html">DecltypeType</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1UsingType.html">UsingType</a>>
</pre></td></tr>
@@ -13787,20 +10433,18 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="throughUsingDecl1"><pre>Matches if a node refers to a declaration through a specific
using shadow declaration.
-Given
+Examples:
namespace a { int f(); }
using a::f;
int x = f();
-
-The matcher declRefExpr(throughUsingDecl(anything()))
-matches f
+declRefExpr(throughUsingDecl(anything()))
+ matches f
namespace a { class X{}; }
using a::X;
X x;
-
-The matcher typeLoc(loc(usingType(throughUsingDecl(anything()))))
-matches X
+typeLoc(loc(usingType(throughUsingDecl(anything()))))
+ matches X
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DeclRefExpr.html">DeclRefExpr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1UsingType.html">UsingType</a>>
</pre></td></tr>
@@ -13816,31 +10460,21 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
X, while varDecl(hasType(cxxRecordDecl(hasName("X")))) matches the
declaration of x.
+Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
+ and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
+ and friend class X (matcher = friendDecl(hasType("X"))
+ and public virtual X (matcher = cxxBaseSpecifier(hasType(
+ cxxRecordDecl(hasName("X"))))
class X {};
void y(X &x) { x; X z; }
class Y { friend class X; };
class Z : public virtual X {};
-The matcher expr(hasType(cxxRecordDecl(hasName("X"))))
-matches x and z.
-The matcher varDecl(hasType(cxxRecordDecl(hasName("X"))))
-matches z.
-The matcher friendDecl(hasType(asString("class X")))
-matches friend class X.
-The matcher cxxRecordDecl(hasAnyBase(cxxBaseSpecifier(hasType(
-asString("X"))).bind("b"))) matches
-class Z : public virtual X {},
-with cxxBaseSpecifier(...)
-matching public virtual X.
-
-Given
+Example matches class Derived
+(matcher = cxxRecordDecl(hasAnyBase(hasType(cxxRecordDecl(hasName("Base"))))))
class Base {};
class Derived : Base {};
-The matcher
-cxxRecordDecl(hasAnyBase(hasType(cxxRecordDecl(hasName("Base")))))
-matches class Derived : Base {}.
-
Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FriendDecl.html">FriendDecl</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>>,
Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>>
</pre></td></tr>
@@ -13850,25 +10484,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasType3"><pre>Matches if the expression's or declaration's type matches a type
matcher.
-Exmaple
+Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
+ and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
+ and U (matcher = typedefDecl(hasType(asString("int")))
+ and friend class X (matcher = friendDecl(hasType("X"))
+ and public virtual X (matcher = cxxBaseSpecifier(hasType(
+ asString("class X")))
class X {};
void y(X &x) { x; X z; }
typedef int U;
class Y { friend class X; };
class Z : public virtual X {};
-
-The matcher expr(hasType(cxxRecordDecl(hasName("X"))))
-matches x and z.
-The matcher varDecl(hasType(cxxRecordDecl(hasName("X"))))
-matches z
-The matcher typedefDecl(hasType(asString("int")))
-matches typedef int U
-The matcher friendDecl(hasType(asString("class X")))
-matches friend class X
-The matcher cxxRecordDecl(hasAnyBase(cxxBaseSpecifier(hasType(
-asString("X"))).bind("b"))) matches class Z : public virtual X {},
-with cxxBaseSpecifier(...)
-matching public virtual X.
</pre></td></tr>
@@ -13876,13 +10502,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasInitializer0"><pre>Matches a variable declaration that has an initializer expression
that matches the given matcher.
-Given
- int y() { return 0; }
- void foo() {
- int x = y();
- }
-The matcher varDecl(hasInitializer(callExpr()))
-matches x
+Example matches x (matcher = varDecl(hasInitializer(callExpr())))
+ bool y() { return true; }
+ bool x = y();
</pre></td></tr>
@@ -13902,22 +10524,13 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
template <typename T, typename U>
void f(T&& t, U&& u) {}
- void foo() {
- bool B = false;
- f(R, B);
- }
-
-The matcher
-templateSpecializationType(forEachTemplateArgument(isExpr(expr().bind("t_arg"))))
-matches Matrix<int, R * 2, R * 4> twice, with
-expr() matching R * 2 and
-R * 4.
-The matcher
-functionDecl(forEachTemplateArgument(refersToType(qualType().bind("type"))))
-matches the specialization of f twice,
-with qualType() matching
-unsigned and
-bool.
+ bool B = false;
+ f(R, B);
+templateSpecializationType(forEachTemplateArgument(isExpr(expr())))
+ matches twice, with expr() matching 'R * 2' and 'R * 4'
+functionDecl(forEachTemplateArgument(refersToType(builtinType())))
+ matches the specialization f<unsigned, bool> twice, for 'unsigned'
+ and 'bool'
</pre></td></tr>
@@ -13930,11 +10543,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
template<typename T> class A {};
A<int> a;
-
-The matcher
-varDecl(hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
-templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
-hasTypeLoc(loc(asString("int"))))))))) matches A<int> a.
+varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
+ hasTypeLoc(loc(asString("int")))))))
+ matches `A<int> a`.
</pre></td></tr>
@@ -13948,19 +10559,15 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
template<> class A<double> {};
A<int> a;
- template<typename T> void f() {};
+ template<typename T> f() {};
void func() { f<int>(); };
+classTemplateSpecializationDecl(hasAnyTemplateArgument(
+ refersToType(asString("int"))))
+ matches the specialization A<int>
-The matcher classTemplateSpecializationDecl(
- hasAnyTemplateArgument(
- refersToType(asString("int"))))
-matches class A<int>.
-
-The matcher
-functionDecl(hasAnyTemplateArgument(
- refersToType(asString("int"))))
-matches the instantiation of f.
+functionDecl(hasAnyTemplateArgument(refersToType(asString("int"))))
+ matches the specialization f<int>
</pre></td></tr>
@@ -13973,12 +10580,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
template<typename T, typename U> class A {};
A<double, int> b;
A<int, double> c;
-
-The matcher
-varDecl(hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
-templateSpecializationTypeLoc(hasTemplateArgumentLoc(0,
-hasTypeLoc(loc(asString("double")))))))))
-matches A<double, int> b, but not double> c}.
+varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(0,
+ hasTypeLoc(loc(asString("double")))))))
+ matches `A<double, int> b`, but not `A<int, double> c`.
</pre></td></tr>
@@ -13989,20 +10593,17 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
Given
template<typename T, typename U> class A {};
- A<double, int> b;
- A<int, double> c;
+ A<bool, int> b;
+ A<int, bool> c;
template<typename T> void f() {}
void func() { f<int>(); };
-
-The matcher
classTemplateSpecializationDecl(hasTemplateArgument(
1, refersToType(asString("int"))))
-matches the specialization class A<double, int>.
+ matches the specialization A<bool, int>
-The matcher functionDecl(hasTemplateArgument(0,
- refersToType(asString("int"))))
-matches the specialization of f.
+functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))
+ matches the specialization f<int>
</pre></td></tr>
@@ -14014,10 +10615,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
void f(int b) {
int a[b];
}
-The matcher
variableArrayType(hasSizeExpr(ignoringImpCasts(declRefExpr(to(
varDecl(hasName("b")))))))
-matches int[b]
+ matches "int a[b]"
</pre></td></tr>
@@ -14028,22 +10628,20 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
other declarations of the same function or coroutine.
Given
-void foo() {
for (;;) {}
-}
-The matcher forStmt(hasBody(compoundStmt().bind("body")))
-matches for (;;) {}
+forStmt(hasBody(compoundStmt()))
+ matches 'for (;;) {}'
with compoundStmt()
- matching {}
+ matching '{}'
Given
void f();
void f() {}
-The matcher functionDecl(hasBody(compoundStmt().bind("compound")))
-f
+functionDecl(hasBody(compoundStmt()))
+ matches 'void f() {}'
with compoundStmt()
-matching {}
-but does not match void f();
+ matching '{}'
+ but does not match 'void f();'
</pre></td></tr>
@@ -14051,13 +10649,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasCondition2"><pre>Matches the condition expression of an if statement, for loop,
switch statement or conditional operator.
-Given
-void foo() {
+Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
if (true) {}
-}
-
-The matcher ifStmt(hasCondition(cxxBoolLiteral(equals(true))))
-if (true) {}
</pre></td></tr>
<!--END_TRAVERSAL_MATCHERS -->
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f9ab34a3f3cf3d..a8830a5658c7da 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -858,9 +858,6 @@ AST Matchers
- Ensure ``hasName`` matches template specializations across inline namespaces,
making `matchesNodeFullSlow` and `matchesNodeFullFast` consistent.
-- The examples in the AST matcher reference are now tested and additional
- examples and descriptions were added.
-
clang-format
------------
diff --git a/clang/docs/doxygen.cfg.in b/clang/docs/doxygen.cfg.in
index 1d1deb0fcfb07b..251afb179b2055 100644
--- a/clang/docs/doxygen.cfg.in
+++ b/clang/docs/doxygen.cfg.in
@@ -220,14 +220,7 @@ TAB_SIZE = 2
# "Side Effects:". You can put \n's in the value part of an alias to insert
# newlines.
-ALIASES += compile_args{1}="Compiled with <tt>\1</tt>.\n"
-ALIASES += matcher{1}="<tt>\1</tt>"
-ALIASES += matcher{2$}="<tt>\2</tt>"
-ALIASES += match{1}="<tt>\1</tt>"
-ALIASES += match{2$}="<tt>\2</tt>"
-ALIASES += nomatch{1}="<tt>\1</tt>"
-ALIASES += header{1}="\code"
-ALIASES += endheader="\endcode"
+ALIASES =
# This tag can be used to specify a number of word-keyword mappings (TCL only).
# A mapping has the form "name=value". For example adding "class=itcl::class"
diff --git a/clang/docs/tools/dump_ast_matchers.py b/clang/docs/tools/dump_ast_matchers.py
index a3feac8728c653..705ff0d4d40985 100755
--- a/clang/docs/tools/dump_ast_matchers.py
+++ b/clang/docs/tools/dump_ast_matchers.py
@@ -100,72 +100,15 @@ def extract_result_types(comment):
comment = m.group(1)
-def find_next_closing_rbrace(
- data: str, start_pos: int, braces_to_be_matched: int
-) -> int:
- """Finds the location of the closing rbrace '}' inside of data."""
- """'start_pos' should be one past the opening lbrace and braces_to_be_matched is initialized with 0"""
- next_lbrace = data.find("{", start_pos)
- next_rbrace = data.find("}", start_pos)
- if next_lbrace != -1:
- if next_lbrace < next_rbrace:
- return find_next_closing_rbrace(
- data, next_lbrace + 1, braces_to_be_matched + 1
- )
- if braces_to_be_matched == 0:
- return next_rbrace
- return find_next_closing_rbrace(data, next_rbrace + 1, braces_to_be_matched - 1)
-
- if braces_to_be_matched > 0:
- return find_next_closing_rbrace(data, next_rbrace + 1, braces_to_be_matched - 1)
-
- return next_rbrace
-
-
def strip_doxygen(comment):
"""Returns the given comment without \-escaped words."""
+ # If there is only a doxygen keyword in the line, delete the whole line.
+ comment = re.sub(r"^\\[^\s]+\n", r"", comment, flags=re.M)
+
# If there is a doxygen \see command, change the \see prefix into "See also:".
# FIXME: it would be better to turn this into a link to the target instead.
comment = re.sub(r"\\see", r"See also:", comment)
- commands: list[str] = [
- "\\compile_args{",
- "\\matcher{",
- "\\match{",
- "\\nomatch{",
- ]
-
- for command in commands:
- delete_command = command == "\\compile_args{"
- command_begin_loc = comment.find(command)
- while command_begin_loc != -1:
- command_end_loc = command_begin_loc + len(command)
- end_brace_loc = find_next_closing_rbrace(comment, command_end_loc + 1, 0)
- if end_brace_loc == -1:
- print("found unmatched {")
- command_begin_loc = comment.find(command, command_end_loc)
- continue
-
- if delete_command:
- comment = comment[0:command_begin_loc] + comment[end_brace_loc + 1 :]
- command_begin_loc = comment.find(command, command_begin_loc)
- continue
-
- tag_seperator_loc = comment.find("$", command_end_loc)
- if tag_seperator_loc != -1 and tag_seperator_loc < end_brace_loc:
- command_end_loc = tag_seperator_loc + 1
-
- comment = (
- comment[0:command_begin_loc]
- + comment[command_end_loc:end_brace_loc]
- + comment[end_brace_loc + 1 :]
- )
-
- command_begin_loc = comment.find(command, command_begin_loc)
-
- # If there is only a doxygen keyword in the line, delete the whole line.
- comment = re.sub(r"^\\[^\s]+\n", r"", comment, flags=re.M)
-
# Delete the doxygen command and the following whitespace.
comment = re.sub(r"\\[^\s]+\s+", r"", comment)
return comment
@@ -248,9 +191,8 @@ def act_on_decl(declaration, comment, allowed_types):
definition.
"""
if declaration.strip():
- if re.match(
- r"^\s?(#|namespace|using|template <typename NodeType> using|})", declaration
- ):
+
+ if re.match(r"^\s?(#|namespace|using|template <typename NodeType> using|})", declaration):
return
# Node matchers are defined by writing:
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index 1898d53a503283..4bcaa953a61af2 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -39,158 +39,6 @@
// See ASTMatchFinder.h for how to use the generated matchers to run over
// an AST.
//
-// The doxygen comments on matchers are used to:
-// - create the doxygen documentation
-// - get information in the editor via signature help and goto definition
-// - generate the AST matcher reference html file
-// - test the documentation using a special syntax
-//
-// Test Annotations:
-//
-// The automatic testing uses doxygen commands (aliases) to extract the
-// relevant information about an example of using a matcher from the
-// documentation.
-//
-// \header{a.h}
-// \endheader <- zero or more header
-//
-// \code
-// int a = 42;
-// \endcode
-// \compile_args{-std=c++,c23-or-later} <- optional, the std flag supports
-// std ranges and
-// whole languages
-//
-// \matcher{expr()} <- one or more matchers in succession
-// \matcher{integerLiteral()} <- one or more matchers in succession
-// both matcher will have to match the
-// following matches
-// \match{42} <- one or more matches in succession
-//
-// \matcher{varDecl()} <- new matcher resets the context, the above
-// \match will not count for this new
-// matcher(-group)
-// \match{int a = 42} <- only applies to the previous matcher (not to the
-// previous case)
-//
-//
-// The above block can be repeated inside a doxygen command for multiple code
-// examples for a single matcher. The test generation script will only look for
-// these annotations and ignore anything else like `\c` or the sentences where
-// these annotations are embedded into: `The matcher \matcher{expr()} matches
-// the number \match{42}.`.
-//
-// Language Grammar:
-//
-// [] denotes an optional, and <> denotes user-input
-//
-// compile_args j:= \compile_args{[<compile_arg>;]<compile_arg>}
-// matcher_tag_key ::= type
-// match_tag_key ::= type || std || count || sub
-// matcher_tags ::= [matcher_tag_key=<value>;]matcher_tag_key=<value>
-// match_tags ::= [match_tag_key=<value>;]match_tag_key=<value>
-// matcher ::= \matcher{[matcher_tags$]<matcher>}
-// matchers ::= [matcher] matcher
-// match ::= \match{[match_tags$]<match>}
-// matches ::= [match] match
-// case ::= matchers matches
-// cases ::= [case] case
-// header-block ::= \header{<name>} <code> \endheader
-// code-block ::= \code <code> \endcode
-// testcase ::= code-block [compile_args] cases
-//
-// Language Standard Versions:
-//
-// The 'std' tag and '\compile_args' support specifying a specific language
-// version, a whole language and all of its versions, and thresholds (implies
-// ranges). Multiple arguments are passed with a ',' separator. For a language
-// and version to execute a tested matcher, it has to match the specified
-// '\compile_args' for the code, and the 'std' tag for the matcher. Predicates
-// for the 'std' compiler flag are used with disjunction between languages
-// (e.g. 'c || c++') and conjunction for all predicates specific to each
-// language (e.g. 'c++11-or-later && c++23-or-earlier').
-//
-// Examples:
-// - `c` all available versions of C
-// - `c++11` only C++11
-// - `c++11-or-later` C++11 or later
-// - `c++11-or-earlier` C++11 or earlier
-// - `c++11-or-later,c++23-or-earlier,c` all of C and C++ between 11 and
-// 23 (inclusive)
-// - `c++11-23,c` same as above
-//
-// Tags
-//
-// `type`:
-// **Match types** are used to select where the string that is used to check if
-// a node matches comes from. Available: `code`, `name`, `typestr`,
-// `typeofstr`. The default is `code`.
-//
-// - `code`: Forwards to `tooling::fixit::getText(...)` and should be the
-// preferred way to show what matches.
-// - `name`: Casts the match to a `NamedDecl` and returns the result of
-// `getNameAsString`. Useful when the matched AST node is not easy to spell
-// out (`code` type), e.g., namespaces or classes with many members.
-// - `typestr`: Returns the result of `QualType::getAsString` for the type
-// derived from `Type` (otherwise, if it is derived from `Decl`, recurses with
-// `Node->getTypeForDecl()`)
-//
-// **Matcher types** are used to mark matchers as sub-matcher with 'sub' or as
-// deactivated using 'none'. Testing sub-matcher is not implemented.
-//
-// `count`:
-// Specifying a 'count=n' on a match will result in a test that requires that
-// the specified match will be matched n times. Default is 1.
-//
-// `std`:
-// A match allows specifying if it matches only in specific language versions.
-// This may be needed when the AST differs between language versions.
-//
-// `sub`:
-// The `sub` tag on a `\match` will indicate that the match is for a node of a
-// bound sub-matcher. E.g., `\matcher{expr(expr().bind("inner"))}` has a
-// sub-matcher that binds to `inner`, which is the value for the `sub` tag of
-// the expected match for the sub-matcher `\match{sub=inner$...}`. Currently,
-// sub-matchers are not tested in any way.
-//
-//
-// What if ...?
-//
-// ... I want to add a matcher?
-//
-// Add a doxygen comment to the matcher with a code example, corresponding
-// matchers and matches, that shows what the matcher is supposed to do. Specify
-// the compile arguments/supported languages if required, and run `ninja
-// check-clang-unit` to test the documentation.
-//
-// ... the example I wrote is wrong?
-//
-// The test-failure output of the generated test file will provide information
-// about
-// - where the generated test file is located
-// - which line in `ASTMatcher.h` the example is from
-// - which matches were: found, not-(yet)-found, expected
-// - in case of an unexpected match: what the node looks like using the
-// different `type`s
-// - the language version and if the test ran with a windows `-target` flag
-// (also in failure summary)
-//
-// ... I don't adhere to the required order of the syntax?
-//
-// The script will diagnose any found issues, such as `matcher is missing an
-// example` with a `file:line:` prefix, which should provide enough information
-// about the issue.
-//
-// ... the script diagnoses a false-positive issue with a doxygen comment?
-//
-// It hopefully shouldn't, but if you, e.g., added some non-matcher code and
-// documented it with doxygen, then the script will consider that as a matcher
-// documentation. As a result, the script will print that it detected a
-// mismatch between the actual and the expected number of failures. If the
-// diagnostic truly is a false-positive, change the
-// `expected_failure_statistics` at the top of the
-// `generate_ast_matcher_doc_tests.py` file.
-//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERS_H
@@ -312,13 +160,13 @@ using AttrMatcher = internal::Matcher<Attr>;
/// additional constraint. This will often be used with an explicit conversion
/// to an \c internal::Matcher<> type such as \c TypeMatcher.
///
-/// Given
+/// Example: \c DeclarationMatcher(anything()) matches all declarations, e.g.,
/// \code
+/// "int* p" and "void f()" in
/// int* p;
/// void f();
/// \endcode
-/// The matcher \matcher{decl(anything())}
-/// matches \match{int* p} and \match{void f()}.
+///
/// Usable as: Any Matcher
inline internal::TrueMatcher anything() { return internal::TrueMatcher(); }
@@ -327,13 +175,12 @@ inline internal::TrueMatcher anything() { return internal::TrueMatcher(); }
/// Given
/// \code
/// int X;
-/// namespace NS { int Y; }
+/// namespace NS {
+/// int Y;
+/// } // namespace NS
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{namedDecl(hasDeclContext(translationUnitDecl()))}
-/// matches \match{int X} and \match{namespace NS { int Y; }},
-/// but does not match \nomatch{int Y} because its decl-context is the
-/// namespace \c NS .
+/// decl(hasDeclContext(translationUnitDecl()))
+/// matches "int X", but not "int Y".
extern const internal::VariadicDynCastAllOfMatcher<Decl, TranslationUnitDecl>
translationUnitDecl;
@@ -344,10 +191,8 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, TranslationUnitDecl>
/// typedef int X;
/// using Y = int;
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{typedefDecl()}
-/// matches \match{typedef int X},
-/// but does not match \nomatch{using Y = int}.
+/// typedefDecl()
+/// matches "typedef int X", but not "using Y = int"
extern const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl>
typedefDecl;
@@ -358,9 +203,8 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl>
/// typedef int X;
/// using Y = int;
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{typedefNameDecl()}
-/// matches \match{typedef int X} and \match{using Y = int}.
+/// typedefNameDecl()
+/// matches "typedef int X" and "using Y = int"
extern const internal::VariadicDynCastAllOfMatcher<Decl, TypedefNameDecl>
typedefNameDecl;
@@ -371,44 +215,33 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, TypedefNameDecl>
/// typedef int X;
/// using Y = int;
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{typeAliasDecl()}
-/// matches \match{using Y = int},
-/// but does not match \nomatch{typedef int X}.
+/// typeAliasDecl()
+/// matches "using Y = int", but not "typedef int X"
extern const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasDecl>
typeAliasDecl;
/// Matches type alias template declarations.
///
-/// Given
+/// typeAliasTemplateDecl() matches
/// \code
-/// template <typename T> struct X {};
-/// template <typename T> using Y = X<T>;
+/// template <typename T>
+/// using Y = X<T>;
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{typeAliasTemplateDecl()}
-/// matches \match{template <typename T> using Y = X<T>}.
extern const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasTemplateDecl>
typeAliasTemplateDecl;
/// Matches AST nodes that were expanded within the main-file.
///
-/// Given the header \c Y.h
-/// \header{Y.h}
-/// #pragma once
-/// typedef int my_header_int;
-/// \endheader
-/// and the source file
+/// Example matches X but not Y
+/// (matcher = cxxRecordDecl(isExpansionInMainFile())
/// \code
-/// #include "Y.h"
-/// typedef int my_main_file_int;
-/// my_main_file_int a = 0;
-/// my_header_int b = 1;
+/// #include <Y.h>
+/// class X {};
+/// \endcode
+/// Y.h:
+/// \code
+/// class Y {};
/// \endcode
-///
-/// The matcher \matcher{typedefDecl(isExpansionInMainFile())}
-/// matches \match{typedef int my_main_file_int},
-/// but does not match \nomatch{typedef int my_header_int}.
///
/// Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
AST_POLYMORPHIC_MATCHER(isExpansionInMainFile,
@@ -420,21 +253,16 @@ AST_POLYMORPHIC_MATCHER(isExpansionInMainFile,
/// Matches AST nodes that were expanded within system-header-files.
///
-/// Given the header \c SystemHeader.h
-/// \header{system_include/SystemHeader.h}
-/// #pragma once
-/// int header();
-/// \endheader
-/// and the source code
+/// Example matches Y but not X
+/// (matcher = cxxRecordDecl(isExpansionInSystemHeader())
/// \code
/// #include <SystemHeader.h>
-/// static int main_file();
+/// class X {};
+/// \endcode
+/// SystemHeader.h:
+/// \code
+/// class Y {};
/// \endcode
-/// \compile_args{-isystemsystem_include/}
-///
-/// The matcher \matcher{type=none$functionDecl(isExpansionInSystemHeader())}
-/// matches \match{int header()},
-/// but does not match \nomatch{static int main_file()}.
///
/// Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
AST_POLYMORPHIC_MATCHER(isExpansionInSystemHeader,
@@ -450,31 +278,16 @@ AST_POLYMORPHIC_MATCHER(isExpansionInSystemHeader,
/// Matches AST nodes that were expanded within files whose name is
/// partially matching a given regex.
///
-/// Given the headers \c Y.h
-/// \header{Y.h}
-/// #pragma once
-/// typedef int my_y_int;
-/// \endheader
-/// and \c X.h
-/// \header{X.h}
-/// #pragma once
-/// typedef int my_x_int;
-/// \endheader
-/// and the source code
-/// \code
-/// #include "X.h"
-/// #include "Y.h"
-/// typedef int my_main_file_int;
-/// my_main_file_int a = 0;
-/// my_x_int b = 1;
-/// my_y_int c = 2;
+/// Example matches Y but not X
+/// (matcher = cxxRecordDecl(isExpansionInFileMatching("AST.*"))
+/// \code
+/// #include "ASTMatcher.h"
+/// class X {};
+/// \endcode
+/// ASTMatcher.h:
+/// \code
+/// class Y {};
/// \endcode
-///
-/// The matcher
-/// \matcher{type=none$typedefDecl(isExpansionInFileMatching("Y.h"))}
-/// matches \match{typedef int my_y_int},
-/// but does not match \nomatch{typedef int my_main_file_int} or
-/// \nomatch{typedef int my_x_int}.
///
/// Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
AST_POLYMORPHIC_MATCHER_REGEX(isExpansionInFileMatching,
@@ -500,17 +313,6 @@ AST_POLYMORPHIC_MATCHER_REGEX(isExpansionInFileMatching,
/// Does not match if only part of the statement is expanded from that macro or
/// if different parts of the statement are expanded from different
/// appearances of the macro.
-///
-/// Given
-/// \code
-/// #define A 0
-/// #define B A
-/// int c = B;
-/// \endcode
-///
-/// The matcher \matcher{integerLiteral(isExpandedFromMacro("A"))}
-/// matches the literal expanded at the initializer \match{B} of the variable
-/// \c c .
AST_POLYMORPHIC_MATCHER_P(isExpandedFromMacro,
AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Stmt, TypeLoc),
std::string, MacroName) {
@@ -528,50 +330,35 @@ AST_POLYMORPHIC_MATCHER_P(isExpandedFromMacro,
/// Matches declarations.
///
-/// Given
+/// Examples matches \c X, \c C, and the friend declaration inside \c C;
/// \code
/// void X();
/// class C {
-/// friend void X();
+/// friend X;
/// };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{decl()}
-/// matches \match{void X()} once, \match{type=name;count=2$C}
-/// twice, once for the definition and once for the implicit class declaration,
-/// and \match{count=2$friend void X()} twice, once for the declaration of the
-/// friend, and once for the redeclaration of the function itself.
extern const internal::VariadicAllOfMatcher<Decl> decl;
/// Matches decomposition-declarations.
///
-/// Given
+/// Examples matches the declaration node with \c foo and \c bar, but not
+/// \c number.
+/// (matcher = declStmt(has(decompositionDecl())))
+///
/// \code
-/// struct pair { int x; int y; };
-/// pair make(int, int);
/// int number = 42;
-/// auto [foo, bar] = make(42, 42);
+/// auto [foo, bar] = std::make_pair{42, 42};
/// \endcode
-/// \compile_args{-std=c++17-or-later}
-/// The matcher \matcher{decompositionDecl()}
-/// matches \match{auto [foo, bar] = make(42, 42)},
-/// but does not match \nomatch{type=name$number}.
extern const internal::VariadicDynCastAllOfMatcher<Decl, DecompositionDecl>
decompositionDecl;
/// Matches binding declarations
+/// Example matches \c foo and \c bar
+/// (matcher = bindingDecl()
///
-/// Given
/// \code
-/// struct pair { int x; int y; };
-/// pair make(int, int);
-/// void f() {
-/// auto [foo, bar] = make(42, 42);
-/// }
+/// auto [foo, bar] = std::make_pair{42, 42};
/// \endcode
-/// \compile_args{-std=c++17-or-later}
-/// The matcher \matcher{bindingDecl()}
-/// matches \match{type=name$foo} and \match{type=name$bar}.
extern const internal::VariadicDynCastAllOfMatcher<Decl, BindingDecl>
bindingDecl;
@@ -581,41 +368,33 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, BindingDecl>
/// \code
/// extern "C" {}
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{linkageSpecDecl()}
-/// matches \match{extern "C" {}}.
+/// linkageSpecDecl()
+/// matches "extern "C" {}"
extern const internal::VariadicDynCastAllOfMatcher<Decl, LinkageSpecDecl>
linkageSpecDecl;
/// Matches a declaration of anything that could have a name.
///
/// Example matches \c X, \c S, the anonymous union type, \c i, and \c U;
-/// Given
/// \code
/// typedef int X;
-/// struct S { union { int i; } U; };
-/// \endcode
-/// The matcher \matcher{namedDecl()}
-/// matches \match{typedef int X},
-/// \match{std=c$struct S { union { int i; } U; }}, \match{int i},
-/// the unnamed union\match{type=name$} and the variable
-/// \match{union { int i; } U},
-/// with \match{type=name;count=2;std=c++$S} matching twice in C++.
-/// Once for the implicit class declaration and once for the declaration itself.
+/// struct S {
+/// union {
+/// int i;
+/// } U;
+/// };
+/// \endcode
extern const internal::VariadicDynCastAllOfMatcher<Decl, NamedDecl> namedDecl;
/// Matches a declaration of label.
///
/// Given
/// \code
-/// void bar();
-/// void foo() {
-/// goto FOO;
-/// FOO: bar();
-/// }
+/// goto FOO;
+/// FOO: bar();
/// \endcode
-/// The matcher \matcher{type=none$labelDecl()}
-/// matches \match{FOO: bar()}.
+/// labelDecl()
+/// matches 'FOO:'
extern const internal::VariadicDynCastAllOfMatcher<Decl, LabelDecl> labelDecl;
/// Matches a declaration of a namespace.
@@ -625,9 +404,8 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, LabelDecl> labelDecl;
/// namespace {}
/// namespace test {}
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{namespaceDecl()}
-/// matches \match{namespace {}} and \match{namespace test {}}.
+/// namespaceDecl()
+/// matches "namespace {}" and "namespace test {}"
extern const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceDecl>
namespaceDecl;
@@ -638,53 +416,38 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceDecl>
/// namespace test {}
/// namespace alias = ::test;
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{namespaceAliasDecl()}
-/// matches \match{namespace alias = ::test},
-/// but does not match \nomatch{namespace test {}}.
+/// namespaceAliasDecl()
+/// matches "namespace alias" but not "namespace test"
extern const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceAliasDecl>
namespaceAliasDecl;
/// Matches class, struct, and union declarations.
///
-/// Given
+/// Example matches \c X, \c Z, \c U, and \c S
/// \code
/// class X;
/// template<class T> class Z {};
/// struct S {};
/// union U {};
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{recordDecl()}
-/// matches \match{class X} once, and the rest of the declared records twice,
-/// once for their written definition and once for their implicit declaration:
-/// \match{type=name;count=2$Z}, \match{type=name;count=2$S} and
-/// \match{type=name;count=2$U}.
extern const internal::VariadicDynCastAllOfMatcher<Decl, RecordDecl> recordDecl;
/// Matches C++ class declarations.
///
-/// Given
+/// Example matches \c X, \c Z
/// \code
/// class X;
/// template<class T> class Z {};
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{cxxRecordDecl()}
-/// matches \match{class X} once, and \match{type=name;count=2$Z} twice,
-/// once for the written definition and once for the implicit declaration.
extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXRecordDecl>
cxxRecordDecl;
/// Matches C++ class template declarations.
///
-/// Given
+/// Example matches \c Z
/// \code
/// template<class T> class Z {};
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{classTemplateDecl()}
-/// matches \match{template<class T> class Z {}}.
extern const internal::VariadicDynCastAllOfMatcher<Decl, ClassTemplateDecl>
classTemplateDecl;
@@ -696,10 +459,8 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ClassTemplateDecl>
/// template<> class A<double> {};
/// A<int> a;
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{classTemplateSpecializationDecl()}
-/// matches \match{type=typestr$class A<int>}
-/// and \match{type=typestr$class A<double>}.
+/// classTemplateSpecializationDecl()
+/// matches the specializations \c A<int> and \c A<double>
extern const internal::VariadicDynCastAllOfMatcher<
Decl, ClassTemplateSpecializationDecl>
classTemplateSpecializationDecl;
@@ -711,15 +472,14 @@ extern const internal::VariadicDynCastAllOfMatcher<
/// template<class T1, class T2, int I>
/// class A {};
///
-/// template<class T, int I> class A<T, T*, I> {};
+/// template<class T, int I>
+/// class A<T, T*, I> {};
///
/// template<>
/// class A<int, int, 1> {};
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{classTemplatePartialSpecializationDecl()}
-/// matches \match{template<class T, int I> class A<T, T*, I> {}},
-/// but does not match \nomatch{A<int, int, 1>}.
+/// classTemplatePartialSpecializationDecl()
+/// matches the specialization \c A<T,T*,I> but not \c A<int,int,1>
extern const internal::VariadicDynCastAllOfMatcher<
Decl, ClassTemplatePartialSpecializationDecl>
classTemplatePartialSpecializationDecl;
@@ -731,9 +491,8 @@ extern const internal::VariadicDynCastAllOfMatcher<
/// \code
/// class X { int y; };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{declaratorDecl()}
-/// matches \match{int y}.
+/// declaratorDecl()
+/// matches \c int y.
extern const internal::VariadicDynCastAllOfMatcher<Decl, DeclaratorDecl>
declaratorDecl;
@@ -743,8 +502,8 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, DeclaratorDecl>
/// \code
/// void f(int x);
/// \endcode
-/// The matcher \matcher{parmVarDecl()}
-/// matches \match{int x}.
+/// parmVarDecl()
+/// matches \c int x.
extern const internal::VariadicDynCastAllOfMatcher<Decl, ParmVarDecl>
parmVarDecl;
@@ -757,36 +516,29 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ParmVarDecl>
/// int a;
/// };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{accessSpecDecl()}
-/// matches \match{public:}.
+/// accessSpecDecl()
+/// matches 'public:'
extern const internal::VariadicDynCastAllOfMatcher<Decl, AccessSpecDecl>
accessSpecDecl;
/// Matches class bases.
///
-/// Given
+/// Examples matches \c public virtual B.
/// \code
/// class B {};
-/// class C : public B {};
+/// class C : public virtual B {};
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxRecordDecl(hasDirectBase(cxxBaseSpecifier()))}
-/// matches \match{class C : public B {}}.
extern const internal::VariadicAllOfMatcher<CXXBaseSpecifier> cxxBaseSpecifier;
/// Matches constructor initializers.
///
-/// Given
+/// Examples matches \c i(42).
/// \code
/// class C {
/// C() : i(42) {}
/// int i;
/// };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxCtorInitializer()}
-/// matches \match{i(42)}.
extern const internal::VariadicAllOfMatcher<CXXCtorInitializer>
cxxCtorInitializer;
@@ -797,10 +549,8 @@ extern const internal::VariadicAllOfMatcher<CXXCtorInitializer>
/// template <typename T> struct C {};
/// C<int> c;
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher
-/// \matcher{templateSpecializationType(hasAnyTemplateArgument(templateArgument()))}
-/// matches \match{type=typestr$C<int>}.
+/// templateArgument()
+/// matches 'int' in C<int>.
extern const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument;
/// Matches template arguments (with location info).
@@ -810,9 +560,8 @@ extern const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument;
/// template <typename T> struct C {};
/// C<int> c;
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{templateArgumentLoc()}
-/// matches \match{int} in C<int>.
+/// templateArgumentLoc()
+/// matches 'int' in C<int>.
extern const internal::VariadicAllOfMatcher<TemplateArgumentLoc>
templateArgumentLoc;
@@ -820,15 +569,11 @@ extern const internal::VariadicAllOfMatcher<TemplateArgumentLoc>
///
/// Given
/// \code
-/// template<template <typename> class S> class X {};
-/// template<typename T> class Y {};
-/// X<Y> xi;
+/// template <typename T> class X { };
+/// X<int> xi;
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher
-/// \matcher{classTemplateSpecializationDecl(hasAnyTemplateArgument(
-/// refersToTemplate(templateName())))}
-/// matches the specialization \match{type=typestr$class X<Y>}
+/// templateName()
+/// matches 'X' in X<int>.
extern const internal::VariadicAllOfMatcher<TemplateName> templateName;
/// Matches non-type template parameter declarations.
@@ -837,10 +582,8 @@ extern const internal::VariadicAllOfMatcher<TemplateName> templateName;
/// \code
/// template <typename T, int N> struct C {};
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{nonTypeTemplateParmDecl()}
-/// matches \match{int N},
-/// but does not match \nomatch{typename T}.
+/// nonTypeTemplateParmDecl()
+/// matches 'N', but not 'T'.
extern const internal::VariadicDynCastAllOfMatcher<Decl,
NonTypeTemplateParmDecl>
nonTypeTemplateParmDecl;
@@ -851,10 +594,8 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl,
/// \code
/// template <typename T, int N> struct C {};
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{templateTypeParmDecl()}
-/// matches \match{typename T},
-/// but does not \nomatch{int N}.
+/// templateTypeParmDecl()
+/// matches 'T', but not 'N'.
extern const internal::VariadicDynCastAllOfMatcher<Decl, TemplateTypeParmDecl>
templateTypeParmDecl;
@@ -864,10 +605,8 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, TemplateTypeParmDecl>
/// \code
/// template <template <typename> class Z, int N> struct C {};
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{templateTemplateParmDecl()}
-/// matches \match{template <typename> class Z},
-/// but does not match \nomatch{int N}.
+/// templateTypeParmDecl()
+/// matches 'Z', but not 'N'.
extern const internal::VariadicDynCastAllOfMatcher<Decl,
TemplateTemplateParmDecl>
templateTemplateParmDecl;
@@ -875,31 +614,20 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl,
/// Matches public C++ declarations and C++ base specifers that specify public
/// inheritance.
///
-/// Given
+/// Examples:
/// \code
/// class C {
-/// public: int a;
+/// public: int a; // fieldDecl(isPublic()) matches 'a'
/// protected: int b;
/// private: int c;
/// };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{fieldDecl(isPublic())}
-/// matches \match{int a}.
///
-/// Given
/// \code
/// class Base {};
-/// class Derived1 : public Base {};
-/// struct Derived2 : Base {};
+/// class Derived1 : public Base {}; // matches 'Base'
+/// struct Derived2 : Base {}; // matches 'Base'
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{cxxRecordDecl(hasAnyBase(cxxBaseSpecifier(isPublic()).bind("base")))}
-/// matches \match{class Derived1 : public Base {}} and
-/// \match{struct Derived2 : Base {}},
-/// with \matcher{type=sub$cxxBaseSpecifier(isPublic())} matching
-/// \match{sub=base$public Base} and \match{sub=base$Base}.
AST_POLYMORPHIC_MATCHER(isPublic,
AST_POLYMORPHIC_SUPPORTED_TYPES(Decl,
CXXBaseSpecifier)) {
@@ -909,28 +637,19 @@ AST_POLYMORPHIC_MATCHER(isPublic,
/// Matches protected C++ declarations and C++ base specifers that specify
/// protected inheritance.
///
-/// Given
+/// Examples:
/// \code
/// class C {
/// public: int a;
-/// protected: int b;
+/// protected: int b; // fieldDecl(isProtected()) matches 'b'
/// private: int c;
/// };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{fieldDecl(isProtected())}
-/// matches \match{int b}.
///
/// \code
/// class Base {};
-/// class Derived : protected Base {};
+/// class Derived : protected Base {}; // matches 'Base'
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{cxxRecordDecl(hasAnyBase(cxxBaseSpecifier(isProtected()).bind("base")))}
-/// matches \match{class Derived : protected Base {}}, with
-/// \matcher{type=sub$cxxBaseSpecifier(isProtected())} matching
-/// \match{sub=base$Base}.
AST_POLYMORPHIC_MATCHER(isProtected,
AST_POLYMORPHIC_SUPPORTED_TYPES(Decl,
CXXBaseSpecifier)) {
@@ -940,30 +659,20 @@ AST_POLYMORPHIC_MATCHER(isProtected,
/// Matches private C++ declarations and C++ base specifers that specify private
/// inheritance.
///
-/// Given
+/// Examples:
/// \code
/// class C {
/// public: int a;
/// protected: int b;
-/// private: int c;
+/// private: int c; // fieldDecl(isPrivate()) matches 'c'
/// };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{fieldDecl(isPrivate())}
-/// matches \match{int c}.
///
/// \code
/// struct Base {};
-/// struct Derived1 : private Base {}; // \match{Base}
-/// class Derived2 : Base {}; // \match{Base}
+/// struct Derived1 : private Base {}; // matches 'Base'
+/// class Derived2 : Base {}; // matches 'Base'
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{cxxRecordDecl(hasAnyBase(cxxBaseSpecifier(isPrivate()).bind("base")))}
-/// matches \match{struct Derived1 : private Base {}} and
-/// \match{class Derived2 : Base {}}, with
-/// \matcher{type=sub$cxxBaseSpecifier(isPrivate())} matching
-/// \match{sub=base;count=2$Base} each time.
AST_POLYMORPHIC_MATCHER(isPrivate,
AST_POLYMORPHIC_SUPPORTED_TYPES(Decl,
CXXBaseSpecifier)) {
@@ -979,11 +688,11 @@ AST_POLYMORPHIC_MATCHER(isPrivate,
/// int b;
/// };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{fieldDecl(isBitField())}
-/// matches \match{int a : 2},
-/// but does not match \nomatch{int b}.
-AST_MATCHER(FieldDecl, isBitField) { return Node.isBitField(); }
+/// fieldDecl(isBitField())
+/// matches 'int a;' but not 'int b;'.
+AST_MATCHER(FieldDecl, isBitField) {
+ return Node.isBitField();
+}
/// Matches non-static data members that are bit-fields of the specified
/// bit width.
@@ -996,10 +705,8 @@ AST_MATCHER(FieldDecl, isBitField) { return Node.isBitField(); }
/// int c : 2;
/// };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{fieldDecl(hasBitWidth(2))}
-/// matches \match{int a : 2} and \match{int c : 2},
-/// but not \nomatch{int b : 4}.
+/// fieldDecl(hasBitWidth(2))
+/// matches 'int a;' and 'int c;' but not 'int b;'.
AST_MATCHER_P(FieldDecl, hasBitWidth, unsigned, Width) {
return Node.isBitField() &&
Node.getBitWidthValue(Finder->getASTContext()) == Width;
@@ -1015,14 +722,10 @@ AST_MATCHER_P(FieldDecl, hasBitWidth, unsigned, Width) {
/// int c;
/// };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{fieldDecl(hasInClassInitializer(integerLiteral(equals(2))))}
-/// matches \match{int a = 2},
-/// but does not match \nomatch{int b = 3}.
-/// The matcher \matcher{fieldDecl(hasInClassInitializer(anything()))}
-/// matches \match{int a = 2} and \match{int b = 3},
-/// but does not match \nomatch{int c}.
+/// fieldDecl(hasInClassInitializer(integerLiteral(equals(2))))
+/// matches 'int a;' but not 'int b;'.
+/// fieldDecl(hasInClassInitializer(anything()))
+/// matches 'int a;' and 'int b;' but not 'int c;'.
AST_MATCHER_P(FieldDecl, hasInClassInitializer, internal::Matcher<Expr>,
InnerMatcher) {
const Expr *Initializer = Node.getInClassInitializer();
@@ -1032,29 +735,20 @@ AST_MATCHER_P(FieldDecl, hasInClassInitializer, internal::Matcher<Expr>,
/// Determines whether the function is "main", which is the entry point
/// into an executable program.
-///
-/// Given
-/// \code
-/// void f();
-/// int main() {}
-/// \endcode
-///
-/// The matcher \matcher{functionDecl(isMain())} matches \match{int main() {}}.
-AST_MATCHER(FunctionDecl, isMain) { return Node.isMain(); }
+AST_MATCHER(FunctionDecl, isMain) {
+ return Node.isMain();
+}
/// Matches the specialized template of a specialization declaration.
///
/// Given
/// \code
-/// template<typename T> class A {}; // #1
-/// template<> class A<int> {}; // #2
+/// template<typename T> class A {}; #1
+/// template<> class A<int> {}; #2
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher
-/// \matcher{classTemplateSpecializationDecl(hasSpecializedTemplate(classTemplateDecl().bind("ctd")))}
-/// matches \match{template<> class A<int> {}},
-/// with \matcher{type=sub$classTemplateDecl()} matching the class template
-/// declaration \match{sub=ctd$template <typename T> class A {}}.
+/// classTemplateSpecializationDecl(hasSpecializedTemplate(classTemplateDecl()))
+/// matches '#2' with classTemplateDecl() matching the class template
+/// declaration of 'A' at #1.
AST_MATCHER_P(ClassTemplateSpecializationDecl, hasSpecializedTemplate,
internal::Matcher<ClassTemplateDecl>, InnerMatcher) {
const ClassTemplateDecl* Decl = Node.getSpecializedTemplate();
@@ -1064,22 +758,6 @@ AST_MATCHER_P(ClassTemplateSpecializationDecl, hasSpecializedTemplate,
/// Matches an entity that has been implicitly added by the compiler (e.g.
/// implicit default/copy constructors).
-///
-/// Given
-/// \code
-/// struct S {};
-/// void f(S obj) {
-/// S copy = obj;
-/// [&](){ return copy; };
-/// }
-/// \endcode
-/// \compile_args{-std=c++11}
-///
-/// The matcher \matcher{cxxConstructorDecl(isImplicit(), isCopyConstructor())}
-/// matches the implicit copy constructor of \match{S}.
-/// The matcher \matcher{lambdaExpr(forEachLambdaCapture(
-/// lambdaCapture(isImplicit())))} matches \match{[&](){ return copy; }},
-/// because it implicitly captures \c copy .
AST_POLYMORPHIC_MATCHER(isImplicit,
AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Attr,
LambdaCapture)) {
@@ -1096,21 +774,17 @@ AST_POLYMORPHIC_MATCHER(isImplicit,
/// template<> class A<double> {};
/// A<int> a;
///
-/// template<typename T> void f() {};
+/// template<typename T> f() {};
/// void func() { f<int>(); };
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
///
-/// The matcher \matcher{classTemplateSpecializationDecl(
-/// hasAnyTemplateArgument(
-/// refersToType(asString("int"))))}
-/// matches \match{type=typestr$class A<int>}.
+/// \endcode
+/// classTemplateSpecializationDecl(hasAnyTemplateArgument(
+/// refersToType(asString("int"))))
+/// matches the specialization \c A<int>
///
-/// The matcher
-/// \matcher{functionDecl(hasAnyTemplateArgument(
-/// refersToType(asString("int"))))}
-/// matches the instantiation of
-/// \match{void f() {}}.
+/// functionDecl(hasAnyTemplateArgument(refersToType(asString("int"))))
+/// matches the specialization \c f<int>
AST_POLYMORPHIC_MATCHER_P(
hasAnyTemplateArgument,
AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
@@ -1133,10 +807,12 @@ AST_POLYMORPHIC_MATCHER_P(
/// }
/// \endcode
/// The matcher
-/// \matcher{traverse(TK_IgnoreUnlessSpelledInSource,
+/// \code
+/// traverse(TK_IgnoreUnlessSpelledInSource,
/// varDecl(hasInitializer(floatLiteral().bind("init")))
-/// )}
-/// matches \match{int i = 3.0} with "init" bound to \match{sub=init$3.0}.
+/// )
+/// \endcode
+/// matches the variable declaration with "init" bound to the "3.0".
template <typename T>
internal::Matcher<T> traverse(TraversalKind TK,
const internal::Matcher<T> &InnerMatcher) {
@@ -1197,37 +873,25 @@ traverse(TraversalKind TK, const internal::MapAnyOfHelper<T...> &InnerMatcher) {
/// nodes are stripped off.
///
/// Parentheses and explicit casts are not discarded.
-///
/// Given
/// \code
-/// void f(int param) {
-/// int a = 0;
-/// int b = param;
-/// const int c = 0;
-/// const int d = param;
-/// int e = (0U);
-/// int f = (int)0.0;
-/// const int g = ((int)(((0))));
-/// }
+/// class C {};
+/// C a = C();
+/// C b;
+/// C c = b;
/// \endcode
-///
-/// The matcher
-/// \matcher{varDecl(hasInitializer(ignoringImplicit(integerLiteral())))}
-/// matches \match{int a = 0} and \match{const int c = 0},
-/// but not \nomatch{int e = (0U)} and \nomatch{((int)(((0)))}.
-/// The matcher
-/// \matcher{varDecl(hasInitializer(integerLiteral()))}
-/// matches \match{int a = 0} and \match{const int c = 0},
-/// but not \nomatch{int e = (0U)} and \nomatch{((int)(((0)))}.
-///
-/// The matcher
-/// \matcher{varDecl(hasInitializer(ignoringImplicit(declRefExpr())))}
-/// matches \match{int b = param} and \match{const int d = param}.
-/// The matcher
-/// \matcher{varDecl(hasInitializer(declRefExpr()))}
-/// matches neither \nomatch{int b = param} nor \nomatch{const int d = param},
-/// because an l-to-r-value cast happens.
-AST_MATCHER_P(Expr, ignoringImplicit, internal::Matcher<Expr>, InnerMatcher) {
+/// The matchers
+/// \code
+/// varDecl(hasInitializer(ignoringImplicit(cxxConstructExpr())))
+/// \endcode
+/// would match the declarations for a, b, and c.
+/// While
+/// \code
+/// varDecl(hasInitializer(cxxConstructExpr()))
+/// \endcode
+/// only match the declarations for b and c.
+AST_MATCHER_P(Expr, ignoringImplicit, internal::Matcher<Expr>,
+ InnerMatcher) {
return InnerMatcher.matches(*Node.IgnoreImplicit(), Finder, Builder);
}
@@ -1238,32 +902,24 @@ AST_MATCHER_P(Expr, ignoringImplicit, internal::Matcher<Expr>, InnerMatcher) {
/// Given
/// \code
/// int arr[5];
-/// const int a = 0;
+/// int a = 0;
/// char b = 0;
/// const int c = a;
/// int *d = arr;
/// long e = (long) 0l;
/// \endcode
-/// The matcher
-/// \matcher{varDecl(hasInitializer(ignoringImpCasts(integerLiteral())))}
-/// matches \match{const int a = 0} and \match{char b = 0},
-/// but does not match \nomatch{long e = (long) 0l} because of the c-style
-/// case.
-///
-/// The matcher
-/// \matcher{varDecl(hasInitializer(ignoringImpCasts(declRefExpr())))}
-/// matches \match{const int c = a} and \match{int *d = arr}.
-///
-/// The matcher
-/// \matcher{varDecl(hasInitializer(integerLiteral()))}
-/// matches \match{const int a = 0},
-/// but does not match \nomatch{char b = 0} because of the implicit cast to
-/// \c char or \nomatch{long e = (long) 0l} because of the c-style cast.
-///
-/// The matcher \matcher{varDecl(hasInitializer(declRefExpr()))}
-/// does not match \nomatch{const int c = a} because \c a is cast from an
-/// l- to an r-value or \nomatch{int *d = arr} because the array-to-pointer
-/// decay.
+/// The matchers
+/// \code
+/// varDecl(hasInitializer(ignoringImpCasts(integerLiteral())))
+/// varDecl(hasInitializer(ignoringImpCasts(declRefExpr())))
+/// \endcode
+/// would match the declarations for a, b, c, and d, but not e.
+/// While
+/// \code
+/// varDecl(hasInitializer(integerLiteral()))
+/// varDecl(hasInitializer(declRefExpr()))
+/// \endcode
+/// only match the declarations for a.
AST_MATCHER_P(Expr, ignoringImpCasts,
internal::Matcher<Expr>, InnerMatcher) {
return InnerMatcher.matches(*Node.IgnoreImpCasts(), Finder, Builder);
@@ -1280,15 +936,12 @@ AST_MATCHER_P(Expr, ignoringImpCasts,
/// void* c = reinterpret_cast<char*>(0);
/// char d = char(0);
/// \endcode
-/// \compile_args{-std=c++}
/// The matcher
-/// \matcher{varDecl(hasInitializer(ignoringParenCasts(integerLiteral())))}
-/// matches \match{int a = 0}, \match{char b = (0)},
-/// \match{void* c = reinterpret_cast<char*>(0)} and \match{type=name$d}.
-///
-/// The matcher
-/// \matcher{varDecl(hasInitializer(integerLiteral()))}
-/// matches \match{int a = 0}.
+/// varDecl(hasInitializer(ignoringParenCasts(integerLiteral())))
+/// would match the declarations for a, b, c, and d.
+/// while
+/// varDecl(hasInitializer(integerLiteral()))
+/// only match the declaration for a.
AST_MATCHER_P(Expr, ignoringParenCasts, internal::Matcher<Expr>, InnerMatcher) {
return InnerMatcher.matches(*Node.IgnoreParenCasts(), Finder, Builder);
}
@@ -1306,25 +959,14 @@ AST_MATCHER_P(Expr, ignoringParenCasts, internal::Matcher<Expr>, InnerMatcher) {
/// int *d = (arr);
/// long e = ((long) 0l);
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher
-/// \matcher{varDecl(hasInitializer(ignoringParenImpCasts(integerLiteral())))}
-/// matches \match{int a = 0} and \match{char b = (0)},
-/// but does not match \nomatch{long e = ((long) 0l)} because of the c-style
-/// cast.
-///
-/// The matcher
-/// \matcher{varDecl(hasInitializer(ignoringParenImpCasts(declRefExpr())))}
-/// matches \match{const int c = a} and \match{int *d = (arr)}.
-///
-/// The matcher \matcher{varDecl(hasInitializer(integerLiteral()))} matches
-/// \match{int a = 0}, but does not match \nomatch{char b = (0)} or
-/// \nomatch{long e = ((long) 0l)} because of the casts.
-///
-/// The matcher \matcher{varDecl(hasInitializer(declRefExpr()))}
-/// does not match \nomatch{const int c = a} because of the l- to r-value cast,
-/// or \nomatch{int *d = (arr)} because of the array-to-pointer decay.
+/// The matchers
+/// varDecl(hasInitializer(ignoringParenImpCasts(integerLiteral())))
+/// varDecl(hasInitializer(ignoringParenImpCasts(declRefExpr())))
+/// would match the declarations for a, b, c, and d, but not e.
+/// while
+/// varDecl(hasInitializer(integerLiteral()))
+/// varDecl(hasInitializer(declRefExpr()))
+/// would only match the declaration for a.
AST_MATCHER_P(Expr, ignoringParenImpCasts,
internal::Matcher<Expr>, InnerMatcher) {
return InnerMatcher.matches(*Node.IgnoreParenImpCasts(), Finder, Builder);
@@ -1337,8 +979,10 @@ AST_MATCHER_P(Expr, ignoringParenImpCasts,
/// void (*fp)(void);
/// \endcode
/// The matcher
-/// \matcher{varDecl(hasType(pointerType(pointee(ignoringParens(functionType())))))}
-/// matches \match{void (*fp)(void)}.
+/// \code
+/// varDecl(hasType(pointerType(pointee(ignoringParens(functionType())))))
+/// \endcode
+/// would match the declaration for fp.
AST_MATCHER_P_OVERLOAD(QualType, ignoringParens, internal::Matcher<QualType>,
InnerMatcher, 0) {
return InnerMatcher.matches(Node.IgnoreParens(), Finder, Builder);
@@ -1351,9 +995,10 @@ AST_MATCHER_P_OVERLOAD(QualType, ignoringParens, internal::Matcher<QualType>,
/// const char* str = ("my-string");
/// \endcode
/// The matcher
-/// \matcher{implicitCastExpr(hasSourceExpression(ignoringParens(stringLiteral())))}
-/// would match the implicit cast resulting from the assignment
-/// \match{("my-string")}.
+/// \code
+/// implicitCastExpr(hasSourceExpression(ignoringParens(stringLiteral())))
+/// \endcode
+/// would match the implicit cast resulting from the assignment.
AST_MATCHER_P_OVERLOAD(Expr, ignoringParens, internal::Matcher<Expr>,
InnerMatcher, 1) {
const Expr *E = Node.IgnoreParens();
@@ -1370,13 +1015,9 @@ AST_MATCHER_P_OVERLOAD(Expr, ignoringParens, internal::Matcher<Expr>,
/// sizeof is known.
/// \code
/// template<typename T>
-/// void f(T x, T y) { sizeof(T() + T()); }
+/// void f(T x, T y) { sizeof(sizeof(T() + T()); }
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{expr(isInstantiationDependent())}
-/// matches \match{sizeof(T() + T())},
-/// \match{(T() + T())},
-/// \match{T() + T()} and two time \match{count=2$T()}.
+/// expr(isInstantiationDependent()) matches sizeof(sizeof(T() + T())
AST_MATCHER(Expr, isInstantiationDependent) {
return Node.isInstantiationDependent();
}
@@ -1392,9 +1033,7 @@ AST_MATCHER(Expr, isInstantiationDependent) {
/// x + y;
/// }
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{expr(isTypeDependent())}
-/// matches \match{x + y} and \match{x}.
+/// expr(isTypeDependent()) matches x + y
AST_MATCHER(Expr, isTypeDependent) { return Node.isTypeDependent(); }
/// Matches expression that are value-dependent because they contain a
@@ -1405,9 +1044,7 @@ AST_MATCHER(Expr, isTypeDependent) { return Node.isTypeDependent(); }
/// \code
/// template<int Size> int f() { return Size; }
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{expr(isValueDependent())}
-/// matches the return value \match{Size}.
+/// expr(isValueDependent()) matches return Size
AST_MATCHER(Expr, isValueDependent) { return Node.isValueDependent(); }
/// Matches templateSpecializationType, class template specializations,
@@ -1417,21 +1054,18 @@ AST_MATCHER(Expr, isValueDependent) { return Node.isValueDependent(); }
/// Given
/// \code
/// template<typename T, typename U> class A {};
-/// A<double, int> b;
-/// A<int, double> c;
+/// A<bool, int> b;
+/// A<int, bool> c;
///
/// template<typename T> void f() {}
/// void func() { f<int>(); };
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher
-/// \matcher{classTemplateSpecializationDecl(hasTemplateArgument(
-/// 1, refersToType(asString("int"))))}
-/// matches the specialization \match{type=typestr$class A<double, int>}.
+/// classTemplateSpecializationDecl(hasTemplateArgument(
+/// 1, refersToType(asString("int"))))
+/// matches the specialization \c A<bool, int>
///
-/// The matcher \matcher{functionDecl(hasTemplateArgument(0,
-/// refersToType(asString("int"))))}
-/// matches the specialization of \match{void f() {}}.
+/// functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))
+/// matches the specialization \c f<int>
AST_POLYMORPHIC_MATCHER_P2(
hasTemplateArgument,
AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
@@ -1452,10 +1086,8 @@ AST_POLYMORPHIC_MATCHER_P2(
/// template<typename T> struct C {};
/// C<int> c;
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher
-/// \matcher{classTemplateSpecializationDecl(templateArgumentCountIs(1))}
-/// matches \match{type=typestr$struct C<int>}.
+/// classTemplateSpecializationDecl(templateArgumentCountIs(1))
+/// matches C<int>.
AST_POLYMORPHIC_MATCHER_P(
templateArgumentCountIs,
AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
@@ -1472,11 +1104,9 @@ AST_POLYMORPHIC_MATCHER_P(
/// template<typename T> struct A {};
/// A<X> a;
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher
-/// \matcher{classTemplateSpecializationDecl(hasAnyTemplateArgument(refersToType(
-/// recordType(hasDeclaration(recordDecl(hasName("X")))))))}
-/// matches the specialization \match{type=typestr$struct A<struct X>}.
+/// classTemplateSpecializationDecl(hasAnyTemplateArgument(refersToType(
+/// recordType(hasDeclaration(recordDecl(hasName("X")))))))
+/// matches the specialization of \c struct A generated by \c A<X>.
AST_MATCHER_P(TemplateArgument, refersToType,
internal::Matcher<QualType>, InnerMatcher) {
if (Node.getKind() != TemplateArgument::Type)
@@ -1492,11 +1122,9 @@ AST_MATCHER_P(TemplateArgument, refersToType,
/// template<typename T> class Y {};
/// X<Y> xi;
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher
-/// \matcher{classTemplateSpecializationDecl(hasAnyTemplateArgument(
-/// refersToTemplate(templateName())))}
-/// matches the specialization \match{type=typestr$class X<Y>}
+/// classTemplateSpecializationDecl(hasAnyTemplateArgument(
+/// refersToTemplate(templateName())))
+/// matches the specialization \c X<Y>
AST_MATCHER_P(TemplateArgument, refersToTemplate,
internal::Matcher<TemplateName>, InnerMatcher) {
if (Node.getKind() != TemplateArgument::Template)
@@ -1513,13 +1141,10 @@ AST_MATCHER_P(TemplateArgument, refersToTemplate,
/// template<int(B::*next_ptr)> struct A {};
/// A<&B::next> a;
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher
-/// \matcher{classTemplateSpecializationDecl(hasAnyTemplateArgument(
-/// refersToDeclaration(fieldDecl(hasName("next")).bind("next"))))}
-/// matches the specialization \match{type=typestr$struct A<&B::next>}
-/// with \matcher{type=sub$fieldDecl(hasName("next"))} matching
-/// \match{sub=next$int next}.
+/// classTemplateSpecializationDecl(hasAnyTemplateArgument(
+/// refersToDeclaration(fieldDecl(hasName("next")))))
+/// matches the specialization \c A<&B::next> with \c fieldDecl(...) matching
+/// \c B::next
AST_MATCHER_P(TemplateArgument, refersToDeclaration,
internal::Matcher<Decl>, InnerMatcher) {
if (Node.getKind() == TemplateArgument::Declaration)
@@ -1535,13 +1160,10 @@ AST_MATCHER_P(TemplateArgument, refersToDeclaration,
/// template<int(B::*next_ptr)> struct A {};
/// A<&B::next> a;
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher
-/// \matcher{templateSpecializationType(hasAnyTemplateArgument(
-/// isExpr(hasDescendant(declRefExpr(to(fieldDecl(hasName("next")).bind("next")))))))}
-/// matches the specialization \match{type=typestr$A<&struct B::next>}
-/// with \matcher{type=sub$fieldDecl(hasName("next"))} matching
-/// \match{sub=next$int next}.
+/// templateSpecializationType(hasAnyTemplateArgument(
+/// isExpr(hasDescendant(declRefExpr(to(fieldDecl(hasName("next"))))))))
+/// matches the specialization \c A<&B::next> with \c fieldDecl(...) matching
+/// \c B::next
AST_MATCHER_P(TemplateArgument, isExpr, internal::Matcher<Expr>, InnerMatcher) {
if (Node.getKind() == TemplateArgument::Expression)
return InnerMatcher.matches(*Node.getAsExpr(), Finder, Builder);
@@ -1555,12 +1177,10 @@ AST_MATCHER_P(TemplateArgument, isExpr, internal::Matcher<Expr>, InnerMatcher) {
/// template<int T> struct C {};
/// C<42> c;
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{classTemplateSpecializationDecl(
-/// hasAnyTemplateArgument(isIntegral()))}
-/// matches the implicitly declared specialization
-/// \match{type=typestr$struct C<42>} from the instantiation for the type of the
-/// variable \c c .
+/// classTemplateSpecializationDecl(
+/// hasAnyTemplateArgument(isIntegral()))
+/// matches the implicit instantiation of C in C<42>
+/// with isIntegral() matching 42.
AST_MATCHER(TemplateArgument, isIntegral) {
return Node.getKind() == TemplateArgument::Integral;
}
@@ -1572,12 +1192,9 @@ AST_MATCHER(TemplateArgument, isIntegral) {
/// template<int T> struct C {};
/// C<42> c;
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{classTemplateSpecializationDecl(
-/// hasAnyTemplateArgument(refersToIntegralType(asString("int"))))}
-/// matches the implicitly declared specialization
-/// \match{type=typestr$struct C<42>} from the instantiation for the type of the
-/// variable \c c .
+/// classTemplateSpecializationDecl(
+/// hasAnyTemplateArgument(refersToIntegralType(asString("int"))))
+/// matches the implicit instantiation of C in C<42>.
AST_MATCHER_P(TemplateArgument, refersToIntegralType,
internal::Matcher<QualType>, InnerMatcher) {
if (Node.getKind() != TemplateArgument::Integral)
@@ -1596,12 +1213,9 @@ AST_MATCHER_P(TemplateArgument, refersToIntegralType,
/// template<int T> struct C {};
/// C<42> c;
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{classTemplateSpecializationDecl(
-/// hasAnyTemplateArgument(equalsIntegralValue("42")))}
-/// matches the implicitly declared specialization
-/// \match{type=typestr$struct C<42>} from the instantiation for the type of the
-/// variable \c c .
+/// classTemplateSpecializationDecl(
+/// hasAnyTemplateArgument(equalsIntegralValue("42")))
+/// matches the implicit instantiation of C in C<42>.
AST_MATCHER_P(TemplateArgument, equalsIntegralValue,
std::string, Value) {
if (Node.getKind() != TemplateArgument::Integral)
@@ -1617,28 +1231,23 @@ AST_MATCHER_P(TemplateArgument, equalsIntegralValue,
/// int x = 0;
/// }
/// \endcode
-/// \compile_args{-ObjC}
-/// The matcher \matcher{autoreleasePoolStmt(stmt())} matches the declaration of
-/// \match{int x = 0} inside the autorelease pool.
+/// autoreleasePoolStmt(stmt()) matches the declaration of "x"
+/// inside the autorelease pool.
extern const internal::VariadicDynCastAllOfMatcher<Stmt,
ObjCAutoreleasePoolStmt> autoreleasePoolStmt;
/// Matches any value declaration.
///
-/// Given
+/// Example matches A, B, C and F
/// \code
/// enum X { A, B, C };
/// void F();
-/// int V = 0;
/// \endcode
-/// The matcher \matcher{valueDecl()}
-/// matches \match{A}, \match{B}, \match{C}, \match{void F()}
-/// and \match{int V = 0}.
extern const internal::VariadicDynCastAllOfMatcher<Decl, ValueDecl> valueDecl;
/// Matches C++ constructor declarations.
///
-/// Given
+/// Example matches Foo::Foo() and Foo::Foo(int)
/// \code
/// class Foo {
/// public:
@@ -1646,134 +1255,93 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ValueDecl> valueDecl;
/// Foo(int);
/// int DoSomething();
/// };
-///
-/// struct Bar {};
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{cxxConstructorDecl()}
-/// matches \match{Foo()} and \match{Foo(int)}.
extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXConstructorDecl>
cxxConstructorDecl;
/// Matches explicit C++ destructor declarations.
///
-/// Given
+/// Example matches Foo::~Foo()
/// \code
/// class Foo {
/// public:
/// virtual ~Foo();
/// };
-///
-/// struct Bar {};
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{cxxDestructorDecl()}
-/// matches \match{virtual ~Foo()}.
extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXDestructorDecl>
cxxDestructorDecl;
/// Matches enum declarations.
///
-/// Given
+/// Example matches X
/// \code
-/// enum X { A, B, C };
+/// enum X {
+/// A, B, C
+/// };
/// \endcode
-///
-/// The matcher \matcher{enumDecl()}
-/// matches the enum \match{enum X { A, B, C }}.
extern const internal::VariadicDynCastAllOfMatcher<Decl, EnumDecl> enumDecl;
/// Matches enum constants.
///
-/// Given
+/// Example matches A, B, C
/// \code
/// enum X {
/// A, B, C
/// };
/// \endcode
-/// The matcher \matcher{enumConstantDecl()}
-/// matches \match{A}, \match{B} and \match{C}.
extern const internal::VariadicDynCastAllOfMatcher<Decl, EnumConstantDecl>
enumConstantDecl;
/// Matches tag declarations.
///
-/// Given
+/// Example matches X, Z, U, S, E
/// \code
/// class X;
/// template<class T> class Z {};
/// struct S {};
/// union U {};
-/// enum E { A, B, C };
+/// enum E {
+/// A, B, C
+/// };
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-///
-/// The matcher \matcher{tagDecl()}
-/// matches \match{class X}, \match{class Z {}}, the implicit class
-/// declaration \match{class Z}, \match{struct S {}},
-/// the implicit class declaration \match{struct S}, \match{union U {}},
-/// the implicit class declaration \match{union U}
-/// and \match{enum E { A, B, C }}.
extern const internal::VariadicDynCastAllOfMatcher<Decl, TagDecl> tagDecl;
/// Matches method declarations.
///
-/// Given
+/// Example matches y
/// \code
/// class X { void y(); };
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{cxxMethodDecl()}
-/// matches \match{void y()}.
extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl>
cxxMethodDecl;
/// Matches conversion operator declarations.
///
-/// Given
+/// Example matches the operator.
/// \code
/// class X { operator int() const; };
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{cxxConversionDecl()}
-/// matches \match{operator int() const}.
extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXConversionDecl>
cxxConversionDecl;
/// Matches user-defined and implicitly generated deduction guide.
///
-/// Given
+/// Example matches the deduction guide.
/// \code
/// template<typename T>
-/// class X { X(int); };
+/// class X { X(int) };
/// X(int) -> X<int>;
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++17-or-later}
-///
-/// The matcher \matcher{cxxDeductionGuideDecl()}
-/// matches the written deduction guide
-/// \match{type=typestr$auto (int) -> X<int>},
-/// the implicit copy deduction guide \match{type=typestr$auto (int) -> X<T>}
-/// and the implicitly declared deduction guide
-/// \match{type=typestr$auto (X<T>) -> X<T>}.
extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXDeductionGuideDecl>
cxxDeductionGuideDecl;
/// Matches concept declarations.
///
-/// Given
+/// Example matches integral
/// \code
-/// template<typename T> concept my_concept = true;
+/// template<typename T>
+/// concept integral = std::is_integral_v<T>;
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++20-or-later}
-///
-/// The matcher \matcher{conceptDecl()}
-/// matches \match{template<typename T>
-/// concept my_concept = true}.
extern const internal::VariadicDynCastAllOfMatcher<Decl, ConceptDecl>
conceptDecl;
@@ -1785,29 +1353,17 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ConceptDecl>
/// Example matches a
/// \code
/// int a;
-/// struct Foo {
-/// int x;
-/// };
-/// void bar(int val);
/// \endcode
-///
-/// The matcher \matcher{varDecl()}
-/// matches \match{int a} and \match{int val}, but not \nomatch{int x}.
extern const internal::VariadicDynCastAllOfMatcher<Decl, VarDecl> varDecl;
/// Matches field declarations.
///
/// Given
/// \code
-/// int a;
-/// struct Foo {
-/// int x;
-/// };
-/// void bar(int val);
+/// class X { int m; };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{fieldDecl()}
-/// matches \match{int x}.
+/// fieldDecl()
+/// matches 'm'.
extern const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> fieldDecl;
/// Matches indirect field declarations.
@@ -1816,20 +1372,17 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> fieldDecl;
/// \code
/// struct X { struct { int a; }; };
/// \endcode
-/// The matcher \matcher{indirectFieldDecl()}
-/// matches \match{a}.
+/// indirectFieldDecl()
+/// matches 'a'.
extern const internal::VariadicDynCastAllOfMatcher<Decl, IndirectFieldDecl>
indirectFieldDecl;
/// Matches function declarations.
///
-/// Given
+/// Example matches f
/// \code
/// void f();
/// \endcode
-///
-/// The matcher \matcher{functionDecl()}
-/// matches \match{void f()}.
extern const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl>
functionDecl;
@@ -1839,10 +1392,6 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl>
/// \code
/// template<class T> void f(T t) {}
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-///
-/// The matcher \matcher{functionTemplateDecl()}
-/// matches \match{template<class T> void f(T t) {}}.
extern const internal::VariadicDynCastAllOfMatcher<Decl, FunctionTemplateDecl>
functionTemplateDecl;
@@ -1852,32 +1401,28 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, FunctionTemplateDecl>
/// \code
/// class X { friend void foo(); };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{friendDecl()}
-/// matches \match{friend void foo()}.
+/// friendDecl()
+/// matches 'friend void foo()'.
extern const internal::VariadicDynCastAllOfMatcher<Decl, FriendDecl> friendDecl;
/// Matches statements.
///
/// Given
/// \code
-/// void foo(int a) { { ++a; } }
+/// { ++a; }
/// \endcode
-/// The matcher \matcher{stmt()}
-/// matches the function body itself \match{{ { ++a; } }}, the compound
-/// statement \match{{ ++a; }}, the expression \match{++a} and \match{a}.
+/// stmt()
+/// matches both the compound statement '{ ++a; }' and '++a'.
extern const internal::VariadicAllOfMatcher<Stmt> stmt;
/// Matches declaration statements.
///
/// Given
/// \code
-/// void foo() {
-/// int a;
-/// }
+/// int a;
/// \endcode
-/// The matcher \matcher{declStmt()}
-/// matches \match{int a;}.
+/// declStmt()
+/// matches 'int a'.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, DeclStmt> declStmt;
/// Matches member expressions.
@@ -1889,9 +1434,8 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, DeclStmt> declStmt;
/// int a; static int b;
/// };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{memberExpr()}
-/// matches \match{this->x}, \match{x}, \match{y.x}, \match{a}, \match{this->b}.
+/// memberExpr()
+/// matches this->x, x, y.x, a, this->b
extern const internal::VariadicDynCastAllOfMatcher<Stmt, MemberExpr> memberExpr;
/// Matches unresolved member expressions.
@@ -1904,9 +1448,8 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, MemberExpr> memberExpr;
/// };
/// template <class T> void h() { X x; x.f<T>(); x.g(); }
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{unresolvedMemberExpr()}
-/// matches \match{x.f<T>}
+/// unresolvedMemberExpr()
+/// matches x.f<T>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, UnresolvedMemberExpr>
unresolvedMemberExpr;
@@ -1917,9 +1460,8 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, UnresolvedMemberExpr>
/// \code
/// template <class T> void f() { T t; t.g(); }
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{cxxDependentScopeMemberExpr()}
-/// matches \match{t.g}
+/// cxxDependentScopeMemberExpr()
+/// matches t.g
extern const internal::VariadicDynCastAllOfMatcher<Stmt,
CXXDependentScopeMemberExpr>
cxxDependentScopeMemberExpr;
@@ -1928,22 +1470,15 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt,
///
/// Example matches x.y() and y()
/// \code
-/// struct X { void foo(); };
-/// void bar();
-/// void foobar() {
-/// X x;
-/// x.foo();
-/// bar();
-/// }
+/// X x;
+/// x.y();
+/// y();
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{callExpr()}
-/// matches \match{x.foo()} and \match{bar()};
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> callExpr;
/// Matches call expressions which were resolved using ADL.
///
-/// Given
+/// Example matches y(x) but not y(42) or NS::y(x).
/// \code
/// namespace NS {
/// struct X {};
@@ -1959,46 +1494,25 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> callExpr;
/// y(42); // Doesn't match
/// using NS::y;
/// y(x); // Found by both unqualified lookup and ADL, doesn't match
-/// }
+// }
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-///
-/// The matcher \matcher{callExpr(usesADL())}
-/// matches \match{y(x)}, but not \nomatch{y(42)} or \nomatch{NS::y(x)}.
AST_MATCHER(CallExpr, usesADL) { return Node.usesADL(); }
/// Matches lambda expressions.
///
-/// Given
+/// Example matches [&](){return 5;}
/// \code
-/// void f() {
-/// []() { return 5; };
-/// }
+/// [&](){return 5;}
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-///
-/// The matcher \matcher{lambdaExpr()} matches \match{[]() { return 5; }}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, LambdaExpr> lambdaExpr;
/// Matches member call expressions.
///
-/// Given
+/// Example matches x.y()
/// \code
-/// struct X {
-/// void y();
-/// void m() { y(); }
-/// };
-/// void f();
-/// void g() {
-/// X x;
-/// x.y();
-/// f();
-/// }
+/// X x;
+/// x.y();
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{cxxMemberCallExpr()} matches \match{x.y()} and
-/// \match{y()}, but not \nomatch{f()}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXMemberCallExpr>
cxxMemberCallExpr;
@@ -2011,10 +1525,6 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXMemberCallExpr>
/// \code
/// [[NSString alloc] initWithString:@"Hello"]
/// \endcode
-/// \compile_args{-ObjC}
-///
-/// The matcher \matcher{objcMessageExpr()} matches
-/// \match{[[NSString alloc] initWithString:@"Hello"]}
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCMessageExpr>
objcMessageExpr;
@@ -2024,7 +1534,6 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCMessageExpr>
/// \code
/// NSString *s = @"abcd";
/// \endcode
-/// \compile_args{-ObjC}
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCStringLiteral>
objcStringLiteral;
@@ -2035,7 +1544,6 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCStringLiteral>
/// @interface Foo
/// @end
/// \endcode
-/// \compile_args{-ObjC}
extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCInterfaceDecl>
objcInterfaceDecl;
@@ -2046,7 +1554,6 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCInterfaceDecl>
/// @implementation Foo
/// @end
/// \endcode
-/// \compile_args{-ObjC}
extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCImplementationDecl>
objcImplementationDecl;
@@ -2057,7 +1564,6 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCImplementationDecl>
/// @protocol FooDelegate
/// @end
/// \endcode
-/// \compile_args{-ObjC}
extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCProtocolDecl>
objcProtocolDecl;
@@ -2068,7 +1574,6 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCProtocolDecl>
/// @interface Foo (Additions)
/// @end
/// \endcode
-/// \compile_args{-ObjC}
extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCCategoryDecl>
objcCategoryDecl;
@@ -2079,7 +1584,6 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCCategoryDecl>
/// @implementation Foo (Additions)
/// @end
/// \endcode
-/// \compile_args{-ObjC}
extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCCategoryImplDecl>
objcCategoryImplDecl;
@@ -2095,7 +1599,6 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCCategoryImplDecl>
/// - (void)method {}
/// @end
/// \endcode
-/// \compile_args{-ObjC}
extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCMethodDecl>
objcMethodDecl;
@@ -2109,7 +1612,6 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCMethodDecl>
/// printf("%d", p);
/// })
/// \endcode
-/// \compile_args{-ObjC}
extern const internal::VariadicDynCastAllOfMatcher<Decl, BlockDecl>
blockDecl;
@@ -2122,7 +1624,6 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, BlockDecl>
/// }
/// @end
/// \endcode
-/// \compile_args{-ObjC}
extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCIvarDecl>
objcIvarDecl;
@@ -2134,7 +1635,6 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCIvarDecl>
/// @property BOOL enabled;
/// @end
/// \endcode
-/// \compile_args{-ObjC}
extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCPropertyDecl>
objcPropertyDecl;
@@ -2144,7 +1644,6 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCPropertyDecl>
/// \code
/// @throw obj;
/// \endcode
-/// \compile_args{-ObjC}
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtThrowStmt>
objcThrowStmt;
@@ -2155,7 +1654,6 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtThrowStmt>
/// @try {}
/// @catch (...) {}
/// \endcode
-/// \compile_args{-ObjC}
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtTryStmt>
objcTryStmt;
@@ -2166,7 +1664,6 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtTryStmt>
/// @try {}
/// @catch (...) {}
/// \endcode
-/// \compile_args{-ObjC}
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtCatchStmt>
objcCatchStmt;
@@ -2177,7 +1674,6 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtCatchStmt>
/// @try {}
/// @finally {}
/// \endcode
-/// \compile_args{-ObjC}
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtFinallyStmt>
objcFinallyStmt;
@@ -2186,21 +1682,8 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtFinallyStmt>
///
/// Example matches std::string()
/// \code
-/// struct A { ~A(); };
-/// void f(A);
-/// void g(A&);
-/// void h() {
-/// A a = A{};
-/// f(A{});
-/// f(a);
-/// g(a);
-/// }
+/// const std::string str = std::string();
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-///
-/// The matcher \matcher{exprWithCleanups()} matches \match{A{}},
-/// \match{f(A{})} and \match{f(a)},
-/// but does not match passing \nomatch{g(a)}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ExprWithCleanups>
exprWithCleanups;
@@ -2210,29 +1693,17 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ExprWithCleanups>
/// \code
/// int a[] = { 1, 2 };
/// struct B { int x, y; };
-/// struct B b = { 5, 6 };
+/// B b = { 5, 6 };
/// \endcode
-/// The matcher \matcher{initListExpr()}
-/// matches \match{{ 1, 2 }} and \match{{ 5, 6 }}
+/// initListExpr()
+/// matches "{ 1, 2 }" and "{ 5, 6 }"
extern const internal::VariadicDynCastAllOfMatcher<Stmt, InitListExpr>
initListExpr;
/// Matches the syntactic form of init list expressions
/// (if expression have it).
-///
-/// Given
-/// \code
-/// int a[] = { 1, 2 };
-/// struct B { int x, y; };
-/// struct B b = { 5, 6 };
-/// \endcode
-/// \compile_args{-std=c}
-///
-/// The matcher
-/// \matcher{initListExpr(hasSyntacticForm(expr().bind("syntactic")))}
-/// matches \match{{ 1, 2 }} and \match{{ 5, 6 }}.
-AST_MATCHER_P(InitListExpr, hasSyntacticForm, internal::Matcher<Expr>,
- InnerMatcher) {
+AST_MATCHER_P(InitListExpr, hasSyntacticForm,
+ internal::Matcher<Expr>, InnerMatcher) {
const Expr *SyntForm = Node.getSyntacticForm();
return (SyntForm != nullptr &&
InnerMatcher.matches(*SyntForm, Finder, Builder));
@@ -2242,26 +1713,13 @@ AST_MATCHER_P(InitListExpr, hasSyntacticForm, internal::Matcher<Expr>,
///
/// Given
/// \code
-/// namespace std {
-/// template <typename T>
-/// class initializer_list {
-/// const T* begin;
-/// const T* end;
-/// };
-/// }
-/// template <typename T> class vector {
-/// public: vector(std::initializer_list<T>) {}
-/// };
-///
-/// vector<int> a({ 1, 2, 3 });
-/// vector<int> b = { 4, 5 };
+/// std::vector<int> a({ 1, 2, 3 });
+/// std::vector<int> b = { 4, 5 };
/// int c[] = { 6, 7 };
-/// struct pair { int x; int y; };
-/// pair d = { 8, 9 };
+/// std::pair<int, int> d = { 8, 9 };
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++11-or-later,-nostdinc++}
-/// The matcher \matcher{cxxStdInitializerListExpr()}
-/// matches \match{{ 1, 2, 3 }} and \match{{ 4, 5 }}.
+/// cxxStdInitializerListExpr()
+/// matches "{ 1, 2, 3 }" and "{ 4, 5 }"
extern const internal::VariadicDynCastAllOfMatcher<Stmt,
CXXStdInitializerListExpr>
cxxStdInitializerListExpr;
@@ -2270,12 +1728,10 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt,
///
/// Given
/// \code
-/// struct point { double x; double y; };
-/// struct point pt = { .x = 42.0 };
+/// point ptarray[10] = { [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 };
/// \endcode
-/// The matcher
-/// \matcher{initListExpr(has(implicitValueInitExpr().bind("implicit")))}
-/// matches \match{{ .x = 42.0 }}.
+/// implicitValueInitExpr()
+/// matches "[0].y" (implicitly)
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ImplicitValueInitExpr>
implicitValueInitExpr;
@@ -2292,12 +1748,8 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ImplicitValueInitExpr>
/// }
/// };
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{parenListExpr()}
-/// matches \match{(*this)},
-/// but does not match \nomatch{(a, b)}
-/// because (a, b) has a predefined type and is a ParenExpr, not a
-/// ParenListExpr.
+/// parenListExpr() matches "*this" but NOT matches (a, b) because (a, b)
+/// has a predefined type and is a ParenExpr, not a ParenListExpr.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ParenListExpr>
parenListExpr;
@@ -2309,9 +1761,8 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ParenListExpr>
/// struct A { static const int n = N; };
/// struct B : public A<42> {};
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{substNonTypeTemplateParmExpr()}
-/// matches \match{N} in the right-hand side of "static const int n = N;"
+/// substNonTypeTemplateParmExpr()
+/// matches "N" in the right-hand side of "static const int n = N;"
extern const internal::VariadicDynCastAllOfMatcher<Stmt,
SubstNonTypeTemplateParmExpr>
substNonTypeTemplateParmExpr;
@@ -2323,21 +1774,19 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt,
/// namespace X { int x; }
/// using X::x;
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{usingDecl()}
-/// matches \match{using X::x}
+/// usingDecl()
+/// matches \code using X::x \endcode
extern const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl;
/// Matches using-enum declarations.
///
/// Given
/// \code
-/// namespace X { enum x { val1, val2 }; }
+/// namespace X { enum x {...}; }
/// using enum X::x;
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{usingEnumDecl()}
-/// matches \match{using enum X::x}
+/// usingEnumDecl()
+/// matches \code using enum X::x \endcode
extern const internal::VariadicDynCastAllOfMatcher<Decl, UsingEnumDecl>
usingEnumDecl;
@@ -2348,9 +1797,8 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, UsingEnumDecl>
/// namespace X { int x; }
/// using namespace X;
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{usingDirectiveDecl()}
-/// matches \match{using namespace X}
+/// usingDirectiveDecl()
+/// matches \code using namespace X \endcode
extern const internal::VariadicDynCastAllOfMatcher<Decl, UsingDirectiveDecl>
usingDirectiveDecl;
@@ -2366,9 +1814,8 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, UsingDirectiveDecl>
/// foo<T>();
/// }
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{unresolvedLookupExpr()}
-/// matches \match{foo<T>}.
+/// unresolvedLookupExpr()
+/// matches \code foo<T>() \endcode
extern const internal::VariadicDynCastAllOfMatcher<Stmt, UnresolvedLookupExpr>
unresolvedLookupExpr;
@@ -2381,9 +1828,8 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, UnresolvedLookupExpr>
/// using X::x;
/// };
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{unresolvedUsingValueDecl()}
-/// matches \match{using X::x}
+/// unresolvedUsingValueDecl()
+/// matches \code using X::x \endcode
extern const internal::VariadicDynCastAllOfMatcher<Decl,
UnresolvedUsingValueDecl>
unresolvedUsingValueDecl;
@@ -2401,109 +1847,79 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl,
/// using typename Base<T>::Foo;
/// };
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{unresolvedUsingTypenameDecl()}
-/// matches \match{using typename Base<T>::Foo}
+/// unresolvedUsingTypenameDecl()
+/// matches \code using Base<T>::Foo \endcode
extern const internal::VariadicDynCastAllOfMatcher<Decl,
UnresolvedUsingTypenameDecl>
unresolvedUsingTypenameDecl;
/// Matches a constant expression wrapper.
///
-/// Given
+/// Example matches the constant in the case statement:
+/// (matcher = constantExpr())
/// \code
-/// void f(int a) {
-/// switch (a) {
-/// case 37: break;
-/// }
+/// switch (a) {
+/// case 37: break;
/// }
/// \endcode
-///
-/// The matcher \matcher{constantExpr()} matches \match{37}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ConstantExpr>
constantExpr;
/// Matches parentheses used in expressions.
///
-/// Given
+/// Example matches (foo() + 1)
/// \code
/// int foo() { return 1; }
-/// int bar() {
-/// int a = (foo() + 1);
-/// }
+/// int a = (foo() + 1);
/// \endcode
-///
-/// The matcher \matcher{parenExpr()} matches \match{(foo() + 1)}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ParenExpr> parenExpr;
/// Matches constructor call expressions (including implicit ones).
///
-/// Given
+/// Example matches string(ptr, n) and ptr within arguments of f
+/// (matcher = cxxConstructExpr())
/// \code
-/// struct string {
-/// string(const char*);
-/// string(const char*s, int n);
-/// };
/// void f(const string &a, const string &b);
-/// void foo(char *ptr, int n) {
-/// f(string(ptr, n), ptr);
-/// }
+/// char *ptr;
+/// int n;
+/// f(string(ptr, n), ptr);
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{cxxConstructExpr()} matches \match{string(ptr, n)}
-/// and \match{ptr} within arguments of \c f .
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXConstructExpr>
cxxConstructExpr;
/// Matches unresolved constructor call expressions.
///
-/// Given
+/// Example matches T(t) in return statement of f
+/// (matcher = cxxUnresolvedConstructExpr())
/// \code
/// template <typename T>
/// void f(const T& t) { return T(t); }
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-///
-/// The matcher \matcher{cxxUnresolvedConstructExpr()} matches
-/// \match{T(t)}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt,
CXXUnresolvedConstructExpr>
cxxUnresolvedConstructExpr;
/// Matches implicit and explicit this expressions.
///
-/// Given
+/// Example matches the implicit this expression in "return i".
+/// (matcher = cxxThisExpr())
/// \code
-/// struct foo {
-/// int i;
-/// int f() { return i; }
-/// int g() { return this->i; }
-/// };
+/// struct foo {
+/// int i;
+/// int f() { return i; }
+/// };
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{cxxThisExpr()}
-/// matches \match{this} of \c this->i and the implicit \c this expression
-/// of \match{i}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThisExpr>
cxxThisExpr;
/// Matches nodes where temporaries are created.
///
-/// Given
+/// Example matches FunctionTakesString(GetStringByValue())
+/// (matcher = cxxBindTemporaryExpr())
/// \code
-/// struct S {
-/// S() { } // User defined constructor makes S non-POD.
-/// ~S() { } // User defined destructor makes it non-trivial.
-/// };
-/// void test() {
-/// const S &s_ref = S(); // Requires a CXXBindTemporaryExpr.
-/// }
+/// FunctionTakesString(GetStringByValue());
+/// FunctionTakesStringByPointer(GetStringPointer());
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxBindTemporaryExpr()}
-/// matches the constructor call \match{S()}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXBindTemporaryExpr>
cxxBindTemporaryExpr;
@@ -2514,19 +1930,17 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXBindTemporaryExpr>
/// struct T {void func();};
/// T f();
/// void g(T);
-/// void foo() {
-/// T u(f());
-/// g(f());
-/// f().func();
-/// f(); // does not match
-/// }
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{materializeTemporaryExpr()} matches
-/// \match{std=c++14-or-earlier;count=3$f()} three times before C++17 and it
-/// matches \match{std=c++17-or-later$f()} one time with C++17 and later for
-/// \c f().func() , but it does not match the \nomatch{f()} in the last line in
-/// any version.
+/// materializeTemporaryExpr() matches 'f()' in these statements
+/// \code
+/// T u(f());
+/// g(f());
+/// f().func();
+/// \endcode
+/// but does not match
+/// \code
+/// f();
+/// \endcode
extern const internal::VariadicDynCastAllOfMatcher<Stmt,
MaterializeTemporaryExpr>
materializeTemporaryExpr;
@@ -2535,34 +1949,20 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt,
///
/// Given
/// \code
-/// void* operator new(decltype(sizeof(void*)));
-/// struct X {};
-/// void foo() {
-/// auto* x = new X;
-/// }
+/// new X;
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-///
-/// The matcher \matcher{cxxNewExpr()}
-/// matches \match{new X}.
+/// cxxNewExpr()
+/// matches 'new X'.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNewExpr> cxxNewExpr;
/// Matches delete expressions.
///
/// Given
/// \code
-/// void* operator new(decltype(sizeof(void*)));
-/// void operator delete(void*);
-/// struct X {};
-/// void foo() {
-/// auto* x = new X;
-/// delete x;
-/// }
+/// delete X;
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-///
-/// The matcher \matcher{cxxDeleteExpr()}
-/// matches \match{delete x}.
+/// cxxDeleteExpr()
+/// matches 'delete X'.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr>
cxxDeleteExpr;
@@ -2576,16 +1976,13 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr>
/// bool d() noexcept(noexcept(a()));
/// bool e = noexcept(b()) || noexcept(c());
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{cxxNoexceptExpr()}
-/// matches \match{noexcept(a())}, \match{noexcept(b())} and
-/// \match{noexcept(c())}, but does not match the noexcept specifier in the
-/// declarations a, b, c or d.
+/// cxxNoexceptExpr()
+/// matches `noexcept(a())`, `noexcept(b())` and `noexcept(c())`.
+/// doesn't match the noexcept specifier in the declarations a, b, c or d.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNoexceptExpr>
cxxNoexceptExpr;
-/// Matches a loop initializing the elements of an array in a number of
-/// contexts:
+/// Matches a loop initializing the elements of an array in a number of contexts:
/// * in the implicit copy/move constructor for a class with an array member
/// * when a lambda-expression captures an array by value
/// * when a decomposition declaration decomposes an array
@@ -2594,34 +1991,33 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNoexceptExpr>
/// \code
/// void testLambdaCapture() {
/// int a[10];
-/// [a]() {};
+/// auto Lam1 = [a]() {
+/// return;
+/// };
/// }
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{arrayInitLoopExpr()} matches the implicit loop that
-/// initializes each element of the implicit array field inside the lambda
-/// object, that represents the array \match{a} captured by value.
+/// arrayInitLoopExpr() matches the implicit loop that initializes each element of
+/// the implicit array field inside the lambda object, that represents the array `a`
+/// captured by value.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ArrayInitLoopExpr>
arrayInitLoopExpr;
/// The arrayInitIndexExpr consists of two subexpressions: a common expression
-/// (the source array) that is evaluated once up-front, and a per-element
-/// initializer that runs once for each array element. Within the per-element
-/// initializer, the current index may be obtained via an ArrayInitIndexExpr.
+/// (the source array) that is evaluated once up-front, and a per-element initializer
+/// that runs once for each array element. Within the per-element initializer,
+/// the current index may be obtained via an ArrayInitIndexExpr.
///
/// Given
/// \code
-/// void testStructuredBinding() {
+/// void testStructBinding() {
/// int a[2] = {1, 2};
/// auto [x, y] = a;
/// }
/// \endcode
-/// \compile_args{-std=c++17-or-later}
-///
-/// The matcher \matcher{type=none$arrayInitIndexExpr()} matches the array index
-/// that implicitly iterates over the array `a` to copy each element to the
-/// anonymous array that backs the structured binding.
-/// \match{}
+/// arrayInitIndexExpr() matches the array index that implicitly iterates
+/// over the array `a` to copy each element to the anonymous array
+/// that backs the structured binding `[x, y]` elements of which are
+/// referred to by their aliases `x` and `y`.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ArrayInitIndexExpr>
arrayInitIndexExpr;
@@ -2629,30 +2025,22 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ArrayInitIndexExpr>
///
/// Given
/// \code
-/// void foo() {
-/// int a[2] = {0, 1};
-/// int i = a[1];
-/// }
+/// int i = a[1];
/// \endcode
-/// The matcher \matcher{arraySubscriptExpr()}
-/// matches \match{a[1]}.
+/// arraySubscriptExpr()
+/// matches "a[1]"
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ArraySubscriptExpr>
arraySubscriptExpr;
/// Matches the value of a default argument at the call site.
///
-/// Given
+/// Example matches the CXXDefaultArgExpr placeholder inserted for the
+/// default value of the second parameter in the call expression f(42)
+/// (matcher = cxxDefaultArgExpr())
/// \code
/// void f(int x, int y = 0);
-/// void g() {
-/// f(42);
-/// }
+/// f(42);
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{callExpr(has(cxxDefaultArgExpr()))}
-/// matches the \c CXXDefaultArgExpr placeholder inserted for the default value
-/// of the second parameter in the call expression \match{f(42)}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDefaultArgExpr>
cxxDefaultArgExpr;
@@ -2663,18 +2051,13 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDefaultArgExpr>
/// Currently it does not match operators such as new delete.
/// FIXME: figure out why these do not match?
///
-/// Given
+/// Example matches both operator<<((o << b), c) and operator<<(o, b)
+/// (matcher = cxxOperatorCallExpr())
/// \code
-/// struct ostream;
/// ostream &operator<< (ostream &out, int i) { };
-/// void f(ostream& o, int b, int c) {
-/// o << b << c;
-/// }
+/// ostream &o; int b = 1, c = 1;
+/// o << b << c;
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{cxxOperatorCallExpr()} matches \match{o << b << c}
-/// and \match{o << b}.
/// See also the binaryOperation() matcher for more-general matching of binary
/// uses of this AST node.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXOperatorCallExpr>
@@ -2682,16 +2065,13 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXOperatorCallExpr>
/// Matches C++17 fold expressions.
///
-/// Given
+/// Example matches `(0 + ... + args)`:
/// \code
/// template <typename... Args>
/// auto sum(Args... args) {
/// return (0 + ... + args);
/// }
/// \endcode
-/// \compile_args{-std=c++17-or-later}
-///
-/// The matcher \matcher{cxxFoldExpr()} matches \match{(0 + ... + args)}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXFoldExpr>
cxxFoldExpr;
@@ -2699,21 +2079,17 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXFoldExpr>
///
/// Example matches use of "<":
/// \code
+/// #include <compare>
/// struct HasSpaceshipMem {
/// int a;
-/// constexpr bool operator==(const HasSpaceshipMem&) const = default;
+/// constexpr auto operator<=>(const HasSpaceshipMem&) const = default;
/// };
/// void compare() {
/// HasSpaceshipMem hs1, hs2;
-/// if (hs1 != hs2)
+/// if (hs1 < hs2)
/// return;
/// }
/// \endcode
-/// \compile_args{-std=c++20-or-later}
-///
-/// The matcher \matcher{cxxRewrittenBinaryOperator()} matches
-/// \match{hs1 != hs2}.
-///
/// See also the binaryOperation() matcher for more-general matching
/// of this AST node.
extern const internal::VariadicDynCastAllOfMatcher<Stmt,
@@ -2722,34 +2098,25 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt,
/// Matches expressions.
///
-/// Given
+/// Example matches x()
/// \code
-/// int f(int x, int y) { return x + y; }
+/// void f() { x(); }
/// \endcode
-///
-/// The matcher \matcher{expr()} matches \match{x + y} once,
-/// \match{count=2$x} twice and \match{count=2$y} twice, matching the
-/// \c DeclRefExpr , and the \c ImplicitCastExpr that does an l- to r-value
-/// cast.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, Expr> expr;
/// Matches expressions that refer to declarations.
///
-/// Given
+/// Example matches x in if (x)
/// \code
-/// void f(bool x) {
-/// if (x) {}
-/// }
+/// bool x;
+/// if (x) {}
/// \endcode
-/// \compile_args{-std=c++,c23-or-later}
-///
-/// The matcher \matcher{declRefExpr()} matches \match{x}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, DeclRefExpr>
declRefExpr;
/// Matches a reference to an ObjCIvar.
///
-/// Given
+/// Example: matches "a" in "init" method:
/// \code
/// @implementation A {
/// NSString *a;
@@ -2758,61 +2125,42 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, DeclRefExpr>
/// a = @"hello";
/// }
/// \endcode
-/// \compile_args{-ObjC}
-///
-/// The matcher \matcher{objcIvarRefExpr()} matches \match{a}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCIvarRefExpr>
objcIvarRefExpr;
/// Matches a reference to a block.
///
-/// Given
+/// Example: matches "^{}":
/// \code
/// void f() { ^{}(); }
/// \endcode
-/// \compile_args{-ObjC}
-///
-/// The matcher \matcher{blockExpr()} matches \match{^{}}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, BlockExpr> blockExpr;
/// Matches if statements.
///
-/// Given
+/// Example matches 'if (x) {}'
/// \code
-/// void foo(int x) {
-/// if (x) {}
-/// }
+/// if (x) {}
/// \endcode
-///
-/// The matcher \matcher{ifStmt()} matches \match{if (x) {}}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt;
/// Matches for statements.
///
-/// Given
+/// Example matches 'for (;;) {}'
/// \code
-/// void foo() {
-/// for (;;) {}
-/// int i[] = {1, 2, 3}; for (auto a : i);
-/// }
+/// for (;;) {}
+/// int i[] = {1, 2, 3}; for (auto a : i);
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-///
-/// The matcher \matcher{forStmt()} matches \match{for (;;) {}},
-/// but not \nomatch{for (auto a : i);}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ForStmt> forStmt;
/// Matches the increment statement of a for loop.
///
-/// Given
+/// Example:
+/// forStmt(hasIncrement(unaryOperator(hasOperatorName("++"))))
+/// matches '++x' in
/// \code
-/// void foo(int N) {
-/// for (int x = 0; x < N; ++x) { }
-/// }
+/// for (x; x < N; ++x) { }
/// \endcode
-/// The matcher
-/// \matcher{forStmt(hasIncrement(unaryOperator(hasOperatorName("++"))))}
-/// matches \match{for (int x = 0; x < N; ++x) { }}
AST_MATCHER_P(ForStmt, hasIncrement, internal::Matcher<Stmt>,
InnerMatcher) {
const Stmt *const Increment = Node.getInc();
@@ -2822,14 +2170,12 @@ AST_MATCHER_P(ForStmt, hasIncrement, internal::Matcher<Stmt>,
/// Matches the initialization statement of a for loop.
///
-/// Given
+/// Example:
+/// forStmt(hasLoopInit(declStmt()))
+/// matches 'int x = 0' in
/// \code
-/// void foo(int N) {
/// for (int x = 0; x < N; ++x) { }
-/// }
/// \endcode
-/// The matcher \matcher{forStmt(hasLoopInit(declStmt()))}
-/// matches \match{for (int x = 0; x < N; ++x) { }}
AST_MATCHER_P(ForStmt, hasLoopInit, internal::Matcher<Stmt>,
InnerMatcher) {
const Stmt *const Init = Node.getInit();
@@ -2838,31 +2184,22 @@ AST_MATCHER_P(ForStmt, hasLoopInit, internal::Matcher<Stmt>,
/// Matches range-based for statements.
///
-/// Given
+/// cxxForRangeStmt() matches 'for (auto a : i)'
/// \code
-/// void foo() {
-/// int i[] = {1, 2, 3}; for (auto a : i);
-/// for(int j = 0; j < 5; ++j);
-/// }
+/// int i[] = {1, 2, 3}; for (auto a : i);
+/// for(int j = 0; j < 5; ++j);
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{cxxForRangeStmt()}
-/// matches \match{for (auto a : i);}
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXForRangeStmt>
cxxForRangeStmt;
/// Matches the initialization statement of a for loop.
///
-/// Given
+/// Example:
+/// forStmt(hasLoopVariable(anything()))
+/// matches 'int x' in
/// \code
-/// void foo() {
-/// int a[42] = {};
/// for (int x : a) { }
-/// }
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{cxxForRangeStmt(hasLoopVariable(anything()))}
-/// matches \match{for (int x : a) { }}
AST_MATCHER_P(CXXForRangeStmt, hasLoopVariable, internal::Matcher<VarDecl>,
InnerMatcher) {
const VarDecl *const Var = Node.getLoopVariable();
@@ -2871,16 +2208,12 @@ AST_MATCHER_P(CXXForRangeStmt, hasLoopVariable, internal::Matcher<VarDecl>,
/// Matches the range initialization statement of a for loop.
///
-/// Given
+/// Example:
+/// forStmt(hasRangeInit(anything()))
+/// matches 'a' in
/// \code
-/// void foo() {
-/// int a[42] = {};
/// for (int x : a) { }
-/// }
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{cxxForRangeStmt(hasRangeInit(anything()))}
-/// matches \match{for (int x : a) { }}
AST_MATCHER_P(CXXForRangeStmt, hasRangeInit, internal::Matcher<Expr>,
InnerMatcher) {
const Expr *const Init = Node.getRangeInit();
@@ -2891,52 +2224,40 @@ AST_MATCHER_P(CXXForRangeStmt, hasRangeInit, internal::Matcher<Expr>,
///
/// Given
/// \code
-/// void foo() {
/// while (true) {}
-/// }
/// \endcode
-/// \compile_args{-std=c++,c23-or-later}
-/// The matcher \matcher{whileStmt()}
-/// matches \match{while (true) {}}.
+/// whileStmt()
+/// matches 'while (true) {}'.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, WhileStmt> whileStmt;
/// Matches do statements.
///
/// Given
/// \code
-/// void foo() {
/// do {} while (true);
-/// }
/// \endcode
-/// \compile_args{-std=c++,c23-or-later}
-/// The matcher \matcher{doStmt()}
-/// matches \match{do {} while (true)}
+/// doStmt()
+/// matches 'do {} while(true)'
extern const internal::VariadicDynCastAllOfMatcher<Stmt, DoStmt> doStmt;
/// Matches break statements.
///
/// Given
/// \code
-/// void foo() {
/// while (true) { break; }
-/// }
/// \endcode
-/// \compile_args{-std=c++,c23-or-later}
-/// The matcher \matcher{breakStmt()}
-/// matches \match{break}
+/// breakStmt()
+/// matches 'break'
extern const internal::VariadicDynCastAllOfMatcher<Stmt, BreakStmt> breakStmt;
/// Matches continue statements.
///
/// Given
/// \code
-/// void foo() {
/// while (true) { continue; }
-/// }
/// \endcode
-/// \compile_args{-std=c++,c23-or-later}
-/// The matcher \matcher{continueStmt()}
-/// matches \match{continue}
+/// continueStmt()
+/// matches 'continue'
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ContinueStmt>
continueStmt;
@@ -2944,46 +2265,10 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ContinueStmt>
///
/// Given
/// \code
-/// namespace std {
-/// template <typename T = void>
-/// struct coroutine_handle {
-/// static constexpr coroutine_handle from_address(void* addr) {
-/// return {};
-/// }
-/// };
-///
-/// struct always_suspend {
-/// bool await_ready() const noexcept;
-/// bool await_resume() const noexcept;
-/// template <typename T>
-/// bool await_suspend(coroutine_handle<T>) const noexcept;
-/// };
-///
-/// template <typename T>
-/// struct coroutine_traits {
-/// using promise_type = T::promise_type;
-/// };
-/// } // namespace std
-///
-/// struct generator {
-/// struct promise_type {
-/// void return_value(int v);
-/// std::always_suspend yield_value(int&&);
-/// std::always_suspend initial_suspend() const noexcept;
-/// std::always_suspend final_suspend() const noexcept;
-/// void unhandled_exception();
-/// generator get_return_object();
-/// };
-/// };
-///
-/// generator f() {
-/// co_return 10;
-/// }
-///
+/// while (true) { co_return; }
/// \endcode
-/// \compile_args{-std=c++20-or-later}
-/// The matcher \matcher{coreturnStmt(has(integerLiteral()))}
-/// matches \match{co_return 10}
+/// coreturnStmt()
+/// matches 'co_return'
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CoreturnStmt>
coreturnStmt;
@@ -2991,55 +2276,44 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CoreturnStmt>
///
/// Given
/// \code
-/// int foo() {
/// return 1;
-/// }
/// \endcode
-/// The matcher \matcher{returnStmt()}
-/// matches \match{return 1}
+/// returnStmt()
+/// matches 'return 1'
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ReturnStmt> returnStmt;
/// Matches goto statements.
///
/// Given
/// \code
-/// void bar();
-/// void foo() {
/// goto FOO;
/// FOO: bar();
-/// }
/// \endcode
-/// The matcher \matcher{gotoStmt()}
-/// matches \match{goto FOO}
+/// gotoStmt()
+/// matches 'goto FOO'
extern const internal::VariadicDynCastAllOfMatcher<Stmt, GotoStmt> gotoStmt;
/// Matches label statements.
///
/// Given
/// \code
-/// void bar();
-/// void foo() {
/// goto FOO;
/// FOO: bar();
-/// }
/// \endcode
-/// The matcher \matcher{labelStmt()}
-/// matches \match{FOO: bar()}
+/// labelStmt()
+/// matches 'FOO:'
extern const internal::VariadicDynCastAllOfMatcher<Stmt, LabelStmt> labelStmt;
/// Matches address of label statements (GNU extension).
///
/// Given
/// \code
-/// void bar();
-/// void foo() {
/// FOO: bar();
/// void *ptr = &&FOO;
-/// goto *ptr;
-/// }
+/// goto *bar;
/// \endcode
-/// The matcher \matcher{addrLabelExpr()}
-/// matches \match{&&FOO}
+/// addrLabelExpr()
+/// matches '&&FOO'
extern const internal::VariadicDynCastAllOfMatcher<Stmt, AddrLabelExpr>
addrLabelExpr;
@@ -3047,147 +2321,116 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, AddrLabelExpr>
///
/// Given
/// \code
-/// void foo(int a) {
/// switch(a) { case 42: break; default: break; }
-/// }
/// \endcode
-/// The matcher \matcher{switchStmt()}
-/// matches \match{switch(a) { case 42: break; default: break; }}.
+/// switchStmt()
+/// matches 'switch(a)'.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchStmt> switchStmt;
/// Matches case and default statements inside switch statements.
///
/// Given
/// \code
-/// void foo(int a) {
/// switch(a) { case 42: break; default: break; }
-/// }
/// \endcode
-/// The matcher \matcher{switchCase()}
-/// matches \match{case 42: break} and \match{default: break}
+/// switchCase()
+/// matches 'case 42:' and 'default:'.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchCase> switchCase;
/// Matches case statements inside switch statements.
///
/// Given
/// \code
-/// void foo(int a) {
/// switch(a) { case 42: break; default: break; }
-/// }
/// \endcode
-/// The matcher \matcher{caseStmt()}
-/// matches \match{case 42: break}.
+/// caseStmt()
+/// matches 'case 42:'.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CaseStmt> caseStmt;
/// Matches default statements inside switch statements.
///
/// Given
/// \code
-/// void foo(int a) {
/// switch(a) { case 42: break; default: break; }
-/// }
/// \endcode
-/// The matcher \matcher{defaultStmt()}
-/// matches \match{default: break}.
+/// defaultStmt()
+/// matches 'default:'.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, DefaultStmt>
defaultStmt;
/// Matches compound statements.
///
-/// Given
+/// Example matches '{}' and '{{}}' in 'for (;;) {{}}'
/// \code
-/// void foo() { for (;;) {{}} }
+/// for (;;) {{}}
/// \endcode
-///
-/// The matcher \matcher{compoundStmt()} matches
-/// \match{{ for (;;) {{}} }}, \match{{{}}} and \match{{}}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundStmt>
compoundStmt;
/// Matches catch statements.
///
/// \code
-/// void foo() {
/// try {} catch(int i) {}
-/// }
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxCatchStmt()}
-/// matches \match{catch(int i) {}}
+/// cxxCatchStmt()
+/// matches 'catch(int i)'
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXCatchStmt>
cxxCatchStmt;
/// Matches try statements.
///
/// \code
-/// void foo() {
/// try {} catch(int i) {}
-/// }
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxTryStmt()}
-/// matches \match{try {} catch(int i) {}}
+/// cxxTryStmt()
+/// matches 'try {}'
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTryStmt> cxxTryStmt;
/// Matches throw expressions.
///
/// \code
-/// void foo() {
/// try { throw 5; } catch(int i) {}
-/// }
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxThrowExpr()}
-/// matches \match{throw 5}
+/// cxxThrowExpr()
+/// matches 'throw 5'
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThrowExpr>
cxxThrowExpr;
/// Matches null statements.
///
/// \code
-/// void foo() {
/// foo();;
-/// }
/// \endcode
-/// The matcher \matcher{nullStmt()}
-/// matches the second \match{;}
+/// nullStmt()
+/// matches the second ';'
extern const internal::VariadicDynCastAllOfMatcher<Stmt, NullStmt> nullStmt;
/// Matches asm statements.
///
/// \code
-/// void foo() {
/// int i = 100;
-/// __asm("mov %al, 2");
-/// }
+/// __asm("mov al, 2");
/// \endcode
-/// The matcher \matcher{asmStmt()}
-/// matches \match{__asm("mov %al, 2")}
+/// asmStmt()
+/// matches '__asm("mov al, 2")'
extern const internal::VariadicDynCastAllOfMatcher<Stmt, AsmStmt> asmStmt;
/// Matches bool literals.
///
/// Example matches true
/// \code
-/// bool Flag = true;
+/// true
/// \endcode
-/// \compile_args{-std=c++,c23-or-later}
-///
-/// The matcher \matcher{cxxBoolLiteral()} matches \match{true}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXBoolLiteralExpr>
cxxBoolLiteral;
/// Matches string literals (also matches wide string literals).
///
-/// Given
+/// Example matches "abcd", L"abcd"
/// \code
/// char *s = "abcd";
/// wchar_t *ws = L"abcd";
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{stringLiteral()} matches \match{"abcd"} and
-/// \match{L"abcd"}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, StringLiteral>
stringLiteral;
@@ -3196,15 +2439,11 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, StringLiteral>
/// Not matching Hex-encoded chars (e.g. 0x1234, which is a IntegerLiteral),
/// though.
///
-/// Given
+/// Example matches 'a', L'a'
/// \code
/// char ch = 'a';
/// wchar_t chw = L'a';
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{characterLiteral()} matches \match{'a'} and
-/// \match{L'a'}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CharacterLiteral>
characterLiteral;
@@ -3212,80 +2451,31 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CharacterLiteral>
/// 1, 1L, 0x1 and 1U.
///
/// Does not match character-encoded integers such as L'a'.
-///
-/// Given
-/// \code
-/// int a = 1;
-/// int b = 1L;
-/// int c = 0x1;
-/// int d = 1U;
-/// int e = 1.0;
-/// \endcode
-///
-/// The matcher \matcher{integerLiteral()} matches
-/// \match{1}, \match{1L}, \match{0x1} and \match{1U}, but does not match
-/// \nomatch{1.0}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, IntegerLiteral>
integerLiteral;
/// Matches float literals of all sizes / encodings, e.g.
/// 1.0, 1.0f, 1.0L and 1e10.
///
-/// Given
+/// Does not match implicit conversions such as
/// \code
-/// int a = 1.0;
-/// int b = 1.0F;
-/// int c = 1.0L;
-/// int d = 1e10;
-/// int e = 1;
+/// float a = 10;
/// \endcode
-///
-/// The matcher \matcher{floatLiteral()} matches
-/// \match{1.0}, \match{1.0F}, \match{1.0L} and \match{1e10}, but does not match
-/// \nomatch{1}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, FloatingLiteral>
floatLiteral;
/// Matches imaginary literals, which are based on integer and floating
/// point literals e.g.: 1i, 1.0i
-///
-/// Given
-/// \code
-/// auto a = 1i;
-/// auto b = 1.0i;
-/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{imaginaryLiteral()} matches \match{1i} and
-/// \match{1.0i}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ImaginaryLiteral>
imaginaryLiteral;
/// Matches fixed point literals
-///
-/// Given
-/// \code
-/// void f() {
-/// 0.0k;
-/// }
-/// \endcode
-/// \compile_args{-ffixed-point}
-///
-/// The matcher \matcher{type=none$fixedPointLiteral()} matches \match{0.0k}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, FixedPointLiteral>
fixedPointLiteral;
/// Matches user defined literal operator call.
///
/// Example match: "foo"_suffix
-/// Given
-/// \code
-/// float operator ""_foo(long double);
-/// float a = 1234.5_foo;
-/// \endcode
-/// \compile_args{-std=c++11}
-///
-/// The matcher \matcher{userDefinedLiteral()} matches \match{1234.5_foo}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, UserDefinedLiteral>
userDefinedLiteral;
@@ -3293,12 +2483,9 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, UserDefinedLiteral>
///
/// Example match: {1}, (1, 2)
/// \code
-/// struct vector { int x; int y; };
-/// struct vector myvec = (struct vector){ 1, 2 };
+/// int array[4] = {1};
+/// vector int myvec = (vector int)(1, 2);
/// \endcode
-///
-/// The matcher \matcher{compoundLiteralExpr()}
-/// matches \match{(struct vector){ 1, 2 }}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundLiteralExpr>
compoundLiteralExpr;
@@ -3306,297 +2493,78 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundLiteralExpr>
///
/// Given
/// \code
-/// namespace std {
-/// template <typename T = void>
-/// struct coroutine_handle {
-/// static constexpr coroutine_handle from_address(void* addr) {
-/// return {};
-/// }
-/// };
-///
-/// struct always_suspend {
-/// bool await_ready() const noexcept;
-/// bool await_resume() const noexcept;
-/// template <typename T>
-/// bool await_suspend(coroutine_handle<T>) const noexcept;
-/// };
-///
-/// template <typename T>
-/// struct coroutine_traits {
-/// using promise_type = T::promise_type;
-/// };
-/// } // namespace std
-///
-/// struct generator {
-/// struct promise_type {
-/// std::always_suspend yield_value(int&&);
-/// std::always_suspend initial_suspend() const noexcept;
-/// std::always_suspend final_suspend() const noexcept;
-/// void return_void();
-/// void unhandled_exception();
-/// generator get_return_object();
-/// };
-/// };
-///
-/// std::always_suspend h();
-///
-/// generator g() { co_await h(); }
+/// co_await 1;
/// \endcode
-/// \compile_args{-std=c++20-or-later}
-/// The matcher
-/// \matcher{coawaitExpr(has(callExpr(callee(functionDecl(hasName("h"))))))}
-/// matches \match{co_await h()}.
+/// coawaitExpr()
+/// matches 'co_await 1'
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CoawaitExpr>
coawaitExpr;
-
/// Matches co_await expressions where the type of the promise is dependent
-///
-/// Given
-/// \code
-/// namespace std {
-/// template <typename T = void>
-/// struct coroutine_handle {
-/// static constexpr coroutine_handle from_address(void* addr) {
-/// return {};
-/// }
-/// };
-///
-/// struct always_suspend {
-/// bool await_ready() const noexcept;
-/// bool await_resume() const noexcept;
-/// template <typename T>
-/// bool await_suspend(coroutine_handle<T>) const noexcept;
-/// };
-///
-/// template <typename T>
-/// struct coroutine_traits {
-/// using promise_type = T::promise_type;
-/// };
-/// } // namespace std
-///
-/// template <typename T>
-/// struct generator {
-/// struct promise_type {
-/// std::always_suspend yield_value(int&&);
-/// std::always_suspend initial_suspend() const noexcept;
-/// std::always_suspend final_suspend() const noexcept;
-/// void return_void();
-/// void unhandled_exception();
-/// generator get_return_object();
-/// };
-/// };
-///
-/// template <typename T>
-/// std::always_suspend h();
-///
-/// template <>
-/// std::always_suspend h<void>();
-///
-/// template<typename T>
-/// generator<T> g() { co_await h<T>(); }
-/// \endcode
-/// \compile_args{-std=c++20-or-later}
-/// The matcher \matcher{dependentCoawaitExpr()}
-/// matches \match{co_await h<T>()}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, DependentCoawaitExpr>
dependentCoawaitExpr;
-
/// Matches co_yield expressions.
///
/// Given
/// \code
-/// namespace std {
-/// template <typename T = void>
-/// struct coroutine_handle {
-/// static constexpr coroutine_handle from_address(void* addr) {
-/// return {};
-/// }
-/// };
-///
-/// struct always_suspend {
-/// bool await_ready() const noexcept;
-/// bool await_resume() const noexcept;
-/// template <typename T>
-/// bool await_suspend(coroutine_handle<T>) const noexcept;
-/// };
-///
-/// template <typename T>
-/// struct coroutine_traits {
-/// using promise_type = T::promise_type;
-/// };
-/// } // namespace std
-///
-/// struct generator {
-/// struct promise_type {
-/// std::always_suspend yield_value(int&&);
-/// std::always_suspend initial_suspend() const noexcept;
-/// std::always_suspend final_suspend() const noexcept;
-/// void return_void();
-/// void unhandled_exception();
-/// generator get_return_object();
-/// };
-/// };
-///
-/// generator f() {
-/// while (true) {
-/// co_yield 10;
-/// }
-/// }
+/// co_yield 1;
/// \endcode
-/// \compile_args{-std=c++20-or-later}
-/// The matcher \matcher{coyieldExpr()}
-/// matches \match{co_yield 10}
+/// coyieldExpr()
+/// matches 'co_yield 1'
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CoyieldExpr>
coyieldExpr;
/// Matches coroutine body statements.
///
-/// Given
+/// coroutineBodyStmt() matches the coroutine below
/// \code
-/// namespace std {
-/// template <typename T = void>
-/// struct coroutine_handle {
-/// static constexpr coroutine_handle from_address(void* addr) {
-/// return {};
-/// }
-/// };
-///
-/// struct suspend_always {
-/// bool await_ready() const noexcept;
-/// bool await_resume() const noexcept;
-/// template <typename T>
-/// bool await_suspend(coroutine_handle<T>) const noexcept;
-/// };
-///
-/// template <typename...>
-/// struct coroutine_traits {
-/// struct promise_type {
-/// std::suspend_always initial_suspend() const noexcept;
-/// std::suspend_always final_suspend() const noexcept;
-/// void return_void();
-/// void unhandled_exception();
-/// coroutine_traits get_return_object();
-/// };
-/// };
-/// } // namespace std
-///
-/// void f() { while (true) { co_return; } }
-///
+/// generator<int> gen() {
+/// co_return;
+/// }
/// \endcode
-/// \compile_args{-std=c++20-or-later}
-///
-/// The matcher \matcher{coroutineBodyStmt()} matches
-/// \match{{ while (true) { co_return; } }}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CoroutineBodyStmt>
coroutineBodyStmt;
/// Matches nullptr literal.
-///
-/// Given
-/// \code
-/// int a = 0;
-/// int* b = 0;
-/// int *c = nullptr;
-/// \endcode
-/// \compile_args{-std=c++11,c23-or-later}
-///
-/// The matcher \matcher{cxxNullPtrLiteralExpr()} matches \match{nullptr}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNullPtrLiteralExpr>
cxxNullPtrLiteralExpr;
/// Matches GNU __builtin_choose_expr.
-///
-/// Given
-/// \code
-/// void f() { (void)__builtin_choose_expr(1, 2, 3); }
-/// \endcode
-///
-/// The matcher \matcher{chooseExpr()} matches
-/// \match{__builtin_choose_expr(1, 2, 3)}.
-extern const internal::VariadicDynCastAllOfMatcher<Stmt, ChooseExpr> chooseExpr;
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, ChooseExpr>
+ chooseExpr;
/// Matches builtin function __builtin_convertvector.
-///
-/// Given
-/// \code
-/// typedef double vector4double __attribute__((__vector_size__(32)));
-/// typedef float vector4float __attribute__((__vector_size__(16)));
-/// vector4float vf;
-/// void f() { (void)__builtin_convertvector(vf, vector4double); }
-/// \endcode
-///
-/// The matcher \matcher{convertVectorExpr()} matches
-/// \match{__builtin_convertvector(vf, vector4double)}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ConvertVectorExpr>
convertVectorExpr;
/// Matches GNU __null expression.
-///
-/// Given
-/// \code
-/// auto val = __null;
-/// \endcode
-/// \compile_args{-std=c++11}
-///
-/// The matcher \matcher{gnuNullExpr()} matches \match{__null}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, GNUNullExpr>
gnuNullExpr;
/// Matches C11 _Generic expression.
-///
-/// Given
-/// \code
-/// double fdouble(double);
-/// float ffloat(float);
-/// #define GENERIC_MACRO(X) _Generic((X), double: fdouble, float: ffloat)(X)
-///
-/// void f() {
-/// GENERIC_MACRO(0.0);
-/// GENERIC_MACRO(0.0F);
-/// }
-/// \endcode
-/// \compile_args{-std=c}
-///
-/// The matcher \matcher{type=none$genericSelectionExpr()} matches
-/// the generic selection expression that is expanded in
-/// \match{GENERIC_MACRO(0.0)} and \match{GENERIC_MACRO(0.0F)}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, GenericSelectionExpr>
genericSelectionExpr;
/// Matches atomic builtins.
-///
-/// Given
+/// Example matches __atomic_load_n(ptr, 1)
/// \code
/// void foo() { int *ptr; __atomic_load_n(ptr, 1); }
/// \endcode
-///
-/// The matcher \matcher{atomicExpr()} matches \match{__atomic_load_n(ptr, 1)}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, AtomicExpr> atomicExpr;
/// Matches statement expression (GNU extension).
///
-/// Given
+/// Example match: ({ int X = 4; X; })
/// \code
-/// void f() {
-/// int C = ({ int X = 4; X; });
-/// }
+/// int C = ({ int X = 4; X; });
/// \endcode
-///
-/// The matcher \matcher{stmtExpr()} matches \match{({ int X = 4; X; })}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, StmtExpr> stmtExpr;
/// Matches binary operator expressions.
///
-/// Given
+/// Example matches a || b
/// \code
-/// void foo(bool a, bool b) {
-/// !(a || b);
-/// }
+/// !(a || b)
/// \endcode
-/// \compile_args{-std=c++,c23-or-later}
-///
-/// The matcher \matcher{binaryOperator()} matches \match{a || b}.
-///
/// See also the binaryOperation() matcher for more-general matching.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, BinaryOperator>
binaryOperator;
@@ -3605,39 +2573,26 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, BinaryOperator>
///
/// Example matches !a
/// \code
-/// void foo(bool a, bool b) {
-/// !a || b;
-/// }
+/// !a || b
/// \endcode
-/// \compile_args{-std=c++,c23-or-later}
-///
-/// The matcher \matcher{unaryOperator()} matches \match{!a}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, UnaryOperator>
unaryOperator;
/// Matches conditional operator expressions.
///
-/// Given
+/// Example matches a ? b : c
/// \code
-/// int f(int a, int b, int c) {
-/// return (a ? b : c) + 42;
-/// }
+/// (a ? b : c) + 42
/// \endcode
-///
-/// The matcher \matcher{conditionalOperator()} matches \match{a ? b : c}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ConditionalOperator>
conditionalOperator;
/// Matches binary conditional operator expressions (GNU extension).
///
-/// Given
+/// Example matches a ?: b
/// \code
-/// int f(int a, int b) {
-/// return (a ?: b) + 42;
-/// }
+/// (a ?: b) + 42;
/// \endcode
-///
-/// The matcher \matcher{binaryConditionalOperator()} matches \match{a ?: b}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt,
BinaryConditionalOperator>
binaryConditionalOperator;
@@ -3646,32 +2601,26 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt,
/// to reference another expressions and can be met
/// in BinaryConditionalOperators, for example.
///
-/// Given
+/// Example matches 'a'
/// \code
-/// int f(int a, int b) {
-/// return (a ?: b) + 42;
-/// }
+/// (a ?: c) + 42;
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{opaqueValueExpr()} matches \match{count=2$a} twice,
-/// once for the check and once for the expression of the true path.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, OpaqueValueExpr>
opaqueValueExpr;
/// Matches a C++ static_assert declaration.
///
-/// Given
+/// Example:
+/// staticAssertDecl()
+/// matches
+/// static_assert(sizeof(S) == sizeof(int))
+/// in
/// \code
/// struct S {
/// int x;
/// };
/// static_assert(sizeof(S) == sizeof(int));
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-///
-/// The matcher \matcher{staticAssertDecl()}
-/// matches \match{static_assert(sizeof(S) == sizeof(int))}.
extern const internal::VariadicDynCastAllOfMatcher<Decl, StaticAssertDecl>
staticAssertDecl;
@@ -3685,10 +2634,6 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, StaticAssertDecl>
/// \code
/// void* p = reinterpret_cast<char*>(&p);
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{cxxReinterpretCastExpr()}
-/// matches \match{reinterpret_cast<char*>(&p)}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXReinterpretCastExpr>
cxxReinterpretCastExpr;
@@ -3697,56 +2642,49 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXReinterpretCastExpr>
/// \see hasDestinationType
/// \see reinterpretCast
///
-/// Given
+/// Example:
+/// cxxStaticCastExpr()
+/// matches
+/// static_cast<long>(8)
+/// in
/// \code
/// long eight(static_cast<long>(8));
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{cxxStaticCastExpr()}
-/// matches \match{static_cast<long>(8)}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXStaticCastExpr>
cxxStaticCastExpr;
/// Matches a dynamic_cast expression.
///
-/// Given
+/// Example:
+/// cxxDynamicCastExpr()
+/// matches
+/// dynamic_cast<D*>(&b);
+/// in
/// \code
/// struct B { virtual ~B() {} }; struct D : B {};
/// B b;
/// D* p = dynamic_cast<D*>(&b);
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{cxxDynamicCastExpr()}
-/// matches \match{dynamic_cast<D*>(&b)}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDynamicCastExpr>
cxxDynamicCastExpr;
/// Matches a const_cast expression.
///
-/// Given
+/// Example: Matches const_cast<int*>(&r) in
/// \code
/// int n = 42;
/// const int &r(n);
/// int* p = const_cast<int*>(&r);
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{cxxConstCastExpr()}
-/// matches \match{const_cast<int*>(&r)}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXConstCastExpr>
cxxConstCastExpr;
/// Matches a C-style cast expression.
///
-/// Given
+/// Example: Matches (int) 2.2f in
/// \code
/// int i = (int) 2.2f;
/// \endcode
-///
-/// The matcher \matcher{cStyleCastExpr()}
-/// matches \match{(int) 2.2f}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CStyleCastExpr>
cStyleCastExpr;
@@ -3763,25 +2701,14 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CStyleCastExpr>
///
/// \see hasDestinationType.
///
+/// Example: matches all five of the casts in
/// \code
-/// struct S {};
-/// const S* s;
-/// S* s2 = const_cast<S*>(s);
-///
-/// const int val = 0;
-/// char val0 = val;
-/// char val1 = (char)val;
-/// char val2 = static_cast<char>(val);
-/// int* val3 = reinterpret_cast<int*>(val);
-/// char val4 = char(val);
-/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{explicitCastExpr()}
-/// matches \match{(char)val}, \match{static_cast<char>(val)},
-/// \match{reinterpret_cast<int*>(val)}, \match{const_cast<S*>(s)}
-/// and \match{char(val)}, but not the initialization of \c val0 with
-/// \nomatch{val}.
+/// int((int)(reinterpret_cast<int>(static_cast<int>(const_cast<int>(42)))))
+/// \endcode
+/// but does not match the implicit conversion in
+/// \code
+/// long ell = 42;
+/// \endcode
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ExplicitCastExpr>
explicitCastExpr;
@@ -3789,89 +2716,41 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ExplicitCastExpr>
///
/// This matches many different places, including function call return value
/// eliding, as well as any type conversions.
-///
-/// \code
-/// void f(int);
-/// void g(int val1, int val2) {
-/// unsigned int a = val1;
-/// f(val2);
-/// }
-/// \endcode
-///
-/// The matcher \matcher{implicitCastExpr()}
-/// matches \match{count=2$val1} for the implicit cast from an l- to an r-value
-/// and for the cast to \c{unsigned int}, \match{f} for the function pointer
-/// decay, and \match{val2} for the cast from an l- to an r-value.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, ImplicitCastExpr>
implicitCastExpr;
/// Matches any cast nodes of Clang's AST.
///
-/// Given
+/// Example: castExpr() matches each of the following:
/// \code
-/// struct S {};
-/// const S* s;
-/// S* s2 = const_cast<S*>(s);
-///
-/// const int val = 0;
-/// char val0 = 1;
-/// char val1 = (char)2;
-/// char val2 = static_cast<char>(3);
-/// int* val3 = reinterpret_cast<int*>(4);
-/// char val4 = char(5);
+/// (int) 3;
+/// const_cast<Expr *>(SubExpr);
+/// char c = 0;
+/// \endcode
+/// but does not match
+/// \code
+/// int i = (0);
+/// int k = 0;
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{castExpr()}
-/// matches
-/// \match{const_cast<S*>(s)} and the implicit l- to r-value cast for \match{s},
-/// the implicit cast to \c char for the initializer \match{1},
-/// the c-style cast \match{(char)2} and it's implicit cast to \c char
-/// (part of the c-style cast) \match{2},
-/// \match{static_cast<char>(3)} and it's implicit cast to \c char
-/// (part of the \c static_cast) \match{3},
-/// \match{reinterpret_cast<int*>(4)},
-/// \match{char(5)} and it's implicit cast to \c char
-/// (part of the functional cast) \match{5}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CastExpr> castExpr;
/// Matches functional cast expressions
///
-/// Given
+/// Example: Matches Foo(bar);
/// \code
-/// struct Foo {
-/// Foo(int x);
-/// };
-///
-/// void foo(int bar) {
-/// Foo f = bar;
-/// Foo g = (Foo) bar;
-/// Foo h = Foo(bar);
-/// }
+/// Foo f = bar;
+/// Foo g = (Foo) bar;
+/// Foo h = Foo(bar);
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{cxxFunctionalCastExpr()}
-/// matches \match{Foo(bar)}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXFunctionalCastExpr>
cxxFunctionalCastExpr;
/// Matches functional cast expressions having N != 1 arguments
///
-/// Given
+/// Example: Matches Foo(bar, bar)
/// \code
-/// struct Foo {
-/// Foo(int x, int y);
-/// };
-///
-/// void foo(int bar) {
-/// Foo h = Foo(bar, bar);
-/// }
+/// Foo h = Foo(bar, bar);
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{cxxTemporaryObjectExpr()}
-/// matches \match{Foo(bar, bar)}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTemporaryObjectExpr>
cxxTemporaryObjectExpr;
@@ -3879,27 +2758,17 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTemporaryObjectExpr>
///
/// Example: Matches __func__
/// \code
-/// void f() {
-/// const char* func_name = __func__;
-/// }
+/// printf("%s", __func__);
/// \endcode
-///
-/// The matcher \matcher{predefinedExpr()}
-/// matches \match{__func__}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, PredefinedExpr>
predefinedExpr;
/// Matches C99 designated initializer expressions [C99 6.7.8].
///
-/// Example: Given
+/// Example: Matches { [2].y = 1.0, [0].x = 1.0 }
/// \code
-/// struct point2 { double x; double y; };
-/// struct point2 ptarray[10] = { [0].x = 1.0 };
-/// struct point2 pt = { .x = 2.0 };
+/// point ptarray[10] = { [2].y = 1.0, [0].x = 1.0 };
/// \endcode
-///
-/// The matcher \matcher{designatedInitExpr()}
-/// matches \match{[0].x = 1.0} and \match{.x = 2.0}.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, DesignatedInitExpr>
designatedInitExpr;
@@ -3908,53 +2777,23 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, DesignatedInitExpr>
///
/// Example: Given
/// \code
-/// struct point2 { double x; double y; };
-/// struct point2 ptarray[10] = { [0].x = 1.0 };
-/// struct point2 pt = { .x = 2.0 };
+/// point ptarray[10] = { [2].y = 1.0, [0].x = 1.0 };
+/// point ptarray2[10] = { [2].y = 1.0, [2].x = 0.0, [0].x = 1.0 };
/// \endcode
-///
-/// The matcher \matcher{designatedInitExpr(designatorCountIs(2))}
-/// matches \match{[0].x = 1.0}, but not \nomatch{.x = 2.0}.
+/// designatorCountIs(2)
+/// matches '{ [2].y = 1.0, [0].x = 1.0 }',
+/// but not '{ [2].y = 1.0, [2].x = 0.0, [0].x = 1.0 }'.
AST_MATCHER_P(DesignatedInitExpr, designatorCountIs, unsigned, N) {
return Node.size() == N;
}
/// Matches \c QualTypes in the clang AST.
-///
-/// Given
-/// \code
-/// int a = 0;
-/// const int b = 1;
-/// \endcode
-///
-/// The matcher \matcher{varDecl(hasType(qualType(isConstQualified())))}
-/// matches \match{const int b = 1}, but not \nomatch{int a = 0}.
extern const internal::VariadicAllOfMatcher<QualType> qualType;
/// Matches \c Types in the clang AST.
-///
-/// Given
-/// \code
-/// const int b = 1;
-/// \endcode
-///
-/// The matcher \matcher{varDecl(hasType(type().bind("type")))}
-/// matches \match{const int b = 1}, with \matcher{type=sub$type()}
-/// matching \match{sub=type$int}.
extern const internal::VariadicAllOfMatcher<Type> type;
/// Matches \c TypeLocs in the clang AST.
-///
-/// That is, information about a type and where it was written.
-///
-/// \code
-/// void foo(int val);
-/// \endcode
-///
-/// The matcher \matcher{declaratorDecl(hasTypeLoc(typeLoc().bind("type")))}
-/// matches \match{void foo(int val)} and \match{int val}, with
-/// \matcher{type=sub$typeLoc()} matching \match{sub=type$void} and
-/// \match{sub=type$int} respectively.
extern const internal::VariadicAllOfMatcher<TypeLoc> typeLoc;
/// Matches if any of the given matchers matches.
@@ -3962,20 +2801,18 @@ extern const internal::VariadicAllOfMatcher<TypeLoc> typeLoc;
/// Unlike \c anyOf, \c eachOf will generate a match result for each
/// matching submatcher.
///
-/// Given
+/// For example, in:
/// \code
-/// void f(int a, int b);
+/// class A { int a; int b; };
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{functionDecl(hasAnyParameter(
-/// eachOf(parmVarDecl(hasName("a")).bind("v"),
-/// parmVarDecl(hasName("b")).bind("v"))))}
-/// matches \match{void f(int a, int b)},
-/// with \matcher{type=sub$parmVarDecl(hasName("a"))} matching \match{sub=v$a}
-/// for one match,
-/// and with \matcher{type=sub$parmVarDecl(hasName("b"))} matching
-/// \match{sub=v$b} for the other match.
+/// The matcher:
+/// \code
+/// cxxRecordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
+/// has(fieldDecl(hasName("b")).bind("v"))))
+/// \endcode
+/// will generate two results binding "v", the first of which binds
+/// the field declaration of \c a, the second the field declaration of
+/// \c b.
///
/// Usable as: Any Matcher
extern const internal::VariadicOperatorMatcherFunc<
@@ -3985,15 +2822,6 @@ extern const internal::VariadicOperatorMatcherFunc<
/// Matches if any of the given matchers matches.
///
/// Usable as: Any Matcher
-///
-/// \code
-/// char v0 = 'a';
-/// int v1 = 1;
-/// float v2 = 2.0;
-/// \endcode
-///
-/// The matcher \matcher{varDecl(anyOf(hasName("v0"), hasType(isInteger())))}
-/// matches \match{char v0 = 'a'} and \match{int v1 = 1}.
extern const internal::VariadicOperatorMatcherFunc<
2, std::numeric_limits<unsigned>::max()>
anyOf;
@@ -4001,14 +2829,6 @@ extern const internal::VariadicOperatorMatcherFunc<
/// Matches if all given matchers match.
///
/// Usable as: Any Matcher
-///
-/// \code
-/// int v0 = 0;
-/// int v1 = 1;
-/// \endcode
-///
-/// The matcher \matcher{varDecl(allOf(hasName("v0"), hasType(isInteger())))}
-/// matches \match{int v0 = 0}.
extern const internal::VariadicOperatorMatcherFunc<
2, std::numeric_limits<unsigned>::max()>
allOf;
@@ -4019,14 +2839,22 @@ extern const internal::VariadicOperatorMatcherFunc<
/// Useful when additional information which may or may not present about a main
/// matching node is desired.
///
-/// Given
+/// For example, in:
/// \code
-/// int a = 0;
-/// int b;
+/// class Foo {
+/// int bar;
+/// }
/// \endcode
-///
-/// The matcher \matcher{varDecl(optionally(hasInitializer(expr())))}
-/// matches \match{int a = 0} and \match{int b}.
+/// The matcher:
+/// \code
+/// cxxRecordDecl(
+/// optionally(has(
+/// fieldDecl(hasName("bar")).bind("var")
+/// ))).bind("record")
+/// \endcode
+/// will produce a result binding for both "record" and "var".
+/// The matcher will produce a "record" binding for even if there is no data
+/// member named "bar" in that class.
///
/// Usable as: Any Matcher
extern const internal::VariadicOperatorMatcherFunc<1, 1> optionally;
@@ -4035,12 +2863,11 @@ extern const internal::VariadicOperatorMatcherFunc<1, 1> optionally;
///
/// Given
/// \code
-/// int x = 42;
+/// Foo x = bar;
/// int y = sizeof(x) + alignof(x);
/// \endcode
-/// \compile_args{-std=c++11-or-later,c23-or-later}
-/// The matcher \matcher{unaryExprOrTypeTraitExpr()}
-/// matches \match{sizeof(x)} and \match{alignof(x)}
+/// unaryExprOrTypeTraitExpr()
+/// matches \c sizeof(x) and \c alignof(x)
extern const internal::VariadicDynCastAllOfMatcher<Stmt,
UnaryExprOrTypeTraitExpr>
unaryExprOrTypeTraitExpr;
@@ -4049,26 +2876,26 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt,
///
/// Given
/// \code
-/// void f() {
-/// if (true);
-/// for (; true; );
-/// }
+/// if (true);
+/// for (; true; );
+/// \endcode
+/// with the matcher
+/// \code
+/// mapAnyOf(ifStmt, forStmt).with(
+/// hasCondition(cxxBoolLiteralExpr(equals(true)))
+/// ).bind("trueCond")
+/// \endcode
+/// matches the \c if and the \c for. It is equivalent to:
+/// \code
+/// auto trueCond = hasCondition(cxxBoolLiteralExpr(equals(true)));
+/// anyOf(
+/// ifStmt(trueCond).bind("trueCond"),
+/// forStmt(trueCond).bind("trueCond")
+/// );
/// \endcode
-/// \compile_args{-std=c++,c23-or-later}
-///
-/// The matcher \matcher{stmt(mapAnyOf(ifStmt, forStmt).with(
-/// hasCondition(cxxBoolLiteral(equals(true)))
-/// ))},
-/// which is equivalent to
-/// \matcher{stmt(anyOf(
-/// ifStmt(hasCondition(cxxBoolLiteral(equals(true)))).bind("trueCond"),
-/// forStmt(hasCondition(cxxBoolLiteral(equals(true)))).bind("trueCond")
-/// ))},
-/// matches \match{if (true);} and \match{for (; true; );}.
///
/// The with() chain-call accepts zero or more matchers which are combined
/// as-if with allOf() in each of the node matchers.
-///
/// Usable as: Any Matcher
template <typename T, typename... U>
auto mapAnyOf(internal::VariadicDynCastAllOfMatcher<T, U> const &...) {
@@ -4077,23 +2904,34 @@ auto mapAnyOf(internal::VariadicDynCastAllOfMatcher<T, U> const &...) {
/// Matches nodes which can be used with binary operators.
///
-/// A comparison of two expressions might be represented in the clang AST as a
-/// \c binaryOperator, a \c cxxOperatorCallExpr or a
-/// \c cxxRewrittenBinaryOperator, depending on
+/// The code
+/// \code
+/// var1 != var2;
+/// \endcode
+/// might be represented in the clang AST as a binaryOperator, a
+/// cxxOperatorCallExpr or a cxxRewrittenBinaryOperator, depending on
///
/// * whether the types of var1 and var2 are fundamental (binaryOperator) or at
-/// least one is a class type (\c cxxOperatorCallExpr)
+/// least one is a class type (cxxOperatorCallExpr)
/// * whether the code appears in a template declaration, if at least one of the
-/// vars is a dependent-type (\c binaryOperator)
+/// vars is a dependent-type (binaryOperator)
/// * whether the code relies on a rewritten binary operator, such as a
/// spaceship operator or an inverted equality operator
-/// (\c cxxRewrittenBinaryOperator)
+/// (cxxRewrittenBinaryOperator)
///
/// This matcher elides details in places where the matchers for the nodes are
/// compatible.
///
/// Given
/// \code
+/// binaryOperation(
+/// hasOperatorName("!="),
+/// hasLHS(expr().bind("lhs")),
+/// hasRHS(expr().bind("rhs"))
+/// )
+/// \endcode
+/// matches each use of "!=" in:
+/// \code
/// struct S{
/// bool operator!=(const S&) const;
/// };
@@ -4107,28 +2945,25 @@ auto mapAnyOf(internal::VariadicDynCastAllOfMatcher<T, U> const &...) {
/// template<typename T>
/// void templ()
/// {
-/// 3 != 4;
+/// 1 != 2;
/// T() != S();
/// }
/// struct HasOpEq
/// {
-/// friend bool
-/// operator==(const HasOpEq &, const HasOpEq&) noexcept = default;
+/// bool operator==(const HasOpEq &) const;
/// };
///
/// void inverse()
/// {
-/// HasOpEq e1;
-/// HasOpEq e2;
-/// if (e1 != e2)
+/// HasOpEq s1;
+/// HasOpEq s2;
+/// if (s1 != s2)
/// return;
/// }
///
/// struct HasSpaceship
/// {
-/// friend bool
-/// operator<=>(const HasSpaceship &,
-/// const HasSpaceship&) noexcept = default;
+/// bool operator<=>(const HasOpEq &) const;
/// };
///
/// void use_spaceship()
@@ -4139,27 +2974,18 @@ auto mapAnyOf(internal::VariadicDynCastAllOfMatcher<T, U> const &...) {
/// return;
/// }
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++20-or-later}
-///
-/// The matcher \matcher{binaryOperation(
-/// hasOperatorName("!="),
-/// hasLHS(expr().bind("lhs")),
-/// hasRHS(expr().bind("rhs"))
-/// )}
-/// matches \match{1 != 2}, \match{S() != S()}, \match{3 != 4},
-/// \match{T() != S()}, \match{e1 != e2} and \match{s1 != s2}.
extern const internal::MapAnyOfMatcher<BinaryOperator, CXXOperatorCallExpr,
CXXRewrittenBinaryOperator>
binaryOperation;
/// Matches function calls and constructor calls
///
-/// Because \c CallExpr and \c CXXConstructExpr do not share a common
+/// Because CallExpr and CXXConstructExpr do not share a common
/// base class with API accessing arguments etc, AST Matchers for code
/// which should match both are typically duplicated. This matcher
/// removes the need for duplication.
///
-/// Given
+/// Given code
/// \code
/// struct ConstructorTakesInt
/// {
@@ -4180,12 +3006,12 @@ extern const internal::MapAnyOfMatcher<BinaryOperator, CXXOperatorCallExpr,
/// ConstructorTakesInt cti(42);
/// }
/// \endcode
-/// \compile_args{-std=c++}
///
/// The matcher
-/// \matcher{expr(invocation(hasArgument(0, integerLiteral(equals(42)))))}
-/// matches the expressions \match{callTakesInt(42)}
-/// and \match{cti(42)}.
+/// \code
+/// invocation(hasArgument(0, integerLiteral(equals(42))))
+/// \endcode
+/// matches the expression in both doCall and doConstruct
extern const internal::MapAnyOfMatcher<CallExpr, CXXConstructExpr> invocation;
/// Matches unary expressions that have a specific type of argument.
@@ -4194,10 +3020,8 @@ extern const internal::MapAnyOfMatcher<CallExpr, CXXConstructExpr> invocation;
/// \code
/// int a, c; float b; int s = sizeof(a) + sizeof(b) + alignof(c);
/// \endcode
-/// \compile_args{-std=c++11-or-later,c23-or-later}
-/// The matcher
-/// \matcher{unaryExprOrTypeTraitExpr(hasArgumentOfType(asString("int")))}
-/// matches \match{sizeof(a)} and \match{alignof(c)}
+/// unaryExprOrTypeTraitExpr(hasArgumentOfType(asString("int"))
+/// matches \c sizeof(a) and \c alignof(c)
AST_MATCHER_P(UnaryExprOrTypeTraitExpr, hasArgumentOfType,
internal::Matcher<QualType>, InnerMatcher) {
const QualType ArgumentType = Node.getTypeOfArgument();
@@ -4209,11 +3033,10 @@ AST_MATCHER_P(UnaryExprOrTypeTraitExpr, hasArgumentOfType,
/// Given
/// \code
/// int x;
-/// int s = sizeof(x) + alignof(x);
+/// int s = sizeof(x) + alignof(x)
/// \endcode
-/// \compile_args{-std=c++11-or-later,c23-or-later}
-/// The matcher \matcher{unaryExprOrTypeTraitExpr(ofKind(UETT_SizeOf))}
-/// matches \match{sizeof(x)}
+/// unaryExprOrTypeTraitExpr(ofKind(UETT_SizeOf))
+/// matches \c sizeof(x)
///
/// If the matcher is use from clang-query, UnaryExprOrTypeTrait parameter
/// should be passed as a quoted string. e.g., ofKind("UETT_SizeOf").
@@ -4223,17 +3046,8 @@ AST_MATCHER_P(UnaryExprOrTypeTraitExpr, ofKind, UnaryExprOrTypeTrait, Kind) {
/// Same as unaryExprOrTypeTraitExpr, but only matching
/// alignof.
-///
-/// Given
-/// \code
-/// int align = alignof(int);
-/// \endcode
-/// \compile_args{-std=c++11-or-later,c23-or-later}
-///
-/// The matcher \matcher{alignOfExpr(expr())}
-/// matches \match{alignof(int)}.
-inline internal::BindableMatcher<Stmt>
-alignOfExpr(const internal::Matcher<UnaryExprOrTypeTraitExpr> &InnerMatcher) {
+inline internal::BindableMatcher<Stmt> alignOfExpr(
+ const internal::Matcher<UnaryExprOrTypeTraitExpr> &InnerMatcher) {
return stmt(unaryExprOrTypeTraitExpr(
allOf(anyOf(ofKind(UETT_AlignOf), ofKind(UETT_PreferredAlignOf)),
InnerMatcher)));
@@ -4241,15 +3055,6 @@ alignOfExpr(const internal::Matcher<UnaryExprOrTypeTraitExpr> &InnerMatcher) {
/// Same as unaryExprOrTypeTraitExpr, but only matching
/// sizeof.
-///
-/// Given
-/// \code
-/// struct S { double x; double y; };
-/// int size = sizeof(struct S);
-/// \endcode
-///
-/// The matcher \matcher{sizeOfExpr(expr())}
-/// matches \match{sizeof(struct S)}.
inline internal::BindableMatcher<Stmt> sizeOfExpr(
const internal::Matcher<UnaryExprOrTypeTraitExpr> &InnerMatcher) {
return stmt(unaryExprOrTypeTraitExpr(
@@ -4262,26 +3067,15 @@ inline internal::BindableMatcher<Stmt> sizeOfExpr(
/// with '<enclosing>::'.
/// Does not match typedefs of an underlying type with the given name.
///
-/// Given
+/// Example matches X (Name == "X")
/// \code
/// class X;
/// \endcode
-/// \compile_args{-std=c++}
///
-/// The matcher \matcher{namedDecl(hasName("X"))}
-/// matches \match{class X}.
-///
-/// Given
+/// Example matches X (Name is one of "::a::b::X", "a::b::X", "b::X", "X")
/// \code
/// namespace a { namespace b { class X; } }
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matchers \matcher{namedDecl(hasName("::a::b::X"))},
-/// \matcher{namedDecl(hasName("a::b::X"))},
-/// \matcher{namedDecl(hasName("b::X"))} and
-/// \matcher{namedDecl(hasName("X"))}
-/// match \match{class X}.
inline internal::Matcher<NamedDecl> hasName(StringRef Name) {
return internal::Matcher<NamedDecl>(
new internal::HasNameMatcher({std::string(Name)}));
@@ -4290,17 +3084,13 @@ inline internal::Matcher<NamedDecl> hasName(StringRef Name) {
/// Matches NamedDecl nodes that have any of the specified names.
///
/// This matcher is only provided as a performance optimization of hasName.
-///
-/// Given
/// \code
-/// void f(int a, int b);
+/// hasAnyName(a, b, c)
+/// \endcode
+/// is equivalent to, but faster than
+/// \code
+/// anyOf(hasName(a), hasName(b), hasName(c))
/// \endcode
-///
-/// The matcher \matcher{namedDecl(hasAnyName("a", "b"))},
-/// which is equivalent to the matcher
-/// \matcher{namedDecl(hasAnyName("a", "b"))},
-/// matches \match{int a} and \match{int b}, but not
-/// \nomatch{void f(int a, int b)}.
extern const internal::VariadicFunction<internal::Matcher<NamedDecl>, StringRef,
internal::hasAnyNameFunc>
hasAnyName;
@@ -4312,14 +3102,15 @@ extern const internal::VariadicFunction<internal::Matcher<NamedDecl>, StringRef,
/// prefixing the name with '<enclosing>::'. Does not match typedefs
/// of an underlying type with the given name.
///
-/// Given
+/// Example matches X (regexp == "::X")
/// \code
-/// namespace foo { namespace bar { class X; } }
+/// class X;
/// \endcode
-/// \compile_args{-std=c++}
///
-/// The matcher \matcher{namedDecl(matchesName("^::foo:.*X"))}
-/// matches \match{class X}.
+/// Example matches X (regexp is one of "::X", "^foo::.*X", among others)
+/// \code
+/// namespace foo { namespace bar { class X; } }
+/// \endcode
AST_MATCHER_REGEX(NamedDecl, matchesName, RegExp) {
std::string FullNameString = "::" + Node.getQualifiedNameAsString();
return RegExp->match(FullNameString);
@@ -4330,21 +3121,18 @@ AST_MATCHER_REGEX(NamedDecl, matchesName, RegExp) {
/// Matches overloaded operator names specified in strings without the
/// "operator" prefix: e.g. "<<".
///
-/// Given
+/// Given:
/// \code
-/// struct A { int operator*(); };
+/// class A { int operator*(); };
/// const A &operator<<(const A &a, const A &b);
-/// void f(A a) {
-/// a << a; // <-- This matches
-/// }
+/// A a;
+/// a << a; // <-- This matches
/// \endcode
-/// \compile_args{-std=c++}
///
-/// The matcher \matcher{cxxOperatorCallExpr(hasOverloadedOperatorName("<<"))}
-/// matches \match{a << a}.
-/// The matcher
-/// \matcher{cxxRecordDecl(hasMethod(hasOverloadedOperatorName("*")))}
-/// matches \match{struct A { int operator*(); }}.
+/// \c cxxOperatorCallExpr(hasOverloadedOperatorName("<<"))) matches the
+/// specified line and
+/// \c cxxRecordDecl(hasMethod(hasOverloadedOperatorName("*")))
+/// matches the declaration of \c A.
///
/// Usable as: Matcher<CXXOperatorCallExpr>, Matcher<FunctionDecl>
inline internal::PolymorphicMatcher<
@@ -4364,32 +3152,6 @@ hasOverloadedOperatorName(StringRef Name) {
/// "operator" prefix: e.g. "<<".
///
/// hasAnyOverloadedOperatorName("+", "-")
-///
-/// Given
-/// \code
-/// struct Point { double x; double y; };
-/// Point operator+(const Point&, const Point&);
-/// Point operator-(const Point&, const Point&);
-///
-/// Point sub(Point a, Point b) {
-/// return b - a;
-/// }
-/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{functionDecl(hasAnyOverloadedOperatorName("+", "-"))},
-/// which is equivalent to
-/// \matcher{functionDecl(anyOf(hasAnyOverloadedOperatorName("+"),
-/// hasOverloadedOperatorName("-")))},
-/// matches \match{Point operator+(const Point&, const Point&)} and
-/// \match{Point operator-(const Point&, const Point&)}.
-/// The matcher
-/// \matcher{cxxOperatorCallExpr(hasAnyOverloadedOperatorName("+", "-"))},
-/// which is equivalent to
-/// \matcher{cxxOperatorCallExpr(anyOf(hasOverloadedOperatorName("+"),
-/// hasOverloadedOperatorName("-")))},
-/// matches \match{b - a}.
-///
/// Is equivalent to
/// anyOf(hasOverloadedOperatorName("+"), hasOverloadedOperatorName("-"))
extern const internal::VariadicFunction<
@@ -4419,9 +3181,7 @@ extern const internal::VariadicFunction<
/// s.mem();
/// }
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{cxxDependentScopeMemberExpr(hasMemberName("mem"))}
-/// matches \match{s.mem}.
+/// \c cxxDependentScopeMemberExpr(hasMemberName("mem")) matches `s.mem()`
AST_MATCHER_P(CXXDependentScopeMemberExpr, hasMemberName, std::string, N) {
return Node.getMember().getAsString() == N;
}
@@ -4447,20 +3207,19 @@ AST_MATCHER_P(CXXDependentScopeMemberExpr, hasMemberName, std::string, N) {
/// s.mem();
/// }
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{cxxDependentScopeMemberExpr(
-/// hasObjectExpression(declRefExpr(hasType(
-/// elaboratedType(namesType(templateSpecializationType(
+/// The matcher
+/// @code
+/// \c cxxDependentScopeMemberExpr(
+/// hasObjectExpression(declRefExpr(hasType(templateSpecializationType(
/// hasDeclaration(classTemplateDecl(has(cxxRecordDecl(has(
/// cxxMethodDecl(hasName("mem")).bind("templMem")
/// )))))
-/// )))
-/// ))),
+/// )))),
/// memberHasSameNameAsBoundNode("templMem")
-/// )}
-/// matches \match{s.mem}, with the inner matcher
-/// \matcher{type=sub$cxxMethodDecl(hasName("mem"))} matching
-/// \match{sub=templMem$void mem()} of the \c S template.
+/// )
+/// @endcode
+/// first matches and binds the @c mem member of the @c S template, then
+/// compares its name to the usage in @c s.mem() in the @c x function template
AST_MATCHER_P(CXXDependentScopeMemberExpr, memberHasSameNameAsBoundNode,
std::string, BindingID) {
auto MemberName = Node.getMember().getAsString();
@@ -4485,33 +3244,26 @@ AST_MATCHER_P(CXXDependentScopeMemberExpr, memberHasSameNameAsBoundNode,
///
/// Example matches Y, Z, C (Base == hasName("X"))
/// \code
-/// class X {};
+/// class X;
/// class Y : public X {}; // directly derived
/// class Z : public Y {}; // indirectly derived
/// typedef X A;
/// typedef A B;
/// class C : public B {}; // derived from a typedef of X
-///
-/// class Foo {};
-/// typedef Foo Alias;
-/// class Bar : public Alias {};
-/// // derived from a type that Alias is a typedef of Foo
/// \endcode
-/// \compile_args{-std=c++}
///
-/// The matcher \matcher{cxxRecordDecl(isDerivedFrom(hasName("X")))}
-/// matches \match{class Y : public X {}}, \match{class Z : public Y {}}
-/// and \match{class C : public B {}}.
-///
-/// The matcher \matcher{cxxRecordDecl(isDerivedFrom(hasName("Foo")))}
-/// matches \match{class Bar : public Alias {}}.
+/// In the following example, Bar matches isDerivedFrom(hasName("X")):
+/// \code
+/// class Foo;
+/// typedef Foo X;
+/// class Bar : public Foo {}; // derived from a type that X is a typedef of
+/// \endcode
///
/// In the following example, Bar matches isDerivedFrom(hasName("NSObject"))
/// \code
/// @interface NSObject @end
/// @interface Bar : NSObject @end
/// \endcode
-/// \compile_args{-ObjC}
///
/// Usable as: Matcher<CXXRecordDecl>, Matcher<ObjCInterfaceDecl>
AST_POLYMORPHIC_MATCHER_P(
@@ -4529,44 +3281,6 @@ AST_POLYMORPHIC_MATCHER_P(
}
/// Overloaded method as shortcut for \c isDerivedFrom(hasName(...)).
-///
-/// Matches C++ classes that are directly or indirectly derived from a class
-/// matching \c Base, or Objective-C classes that directly or indirectly
-/// subclass a class matching \c Base.
-///
-/// Note that a class is not considered to be derived from itself.
-///
-/// Example matches Y, Z, C (Base == hasName("X"))
-/// \code
-/// class X {};
-/// class Y : public X {}; // directly derived
-/// class Z : public Y {}; // indirectly derived
-/// typedef X A;
-/// typedef A B;
-/// class C : public B {}; // derived from a typedef of X
-///
-/// class Foo {};
-/// typedef Foo Alias;
-/// class Bar : public Alias {}; // derived from Alias, which is a
-/// // typedef of Foo
-/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{cxxRecordDecl(isDerivedFrom("X"))}
-/// matches \match{class Y : public X {}}, \match{class Z : public Y {}}
-/// and \match{class C : public B {}}.
-///
-/// The matcher \matcher{cxxRecordDecl(isDerivedFrom("Foo"))}
-/// matches \match{class Bar : public Alias {}}.
-///
-/// In the following example, Bar matches isDerivedFrom(hasName("NSObject"))
-/// \code
-/// @interface NSObject @end
-/// @interface Bar : NSObject @end
-/// \endcode
-/// \compile_args{-ObjC}
-///
-/// Usable as: Matcher<CXXRecordDecl>, Matcher<ObjCInterfaceDecl>
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
isDerivedFrom,
AST_POLYMORPHIC_SUPPORTED_TYPES(CXXRecordDecl, ObjCInterfaceDecl),
@@ -4586,21 +3300,17 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
/// Matches C++ classes that have a direct or indirect base matching \p
/// BaseSpecMatcher.
///
-/// Given
+/// Example:
+/// matcher hasAnyBase(hasType(cxxRecordDecl(hasName("SpecialBase"))))
/// \code
-/// class Foo {};
+/// class Foo;
/// class Bar : Foo {};
/// class Baz : Bar {};
-/// class SpecialBase {};
+/// class SpecialBase;
/// class Proxy : SpecialBase {}; // matches Proxy
/// class IndirectlyDerived : Proxy {}; //matches IndirectlyDerived
/// \endcode
-/// \compile_args{-std=c++}
///
-/// The matcher
-/// \matcher{cxxRecordDecl(hasAnyBase(hasType(cxxRecordDecl(hasName("SpecialBase")))))}
-/// matches \match{class Proxy : SpecialBase {}} and
-/// \match{class IndirectlyDerived : Proxy {}}.
// FIXME: Refactor this and isDerivedFrom to reuse implementation.
AST_MATCHER_P(CXXRecordDecl, hasAnyBase, internal::Matcher<CXXBaseSpecifier>,
BaseSpecMatcher) {
@@ -4609,19 +3319,16 @@ AST_MATCHER_P(CXXRecordDecl, hasAnyBase, internal::Matcher<CXXBaseSpecifier>,
/// Matches C++ classes that have a direct base matching \p BaseSpecMatcher.
///
-/// Given
+/// Example:
+/// matcher hasDirectBase(hasType(cxxRecordDecl(hasName("SpecialBase"))))
/// \code
-/// class Foo {};
+/// class Foo;
/// class Bar : Foo {};
/// class Baz : Bar {};
-/// class SpecialBase {};
+/// class SpecialBase;
/// class Proxy : SpecialBase {}; // matches Proxy
/// class IndirectlyDerived : Proxy {}; // doesn't match
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{cxxRecordDecl(hasDirectBase(hasType(cxxRecordDecl(hasName("SpecialBase")))))}
-/// matches \match{class Proxy : SpecialBase {}}.
AST_MATCHER_P(CXXRecordDecl, hasDirectBase, internal::Matcher<CXXBaseSpecifier>,
BaseSpecMatcher) {
return Node.hasDefinition() &&
@@ -4632,22 +3339,6 @@ AST_MATCHER_P(CXXRecordDecl, hasDirectBase, internal::Matcher<CXXBaseSpecifier>,
/// Similar to \c isDerivedFrom(), but also matches classes that directly
/// match \c Base.
-///
-/// Given
-/// \code
-/// class X {};
-/// class Y : public X {}; // directly derived
-/// class Z : public Y {}; // indirectly derived
-/// typedef X A;
-/// typedef A B;
-/// class C : public B {}; // derived from a typedef of X
-/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{cxxRecordDecl(isSameOrDerivedFrom(cxxRecordDecl(hasName("X"))),
-/// isDefinition())}
-/// matches \match{class X {}}, \match{class Y : public X {}},
-/// \match{class Z : public Y {}} and \match{class C : public B {}}.
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
isSameOrDerivedFrom,
AST_POLYMORPHIC_SUPPORTED_TYPES(CXXRecordDecl, ObjCInterfaceDecl),
@@ -4661,25 +3352,8 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
return Matcher<ObjCInterfaceDecl>(M).matches(*InterfaceDecl, Finder, Builder);
}
-/// Similar to \c isDerivedFrom(), but also matches classes that directly
-/// match \c Base.
/// Overloaded method as shortcut for
/// \c isSameOrDerivedFrom(hasName(...)).
-///
-/// Given
-/// \code
-/// class X {};
-/// class Y : public X {}; // directly derived
-/// class Z : public Y {}; // indirectly derived
-/// typedef X A;
-/// typedef A B;
-/// class C : public B {}; // derived from a typedef of X
-/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{cxxRecordDecl(isSameOrDerivedFrom("X"), isDefinition())}
-/// matches \match{class X {}}, \match{class Y : public X {}},
-/// \match{class Z : public Y {}} and \match{class C : public B {}}.
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
isSameOrDerivedFrom,
AST_POLYMORPHIC_SUPPORTED_TYPES(CXXRecordDecl, ObjCInterfaceDecl),
@@ -4701,30 +3375,22 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
///
/// Note that a class is not considered to be derived from itself.
///
-/// Given
+/// Example matches Y, C (Base == hasName("X"))
/// \code
-/// class X {};
+/// class X;
/// class Y : public X {}; // directly derived
/// class Z : public Y {}; // indirectly derived
/// typedef X A;
/// typedef A B;
/// class C : public B {}; // derived from a typedef of X
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{cxxRecordDecl(isDirectlyDerivedFrom(namedDecl(hasName("X"))))}
-/// matches \match{class Y : public X {}} and \match{class C : public B {}}
-/// (Base == hasName("X").
///
/// In the following example, Bar matches isDerivedFrom(hasName("X")):
/// \code
-/// class Foo {};
+/// class Foo;
/// typedef Foo X;
/// class Bar : public Foo {}; // derived from a type that X is a typedef of
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxRecordDecl(isDerivedFrom(hasName("X")))}
-/// matches \match{class Bar : public Foo {}}.
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
isDirectlyDerivedFrom,
AST_POLYMORPHIC_SUPPORTED_TYPES(CXXRecordDecl, ObjCInterfaceDecl),
@@ -4740,18 +3406,6 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
}
/// Overloaded method as shortcut for \c isDirectlyDerivedFrom(hasName(...)).
-///
-/// Given
-/// \code
-/// struct Base {};
-/// struct DirectlyDerived : public Base {};
-/// struct IndirectlyDerived : public DirectlyDerived {};
-/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{cxxRecordDecl(isDirectlyDerivedFrom("Base"))}
-/// matches \match{struct DirectlyDerived : public Base {}}, but not
-/// \nomatch{struct IndirectlyDerived : public DirectlyDerived {}}.
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
isDirectlyDerivedFrom,
AST_POLYMORPHIC_SUPPORTED_TYPES(CXXRecordDecl, ObjCInterfaceDecl),
@@ -4769,16 +3423,14 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
/// Matches the first method of a class or struct that satisfies \c
/// InnerMatcher.
///
-/// Given
+/// Given:
/// \code
/// class A { void func(); };
/// class B { void member(); };
/// \endcode
-/// \compile_args{-std=c++}
///
-/// The matcher \matcher{cxxRecordDecl(hasMethod(hasName("func")))}
-/// matches the declaration of \match{class A { void func(); }}
-/// but does not match \nomatch{class B { void member(); }}
+/// \c cxxRecordDecl(hasMethod(hasName("func"))) matches the declaration of
+/// \c A but not \c B.
AST_MATCHER_P(CXXRecordDecl, hasMethod, internal::Matcher<CXXMethodDecl>,
InnerMatcher) {
BoundNodesTreeBuilder Result(*Builder);
@@ -4795,14 +3447,13 @@ AST_MATCHER_P(CXXRecordDecl, hasMethod, internal::Matcher<CXXMethodDecl>,
/// Matches the generated class of lambda expressions.
///
-/// Given
+/// Given:
/// \code
/// auto x = []{};
/// \endcode
-/// \compile_args{-std=c++11-or-later}
///
-/// The matcher \matcher{varDecl(hasType(cxxRecordDecl(isLambda())))}
-/// matches \match{auto x = []{}}.
+/// \c cxxRecordDecl(isLambda()) matches the implicit class declaration of
+/// \c decltype(x)
AST_MATCHER(CXXRecordDecl, isLambda) {
return Node.isLambda();
}
@@ -4810,53 +3461,33 @@ AST_MATCHER(CXXRecordDecl, isLambda) {
/// Matches AST nodes that have child AST nodes that match the
/// provided matcher.
///
-/// Given
+/// Example matches X, Y
+/// (matcher = cxxRecordDecl(has(cxxRecordDecl(hasName("X")))
/// \code
/// class X {}; // Matches X, because X::X is a class of name X inside X.
/// class Y { class X {}; };
/// class Z { class Y { class X {}; }; }; // Does not match Z.
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxRecordDecl(has(cxxRecordDecl(hasName("X"))))}
-/// matches \match{count=3$class X {}} three times for the definitions of \c X
-/// that contain the implicit class declarations of \c X ,
-/// and \match{count=2$class Y { class X {}; }} two times for the two different
-/// definitions of \c Y that contain \c X .
///
/// 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:
-///
-/// Given
-/// \code
-/// int x =0;
-/// double y = static_cast<double>(x);
-/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{cxxStaticCastExpr(has(ignoringParenImpCasts(declRefExpr())))}.
-/// matches \match{static_cast<double>(x)}
+/// probably consider using ignoringParenImpCasts like:
+/// has(ignoringParenImpCasts(expr())).
extern const internal::ArgumentAdaptingMatcherFunc<internal::HasMatcher> has;
/// Matches AST nodes that have descendant AST nodes that match the
/// provided matcher.
///
-/// Given
+/// Example matches X, Y, Z
+/// (matcher = cxxRecordDecl(hasDescendant(cxxRecordDecl(hasName("X")))))
/// \code
/// class X {}; // Matches X, because X::X is a class of name X inside X.
/// class Y { class X {}; };
/// class Z { class Y { class X {}; }; };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{cxxRecordDecl(hasDescendant(cxxRecordDecl(hasName("X"))))}
-/// matches \match{count=3$class X {}} three times for the definitions of \c X
-/// that contain the implicit class declarations of \c X ,
-/// \match{count=2$class Y { class X {}; }} two times for the declaration of
-/// \c X they contain, and \match{class Z { class Y { class X {}; }; }}.
///
/// DescendantT must be an AST base type.
///
@@ -4868,24 +3499,19 @@ extern const internal::ArgumentAdaptingMatcherFunc<
/// Matches AST nodes that have child AST nodes that match the
/// provided matcher.
///
-/// Given
+/// Example matches X, Y, Y::X, Z::Y, Z::Y::X
+/// (matcher = cxxRecordDecl(forEach(cxxRecordDecl(hasName("X")))
/// \code
/// class X {};
/// class Y { class X {}; }; // Matches Y, because Y::X is a class of name X
/// // inside Y.
/// class Z { class Y { class X {}; }; }; // Does not match Z.
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxRecordDecl(forEach(cxxRecordDecl(hasName("X"))))}
-/// matches \match{type=typestr$class X},
-/// \match{type=typestr$class Y},
-/// \match{type=typestr$class Y::X},
-/// \match{type=typestr$class Z::Y::X} and \match{type=typestr$class Z::Y}
///
/// ChildT must be an AST base type.
///
/// As opposed to 'has', 'forEach' will cause a match for each result that
-/// matches instead of only on the first one.
+/// matches instead of only on the first one.
///
/// Usable as: Any Matcher
extern const internal::ArgumentAdaptingMatcherFunc<internal::ForEachMatcher>
@@ -4894,21 +3520,14 @@ extern const internal::ArgumentAdaptingMatcherFunc<internal::ForEachMatcher>
/// Matches AST nodes that have descendant AST nodes that match the
/// provided matcher.
///
-/// Given
+/// Example matches X, A, A::X, B, B::C, B::C::X
+/// (matcher = cxxRecordDecl(forEachDescendant(cxxRecordDecl(hasName("X")))))
/// \code
/// class X {};
/// class A { class X {}; }; // Matches A, because A::X is a class of name
/// // X inside A.
/// class B { class C { class X {}; }; };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{cxxRecordDecl(forEachDescendant(cxxRecordDecl(hasName("X"))))}
-/// matches \match{count=3$class X {}} three times, once for each of the
-/// declared classes \c X and their implicit class declaration,
-/// \match{class A { class X {}; }},
-/// \match{class B { class C { class X {}; }; }} and
-/// \match{class C { class X {}; }}.
///
/// DescendantT must be an AST base type.
///
@@ -4916,63 +3535,13 @@ extern const internal::ArgumentAdaptingMatcherFunc<internal::ForEachMatcher>
/// each result that matches instead of only on the first one.
///
/// Note: Recursively combined ForEachDescendant can cause many matches:
+/// cxxRecordDecl(forEachDescendant(cxxRecordDecl(
+/// forEachDescendant(cxxRecordDecl())
+/// )))
+/// will match 10 times (plus injected class name matches) on:
/// \code
-/// struct A {
-/// struct B {
-/// struct C {};
-/// struct D {};
-/// };
-/// };
-///
+/// class A { class B { class C { class D { class E {}; }; }; }; };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxRecordDecl(forEachDescendant(cxxRecordDecl(
-/// forEachDescendant(cxxRecordDecl().bind("inner"))
-/// ).bind("middle")))}
-/// will match 9 times:
-///
-/// It matches the definition of \match{type=name$A} with the definition of
-/// \match{sub=middle;type=name$B} in the middle and the implicit class
-/// declaration of \match{sub=inner;type=name$B} as the innermost \c
-/// cxxRecordDecl.
-///
-/// It matches the definition of \match{type=name$A} with the definition of
-/// \match{sub=middle;type=name$C} in the middle and the definition of
-/// \match{sub=inner;type=name$B} as the innermost \c cxxRecordDecl.
-///
-/// It matches the definition of \match{type=name$A} with the definition of
-/// \match{sub=middle;type=name$C} in the middle and the implicit class
-/// declaration of \match{sub=inner;type=name$B} as the innermost \c
-/// cxxRecordDecl.
-///
-/// It matches the definition of \match{type=name$A} with the definition of
-/// \match{sub=middle;type=name$B} in the middle and the definition of
-/// \match{sub=inner;type=name$D} as the innermost \c cxxRecordDecl.
-///
-/// It matches the definition of \match{type=name$A} with the definition of
-/// \match{sub=middle;type=name$B} in the middle and the implicit class
-/// declaration of \match{sub=inner;type=name$D} as the innermost \c
-/// cxxRecordDecl.
-///
-/// It matches the definition of \match{type=name$A} with the definition of
-/// \match{sub=middle;type=name$C} in the middle and the implicit class
-/// declaration of \match{sub=inner;type=name$C} as the innermost \c
-/// cxxRecordDecl.
-///
-/// It matches the definition of \match{type=name$A} with the definition of
-/// \match{sub=middle;type=name$D} in the middle and the implicit class
-/// declaration of \match{sub=inner;type=name$D} as the innermost \c
-/// cxxRecordDecl.
-///
-/// It matches the definition of \match{type=name$B} with the definition of
-/// \match{sub=middle;type=name$C} in the middle and the implicit class
-/// declaration of \match{sub=inner;type=name$C} as the innermost \c
-/// cxxRecordDecl.
-///
-/// It matches the definition of \match{type=name$B} with the definition of
-/// \match{sub=middle;type=name$D} in the middle and the implicit class
-/// declaration of \match{sub=inner;type=name$D} as the innermost \c
-/// cxxRecordDecl.
///
/// Usable as: Any Matcher
extern const internal::ArgumentAdaptingMatcherFunc<
@@ -4987,14 +3556,12 @@ extern const internal::ArgumentAdaptingMatcherFunc<
/// \code
/// class A { class B {}; class C {}; };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{cxxRecordDecl(hasName("::A"),
-/// findAll(cxxRecordDecl(isDefinition()).bind("m")))}
-/// matches \match{count=3$class A { class B {}; class C {}; }} three times,
-/// with \matcher{type=sub$cxxRecordDecl(isDefinition()).bind("m")}
-/// matching \match{type=name;sub=m$A},
-/// \match{type=name;sub=m$B} and \match{type=name;sub=m$C}.
+/// The matcher:
+/// \code
+/// cxxRecordDecl(hasName("::A"),
+/// findAll(cxxRecordDecl(isDefinition()).bind("m")))
+/// \endcode
+/// will generate results for \c A, \c B and \c C.
///
/// Usable as: Any Matcher
template <typename T>
@@ -5009,9 +3576,7 @@ internal::Matcher<T> findAll(const internal::Matcher<T> &Matcher) {
/// \code
/// void f() { for (;;) { int x = 42; if (true) { int x = 43; } } }
/// \endcode
-/// \compile_args{-std=c++,c23-or-later}
-/// The matcher \matcher{compoundStmt(hasParent(ifStmt()))}
-/// matches \match{{ int x = 43; }}
+/// \c compoundStmt(hasParent(ifStmt())) matches "{ int x = 43; }".
///
/// Usable as: Any Matcher
extern const internal::ArgumentAdaptingMatcherFunc<
@@ -5028,10 +3593,7 @@ extern const internal::ArgumentAdaptingMatcherFunc<
/// void f() { if (true) { int x = 42; } }
/// void g() { for (;;) { int x = 43; } }
/// \endcode
-/// \compile_args{-std=c++,c23-or-later}
-/// The matcher \matcher{expr(integerLiteral(hasAncestor(ifStmt())))}
-/// matches \match{42}
-/// but does not match \nomatch{43}
+/// \c expr(integerLiteral(hasAncestor(ifStmt()))) matches \c 42, but not 43.
///
/// Usable as: Any Matcher
extern const internal::ArgumentAdaptingMatcherFunc<
@@ -5042,20 +3604,17 @@ extern const internal::ArgumentAdaptingMatcherFunc<
/// Matches if the provided matcher does not match.
///
-/// Given
+/// Example matches Y (matcher = cxxRecordDecl(unless(hasName("X"))))
/// \code
-/// int x;
-/// int y = 0;
+/// class X {};
+/// class Y {};
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{varDecl(unless(hasInitializer(expr())))}
-/// matches \match{int x}, but not \nomatch{int y = 0}.
///
/// Usable as: Any Matcher
extern const internal::VariadicOperatorMatcherFunc<1, 1> unless;
/// Matches a node if the declaration associated with that node
-/// matches the given matcher.
+/// matches the given matcher.
///
/// The associated declaration is:
/// - for type nodes, the declaration of the underlying type
@@ -5065,27 +3624,21 @@ extern const internal::VariadicOperatorMatcherFunc<1, 1> unless;
/// - for CXXNewExpr, the declaration of the operator new
/// - for ObjCIvarExpr, the declaration of the ivar
///
-/// Given
+/// For type nodes, hasDeclaration will generally match the declaration of the
+/// sugared type. Given
/// \code
/// class X {};
/// typedef X Y;
/// Y y;
/// \endcode
-/// \compile_args{-std=c++}
-/// For type nodes, hasDeclaration will generally match the declaration of the
-/// sugared type, i.e., the matcher
-/// \matcher{varDecl(hasType(qualType(hasDeclaration(decl().bind("d")))))},
-/// matches \match{Y y}, with
-/// the matcher \matcher{type=sub$decl()} matching
-/// \match{sub=d$typedef X Y;}.
-/// A common use case is to match the underlying, desugared type.
+/// in varDecl(hasType(hasDeclaration(decl()))) the decl will match the
+/// typedefDecl. A common use case is to match the underlying, desugared type.
/// This can be achieved by using the hasUnqualifiedDesugaredType matcher:
-/// \matcher{varDecl(hasType(hasUnqualifiedDesugaredType(
-/// recordType(hasDeclaration(decl().bind("d"))))))}
-/// matches \match{Y y}.
-/// In this matcher, the matcher \matcher{type=sub$decl()} will match the
-/// CXXRecordDecl
-/// \match{sub=d$class X {};}.
+/// \code
+/// varDecl(hasType(hasUnqualifiedDesugaredType(
+/// recordType(hasDeclaration(decl())))))
+/// \endcode
+/// In this matcher, the decl will match the CXXRecordDecl of class X.
///
/// Usable as: Matcher<AddrLabelExpr>, Matcher<CallExpr>,
/// Matcher<CXXConstructExpr>, Matcher<CXXNewExpr>, Matcher<DeclRefExpr>,
@@ -5112,10 +3665,9 @@ hasDeclaration(const internal::Matcher<Decl> &InnerMatcher) {
/// namespace N { template<class T> void f(T t); }
/// template <class T> void g() { using N::f; f(T()); }
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++11-or-later}
-/// The matcher \matcher{unresolvedLookupExpr(hasAnyDeclaration(
-/// namedDecl(hasUnderlyingDecl(hasName("::N::f")))))}
-/// matches \match{f} in \c g().
+/// \c unresolvedLookupExpr(hasAnyDeclaration(
+/// namedDecl(hasUnderlyingDecl(hasName("::N::f")))))
+/// matches the use of \c f in \c g() .
AST_MATCHER_P(NamedDecl, hasUnderlyingDecl, internal::Matcher<NamedDecl>,
InnerMatcher) {
const NamedDecl *UnderlyingDecl = Node.getUnderlyingDecl();
@@ -5134,15 +3686,12 @@ AST_MATCHER_P(NamedDecl, hasUnderlyingDecl, internal::Matcher<NamedDecl>,
/// class X : public Y {};
/// void z(Y y, X x) { y.m(); (g()).m(); x.m(); }
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("Y")))))}
-/// matches \match{y.m()} and \match{(g()).m()}.
-/// The matcher
-/// \matcher{cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("X")))))}
-/// matches \match{x.m()}.
-/// The matcher \matcher{cxxMemberCallExpr(on(callExpr()))}
-/// matches \match{(g()).m()}.
+/// cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("Y")))))
+/// matches `y.m()` and `(g()).m()`.
+/// cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("X")))))
+/// matches `x.m()`.
+/// cxxMemberCallExpr(on(callExpr()))
+/// matches `(g()).m()`.
///
/// FIXME: Overload to allow directly matching types?
AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher<Expr>,
@@ -5153,17 +3702,17 @@ AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher<Expr>,
InnerMatcher.matches(*ExprNode, Finder, Builder));
}
+
/// Matches on the receiver of an ObjectiveC Message expression.
///
+/// Example
+/// matcher = objCMessageExpr(hasReceiverType(asString("UIWebView *")));
+/// matches the [webView ...] message invocation.
/// \code
/// NSString *webViewJavaScript = ...
/// UIWebView *webView = ...
/// [webView stringByEvaluatingJavaScriptFromString:webViewJavascript];
/// \endcode
-/// \compile_args{-ObjC}
-/// The matcher \matcher{objCMessageExpr(hasReceiverType(asString("UIWebView
-/// *")))} matches
-/// \match{[webViewstringByEvaluatingJavaScriptFromString:webViewJavascript];}
AST_MATCHER_P(ObjCMessageExpr, hasReceiverType, internal::Matcher<QualType>,
InnerMatcher) {
const QualType TypeDecl = Node.getReceiverType();
@@ -5172,63 +3721,66 @@ AST_MATCHER_P(ObjCMessageExpr, hasReceiverType, internal::Matcher<QualType>,
/// Returns true when the Objective-C method declaration is a class method.
///
-/// Given
+/// Example
+/// matcher = objcMethodDecl(isClassMethod())
+/// matches
/// \code
/// @interface I + (void)foo; @end
+/// \endcode
+/// but not
+/// \code
/// @interface I - (void)bar; @end
/// \endcode
-/// \compile_args{-ObjC}
-/// The matcher \matcher{objcMethodDecl(isClassMethod())}
-/// matches \match{@interface I + (void)foo; @end}
-/// but does not match \nomatch{interface I + (void)foo; @end}
AST_MATCHER(ObjCMethodDecl, isClassMethod) {
return Node.isClassMethod();
}
/// Returns true when the Objective-C method declaration is an instance method.
///
-/// Given
+/// Example
+/// matcher = objcMethodDecl(isInstanceMethod())
+/// matches
/// \code
/// @interface I - (void)bar; @end
+/// \endcode
+/// but not
+/// \code
/// @interface I + (void)foo; @end
/// \endcode
-/// \compile_args{-ObjC}
-/// The matcher \matcher{objcMethodDecl(isInstanceMethod())}
-/// matches \match{@interface I - (void)bar; @end}
-/// but does not match \nomatch{@interface I - (void)foo; @end}
-/// \compile_args{-ObjC}
AST_MATCHER(ObjCMethodDecl, isInstanceMethod) {
return Node.isInstanceMethod();
}
/// Returns true when the Objective-C message is sent to a class.
///
-/// Given
+/// Example
+/// matcher = objcMessageExpr(isClassMessage())
+/// matches
/// \code
/// [NSString stringWithFormat:@"format"];
+/// \endcode
+/// but not
+/// \code
/// NSString *x = @"hello";
/// [x containsString:@"h"];
/// \endcode
-/// \compile_args{-ObjC}
-/// The matcher \matcher{objcMessageExpr(isClassMessage())}
-/// matches \match{[NSString stringWithFormat:@"format"];}
-/// but does not match \nomatch{[[x containsString:@"h"]}
AST_MATCHER(ObjCMessageExpr, isClassMessage) {
return Node.isClassMessage();
}
/// Returns true when the Objective-C message is sent to an instance.
///
-/// Given
+/// Example
+/// matcher = objcMessageExpr(isInstanceMessage())
+/// matches
/// \code
/// NSString *x = @"hello";
/// [x containsString:@"h"];
+/// \endcode
+/// but not
+/// \code
/// [NSString stringWithFormat:@"format"];
/// \endcode
-/// \compile_args{-ObjC}
-/// The matcher \matcher{objcMessageExpr(isInstanceMessage())}
-/// matches \match{[x containsString:@"h"];}
-/// but does not match \nomatch{[NSString stringWithFormat:@"format"];}
AST_MATCHER(ObjCMessageExpr, isInstanceMessage) {
return Node.isInstanceMessage();
}
@@ -5236,15 +3788,13 @@ AST_MATCHER(ObjCMessageExpr, isInstanceMessage) {
/// Matches if the Objective-C message is sent to an instance,
/// and the inner matcher matches on that instance.
///
-/// Given
+/// For example the method call in
/// \code
/// NSString *x = @"hello";
/// [x containsString:@"h"];
/// \endcode
-/// \compile_args{-ObjC}
-/// The matcher
-/// \matcher{objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x"))))))}
-/// matches \match{[x containsString:@"h"];}
+/// is matched by
+/// objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x"))))))
AST_MATCHER_P(ObjCMessageExpr, hasReceiver, internal::Matcher<Expr>,
InnerMatcher) {
const Expr *ReceiverNode = Node.getInstanceReceiver();
@@ -5255,14 +3805,12 @@ AST_MATCHER_P(ObjCMessageExpr, hasReceiver, internal::Matcher<Expr>,
/// Matches when BaseName == Selector.getAsString()
///
+/// matcher = objCMessageExpr(hasSelector("loadHTMLString:baseURL:"));
+/// matches the outer message expr in the code below, but NOT the message
+/// invocation for self.bodyView.
/// \code
/// [self.bodyView loadHTMLString:html baseURL:NULL];
/// \endcode
-/// \compile_args{-ObjC}
-/// The matcher
-/// \matcher{objCMessageExpr(hasSelector("loadHTMLString:baseURL:"));} matches
-/// the outer message expr in the code below, but NOT the message invocation
-/// for self.bodyView.
AST_MATCHER_P(ObjCMessageExpr, hasSelector, std::string, BaseName) {
Selector Sel = Node.getSelector();
return BaseName == Sel.getAsString();
@@ -5271,13 +3819,12 @@ AST_MATCHER_P(ObjCMessageExpr, hasSelector, std::string, BaseName) {
/// Matches when at least one of the supplied string equals to the
/// Selector.getAsString()
///
+/// matcher = objCMessageExpr(hasSelector("methodA:", "methodB:"));
+/// matches both of the expressions below:
/// \code
/// [myObj methodA:argA];
/// [myObj methodB:argB];
/// \endcode
-/// \compile_args{-ObjC}
-/// The matcher \matcher{objCMessageExpr(hasSelector("methodA:", "methodB:"));}
-/// matches \match{[myObj methodA:argA];} and \match{[myObj methodB:argB];}
extern const internal::VariadicFunction<internal::Matcher<ObjCMessageExpr>,
StringRef,
internal::hasAnySelectorFunc>
@@ -5285,17 +3832,12 @@ extern const internal::VariadicFunction<internal::Matcher<ObjCMessageExpr>,
/// Matches ObjC selectors whose name contains
/// a substring matched by the given RegExp.
-///
-/// Given
+/// matcher = objCMessageExpr(matchesSelector("loadHTMLString\:baseURL?"));
+/// matches the outer message expr in the code below, but NOT the message
+/// invocation for self.bodyView.
/// \code
/// [self.bodyView loadHTMLString:html baseURL:NULL];
/// \endcode
-/// \compile_args{-ObjC}
-///
-/// The matcher
-/// \matcher{objCMessageExpr(matchesSelector("loadHTMLString\:baseURL?"))}
-/// matches the outer message expr in the code below, but NOT the message
-/// invocation for self.bodyView.
AST_MATCHER_REGEX(ObjCMessageExpr, matchesSelector, RegExp) {
std::string SelectorString = Node.getSelector().getAsString();
return RegExp->match(SelectorString);
@@ -5311,22 +3853,21 @@ AST_MATCHER(ObjCMessageExpr, hasNullSelector) {
/// Matches when the selector is a Unary Selector
///
-/// Given
+/// matcher = objCMessageExpr(matchesSelector(hasUnarySelector());
+/// matches self.bodyView in the code below, but NOT the outer message
+/// invocation of "loadHTMLString:baseURL:".
/// \code
/// [self.bodyView loadHTMLString:html baseURL:NULL];
-/// \endcode
-/// \compile_args{-ObjC}
-///
-/// The matcher \matcher{objCMessageExpr(matchesSelector(hasUnarySelector());}
-/// matches \match{self.bodyView}, but does not match the outer message
-/// invocation of "loadHTMLString:baseURL:".
+/// \endcode
AST_MATCHER(ObjCMessageExpr, hasUnarySelector) {
return Node.getSelector().isUnarySelector();
}
/// Matches when the selector is a keyword selector
///
-/// Given
+/// objCMessageExpr(hasKeywordSelector()) matches the generated setFrame
+/// message expression in
+///
/// \code
/// UIWebView *webView = ...;
/// CGRect bodyFrame = webView.frame;
@@ -5334,25 +3875,21 @@ AST_MATCHER(ObjCMessageExpr, hasUnarySelector) {
/// webView.frame = bodyFrame;
/// // ^---- matches here
/// \endcode
-/// \compile_args{-ObjC}
-///
-/// The matcher \matcher{objCMessageExpr(hasKeywordSelector())} matches the
-/// generated setFrame message expression in
AST_MATCHER(ObjCMessageExpr, hasKeywordSelector) {
return Node.getSelector().isKeywordSelector();
}
/// Matches when the selector has the specified number of arguments
///
+/// matcher = objCMessageExpr(numSelectorArgs(0));
+/// matches self.bodyView in the code below
+///
+/// matcher = objCMessageExpr(numSelectorArgs(2));
+/// matches the invocation of "loadHTMLString:baseURL:" but not that
+/// of self.bodyView
/// \code
/// [self.bodyView loadHTMLString:html baseURL:NULL];
/// \endcode
-/// \compile_args{-ObjC}
-/// The matcher \matcher{objCMessageExpr(numSelectorArgs(0))}
-/// matches \match{self.bodyView}.
-/// The matcher \matcher{objCMessageExpr(numSelectorArgs(2))}
-/// matches the invocation of \match{loadHTMLString:baseURL:}
-/// but does not match \nomatch{self.bodyView}
AST_MATCHER_P(ObjCMessageExpr, numSelectorArgs, unsigned, N) {
return Node.getSelector().getNumArgs() == N;
}
@@ -5364,21 +3901,13 @@ AST_MATCHER_P(ObjCMessageExpr, numSelectorArgs, unsigned, N) {
/// class Y { void x() { this->x(); x(); Y y; y.x(); } };
/// void f() { f(); }
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{callExpr(callee(expr().bind("callee")))}
-/// matches \match{this->x()}, \match{x()}, \match{y.x()}, \match{f()}
-/// with \matcher{type=sub$expr()} inside of \c callee
-/// matching \match{sub=callee$this->x}, \match{sub=callee$x},
-/// \match{sub=callee$y.x}, \match{sub=callee$f} respectively
+/// callExpr(callee(expr()))
+/// matches this->x(), x(), y.x(), f()
+/// with callee(...)
+/// matching this->x, x, y.x, f respectively
///
/// Given
/// \code
-/// struct Dummy {};
-/// // makes sure there is a callee, otherwise there would be no callee,
-/// // just a builtin operator
-/// Dummy operator+(Dummy, Dummy);
-/// // not defining a '*' operator
-///
/// template <typename... Args>
/// auto sum(Args... args) {
/// return (0 + ... + args);
@@ -5389,14 +3918,10 @@ AST_MATCHER_P(ObjCMessageExpr, numSelectorArgs, unsigned, N) {
/// return (args * ... * 1);
/// }
/// \endcode
-/// \compile_args{-std=c++17-or-later}
-/// The matcher \matcher{cxxFoldExpr(callee(expr().bind("op")))}
-/// matches \match{(0 + ... + args)}
-/// with \matcher{type=sub$callee(...)} matching \match{sub=op$*},
-/// but does not match \nomatch{(args * ... * 1)}.
-/// A \c CXXFoldExpr only has an \c UnresolvedLookupExpr as a callee.
-/// When there are no define operators that could be used instead of builtin
-/// ones, then there will be no \c callee .
+/// cxxFoldExpr(callee(expr()))
+/// matches (args * ... * 1)
+/// with callee(...)
+/// matching *
///
/// Note: Callee cannot take the more general internal::Matcher<Expr>
/// because this introduces ambiguous overloads with calls to Callee taking a
@@ -5415,16 +3940,16 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(callee,
/// given matcher; or 2) if the Obj-C message expression's callee's method
/// declaration matches the given matcher.
///
-/// Example 1
+/// Example matches y.x() (matcher = callExpr(callee(
+/// cxxMethodDecl(hasName("x")))))
/// \code
/// class Y { public: void x(); };
/// void z() { Y y; y.x(); }
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{callExpr(callee(cxxMethodDecl(hasName("x"))))}
-/// matches \match{y.x()}
///
-/// Example 2
+/// Example 2. Matches [I foo] with
+/// objcMessageExpr(callee(objcMethodDecl(hasName("foo"))))
+///
/// \code
/// @interface I: NSObject
/// +(void)foo;
@@ -5432,10 +3957,6 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(callee,
/// ...
/// [I foo]
/// \endcode
-/// \compile_args{-ObjC}
-/// The matcher
-/// \matcher{objcMessageExpr(callee(objcMethodDecl(hasName("foo"))))}
-/// matches \match{[I foo]}
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
callee, AST_POLYMORPHIC_SUPPORTED_TYPES(ObjCMessageExpr, CallExpr),
internal::Matcher<Decl>, InnerMatcher, 1) {
@@ -5455,7 +3976,12 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
/// Matches if the expression's or declaration's type matches a type
/// matcher.
///
-/// Exmaple
+/// Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
+/// and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
+/// and U (matcher = typedefDecl(hasType(asString("int")))
+/// and friend class X (matcher = friendDecl(hasType("X"))
+/// and public virtual X (matcher = cxxBaseSpecifier(hasType(
+/// asString("class X")))
/// \code
/// class X {};
/// void y(X &x) { x; X z; }
@@ -5463,19 +3989,6 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
/// class Y { friend class X; };
/// class Z : public virtual X {};
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{expr(hasType(cxxRecordDecl(hasName("X"))))}
-/// matches \match{x} and \match{z}.
-/// The matcher \matcher{varDecl(hasType(cxxRecordDecl(hasName("X"))))}
-/// matches \match{X z}
-/// The matcher \matcher{typedefDecl(hasType(asString("int")))}
-/// matches \match{typedef int U}
-/// The matcher \matcher{friendDecl(hasType(asString("class X")))}
-/// matches \match{friend class X}
-/// The matcher \matcher{cxxRecordDecl(hasAnyBase(cxxBaseSpecifier(hasType(
-/// asString("X"))).bind("b")))} matches \match{class Z : public virtual X {}},
-/// with \matcher{type=sub$cxxBaseSpecifier(...)}
-/// matching \match{sub=b$public virtual X}.
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
hasType,
AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, FriendDecl, TypedefNameDecl,
@@ -5496,34 +4009,24 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
/// X, while varDecl(hasType(cxxRecordDecl(hasName("X")))) matches the
/// declaration of x.
///
+/// Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
+/// and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
+/// and friend class X (matcher = friendDecl(hasType("X"))
+/// and public virtual X (matcher = cxxBaseSpecifier(hasType(
+/// cxxRecordDecl(hasName("X"))))
/// \code
/// class X {};
/// void y(X &x) { x; X z; }
/// class Y { friend class X; };
/// class Z : public virtual X {};
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{expr(hasType(cxxRecordDecl(hasName("X"))))}
-/// matches \match{x} and \match{z}.
-/// The matcher \matcher{varDecl(hasType(cxxRecordDecl(hasName("X"))))}
-/// matches \match{X z}.
-/// The matcher \matcher{friendDecl(hasType(asString("class X")))}
-/// matches \match{friend class X}.
-/// The matcher \matcher{cxxRecordDecl(hasAnyBase(cxxBaseSpecifier(hasType(
-/// asString("X"))).bind("b")))} matches
-/// \match{class Z : public virtual X {}},
-/// with \matcher{type=sub$cxxBaseSpecifier(...)}
-/// matching \match{sub=b$public virtual X}.
///
-/// Given
+/// Example matches class Derived
+/// (matcher = cxxRecordDecl(hasAnyBase(hasType(cxxRecordDecl(hasName("Base"))))))
/// \code
/// class Base {};
/// class Derived : Base {};
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{cxxRecordDecl(hasAnyBase(hasType(cxxRecordDecl(hasName("Base")))))}
-/// matches \match{class Derived : Base {}}.
///
/// Usable as: Matcher<Expr>, Matcher<FriendDecl>, Matcher<ValueDecl>,
/// Matcher<CXXBaseSpecifier>
@@ -5540,32 +4043,25 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
/// Matches if the type location of a node matches the inner matcher.
///
-/// Given
+/// Examples:
/// \code
/// int x;
/// \endcode
-/// The matcher \matcher{declaratorDecl(hasTypeLoc(loc(asString("int"))))}
-/// matches \match{int x}.
+/// declaratorDecl(hasTypeLoc(loc(asString("int"))))
+/// matches int x
///
-/// Given
/// \code
-/// struct point { point(double, double); };
-/// point p = point(1.0, -1.0);
+/// auto x = int(3);
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("point"))))}
-/// matches \match{point(1.0, -1.0)}.
+/// cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("int"))))
+/// matches int(3)
///
-/// Given
/// \code
/// struct Foo { Foo(int, int); };
-/// Foo x = Foo(1, 2);
+/// auto x = Foo(1, 2);
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxTemporaryObjectExpr(hasTypeLoc(
-/// loc(asString("Foo"))))}
-/// matches \match{Foo(1, 2)}.
+/// cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo"))))
+/// matches Foo(1, 2)
///
/// Usable as: Matcher<BlockDecl>, Matcher<CXXBaseSpecifier>,
/// Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>,
@@ -5598,25 +4094,22 @@ AST_POLYMORPHIC_MATCHER_P(
/// class Y { public: void x(); };
/// void z() { Y* y; y->x(); }
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxMemberCallExpr(on(hasType(asString("Y *"))))}
-/// matches \match{y->x()}
+/// cxxMemberCallExpr(on(hasType(asString("class Y *"))))
+/// matches y->x()
AST_MATCHER_P(QualType, asString, std::string, Name) {
return Name == Node.getAsString();
}
/// Matches if the matched type is a pointer type and the pointee type
-/// matches the specified matcher.
+/// matches the specified matcher.
///
-/// Given
+/// Example matches y->x()
+/// (matcher = cxxMemberCallExpr(on(hasType(pointsTo
+/// cxxRecordDecl(hasName("Y")))))))
/// \code
/// class Y { public: void x(); };
/// void z() { Y *y; y->x(); }
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxMemberCallExpr(on(hasType(pointsTo(
-/// qualType()))))}
-/// matches \match{y->x()}
AST_MATCHER_P(
QualType, pointsTo, internal::Matcher<QualType>,
InnerMatcher) {
@@ -5624,19 +4117,7 @@ AST_MATCHER_P(
InnerMatcher.matches(Node->getPointeeType(), Finder, Builder));
}
-/// Matches if the matched type is a pointer type and the pointee type
-/// matches the specified matcher.
/// Overloaded to match the pointee type's declaration.
-///
-/// Given
-/// \code
-/// class Y { public: void x(); };
-/// void z() { Y *y; y->x(); }
-/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxMemberCallExpr(on(hasType(pointsTo(
-/// cxxRecordDecl(hasName("Y"))))))}
-/// matches \match{y->x()}
AST_MATCHER_P_OVERLOAD(QualType, pointsTo, internal::Matcher<Decl>,
InnerMatcher, 1) {
return pointsTo(qualType(hasDeclaration(InnerMatcher)))
@@ -5650,12 +4131,9 @@ AST_MATCHER_P_OVERLOAD(QualType, pointsTo, internal::Matcher<Decl>,
/// \code
/// class A {};
/// using B = A;
-/// B b;
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher
-/// \matcher{varDecl(hasType(hasUnqualifiedDesugaredType(recordType())))}
-/// matches \match{B b}.
+/// The matcher type(hasUnqualifiedDesugaredType(recordType())) matches
+/// both B and A.
AST_MATCHER_P(Type, hasUnqualifiedDesugaredType, internal::Matcher<Type>,
InnerMatcher) {
return InnerMatcher.matches(*Node.getUnqualifiedDesugaredType(), Finder,
@@ -5665,7 +4143,8 @@ AST_MATCHER_P(Type, hasUnqualifiedDesugaredType, internal::Matcher<Type>,
/// Matches if the matched type is a reference type and the referenced
/// type matches the specified matcher.
///
-/// Given
+/// Example matches X &x and const X &y
+/// (matcher = varDecl(hasType(references(cxxRecordDecl(hasName("X"))))))
/// \code
/// class X {
/// void a(X b) {
@@ -5674,29 +4153,24 @@ AST_MATCHER_P(Type, hasUnqualifiedDesugaredType, internal::Matcher<Type>,
/// }
/// };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{varDecl(hasType(references(qualType())))} matches
-/// \match{X &x = b} and \match{const X &y = b}.
-AST_MATCHER_P(QualType, references, internal::Matcher<QualType>, InnerMatcher) {
+AST_MATCHER_P(QualType, references, internal::Matcher<QualType>,
+ InnerMatcher) {
return (!Node.isNull() && Node->isReferenceType() &&
InnerMatcher.matches(Node->getPointeeType(), Finder, Builder));
}
/// Matches QualTypes whose canonical type matches InnerMatcher.
///
-/// Given
+/// Given:
/// \code
/// typedef int &int_ref;
/// int a;
/// int_ref b = a;
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{varDecl(hasType(qualType(referenceType())))}
-/// does not match \nomatch{int_ref b = a},
-/// but the matcher
-/// \matcher{varDecl(hasType(qualType(hasCanonicalType(referenceType()))))}
-/// does match \match{int_ref b = a}.
+///
+/// \c varDecl(hasType(qualType(referenceType()))))) will not match the
+/// declaration of b but \c
+/// varDecl(hasType(qualType(hasCanonicalType(referenceType())))))) does.
AST_MATCHER_P(QualType, hasCanonicalType, internal::Matcher<QualType>,
InnerMatcher) {
if (Node.isNull())
@@ -5704,23 +4178,7 @@ AST_MATCHER_P(QualType, hasCanonicalType, internal::Matcher<QualType>,
return InnerMatcher.matches(Node.getCanonicalType(), Finder, Builder);
}
-/// Matches if the matched type is a reference type and the referenced
-/// type matches the specified matcher.
/// Overloaded to match the referenced type's declaration.
-///
-/// Given
-/// \code
-/// class X {
-/// void a(X b) {
-/// X &x = b;
-/// const X &y = b;
-/// }
-/// };
-/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{varDecl(hasType(references(cxxRecordDecl(hasName("X")))))} matches
-/// \match{X &x = b} and \match{const X &y = b}.
AST_MATCHER_P_OVERLOAD(QualType, references, internal::Matcher<Decl>,
InnerMatcher, 1) {
return references(qualType(hasDeclaration(InnerMatcher)))
@@ -5734,17 +4192,14 @@ AST_MATCHER_P_OVERLOAD(QualType, references, internal::Matcher<Decl>,
/// \code
/// class Y { public: void m(); };
/// Y g();
-/// class X : public Y { public: void g(); };
+/// class X : public Y { void g(); };
/// void z(Y y, X x) { y.m(); x.m(); x.g(); (g()).m(); }
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxMemberCallExpr(onImplicitObjectArgument(hasType(
-/// cxxRecordDecl(hasName("Y")))))}
-/// matches \match{y.m()}, \match{x.m()} and \match{(g()).m()}
-/// but does not match \nomatch{x.g()}.
-/// The matcher \matcher{cxxMemberCallExpr(on(callExpr()))}
-/// only matches \match{(g()).m()}, because the parens are ignored.
-/// FIXME: should they be ignored? (ignored bc of `on`)
+/// cxxMemberCallExpr(onImplicitObjectArgument(hasType(
+/// cxxRecordDecl(hasName("Y")))))
+/// matches `y.m()`, `x.m()` and (`g()).m()`, but not `x.g()`).
+/// cxxMemberCallExpr(on(callExpr()))
+/// only matches `(g()).m()` (the parens are ignored).
///
/// FIXME: Overload to allow directly matching types?
AST_MATCHER_P(CXXMemberCallExpr, onImplicitObjectArgument,
@@ -5755,20 +4210,21 @@ AST_MATCHER_P(CXXMemberCallExpr, onImplicitObjectArgument,
}
/// Matches if the type of the expression's implicit object argument either
-/// matches the InnerMatcher, or is a pointer to a type that matches the
+/// matches the InnerMatcher, or is a pointer to a type that matches the
/// InnerMatcher.
///
/// Given
/// \code
-/// class Y { public: void m() const; };
-/// class X : public Y { public: void g(); };
-/// void z() { const Y y; y.m(); const Y *p; p->m(); X x; x.m(); x.g(); }
+/// class Y { public: void m(); };
+/// class X : public Y { void g(); };
+/// void z() { Y y; y.m(); Y *p; p->m(); X x; x.m(); x.g(); }
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{cxxMemberCallExpr(thisPointerType(isConstQualified()))}
-/// matches \match{y.m()}, \match{x.m()} and \match{p->m()},
-/// but not \nomatch{x.g()}.
+/// cxxMemberCallExpr(thisPointerType(hasDeclaration(
+/// cxxRecordDecl(hasName("Y")))))
+/// matches `y.m()`, `p->m()` and `x.m()`.
+/// cxxMemberCallExpr(thisPointerType(hasDeclaration(
+/// cxxRecordDecl(hasName("X")))))
+/// matches `x.g()`.
AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, thisPointerType,
internal::Matcher<QualType>, InnerMatcher, 0) {
return onImplicitObjectArgument(
@@ -5777,20 +4233,6 @@ AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, thisPointerType,
}
/// Overloaded to match the type's declaration.
-///
-/// Given
-/// \code
-/// class Y { public: void m(); };
-/// class X : public Y { public: void g(); };
-/// void z() { Y y; y.m(); Y *p; p->m(); X x; x.m(); x.g(); }
-/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxMemberCallExpr(thisPointerType(
-/// cxxRecordDecl(hasName("Y"))))}
-/// matches \match{y.m()}, \match{p->m()} and \match{x.m()}.
-/// The matcher \matcher{cxxMemberCallExpr(thisPointerType(
-/// cxxRecordDecl(hasName("X"))))}
-/// matches \match{x.g()}.
AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, thisPointerType,
internal::Matcher<Decl>, InnerMatcher, 1) {
return onImplicitObjectArgument(
@@ -5801,17 +4243,14 @@ AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, thisPointerType,
/// Matches a DeclRefExpr that refers to a declaration that matches the
/// specified matcher.
///
-/// Given
+/// Example matches x in if(x)
+/// (matcher = declRefExpr(to(varDecl(hasName("x")))))
/// \code
-/// void foo() {
-/// bool x;
-/// if (x) {}
-/// }
+/// bool x;
+/// if (x) {}
/// \endcode
-/// \compile_args{-std=c++,c23-or-later}
-/// The matcher \matcher{declRefExpr(to(varDecl(hasName("x"))))}
-/// matches \match{x} inside the condition of the if-stmt.
-AST_MATCHER_P(DeclRefExpr, to, internal::Matcher<Decl>, InnerMatcher) {
+AST_MATCHER_P(DeclRefExpr, to, internal::Matcher<Decl>,
+ InnerMatcher) {
const Decl *DeclNode = Node.getDecl();
return (DeclNode != nullptr &&
InnerMatcher.matches(*DeclNode, Finder, Builder));
@@ -5820,24 +4259,22 @@ AST_MATCHER_P(DeclRefExpr, to, internal::Matcher<Decl>, InnerMatcher) {
/// Matches if a node refers to a declaration through a specific
/// using shadow declaration.
///
-/// Given
+/// Examples:
/// \code
/// namespace a { int f(); }
/// using a::f;
/// int x = f();
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{declRefExpr(throughUsingDecl(anything()))}
-/// matches \match{f}
+/// declRefExpr(throughUsingDecl(anything()))
+/// matches \c f
///
/// \code
/// namespace a { class X{}; }
/// using a::X;
/// X x;
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{typeLoc(loc(usingType(throughUsingDecl(anything()))))}
-/// matches \match{X}
+/// typeLoc(loc(usingType(throughUsingDecl(anything()))))
+/// matches \c X
///
/// Usable as: Matcher<DeclRefExpr>, Matcher<UsingType>
AST_POLYMORPHIC_MATCHER_P(throughUsingDecl,
@@ -5862,11 +4299,9 @@ AST_POLYMORPHIC_MATCHER_P(throughUsingDecl,
/// bar(t);
/// }
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{unresolvedLookupExpr(hasAnyDeclaration(
-/// functionTemplateDecl(hasName("foo"))))}
-/// matches \match{foo} in \c foo(t);
-/// but does not match \nomatch{bar} in \c bar(t);
+/// unresolvedLookupExpr(hasAnyDeclaration(
+/// functionTemplateDecl(hasName("foo"))))
+/// matches \c foo in \c foo(t); but not \c bar in \c bar(t);
AST_MATCHER_P(OverloadExpr, hasAnyDeclaration, internal::Matcher<Decl>,
InnerMatcher) {
return matchesFirstInPointerRange(InnerMatcher, Node.decls_begin(),
@@ -5878,14 +4313,11 @@ AST_MATCHER_P(OverloadExpr, hasAnyDeclaration, internal::Matcher<Decl>,
///
/// Given
/// \code
-/// void foo() {
-/// int a, b;
-/// int c;
-/// }
+/// int a, b;
+/// int c;
/// \endcode
-/// The matcher \matcher{declStmt(hasSingleDecl(anything()))}
-/// matches \match{int c;}
-/// but does not match \nomatch{int a, b;}
+/// declStmt(hasSingleDecl(anything()))
+/// matches 'int c;' but not 'int a, b;'.
AST_MATCHER_P(DeclStmt, hasSingleDecl, internal::Matcher<Decl>, InnerMatcher) {
if (Node.isSingleDecl()) {
const Decl *FoundDecl = Node.getSingleDecl();
@@ -5897,15 +4329,11 @@ AST_MATCHER_P(DeclStmt, hasSingleDecl, internal::Matcher<Decl>, InnerMatcher) {
/// Matches a variable declaration that has an initializer expression
/// that matches the given matcher.
///
-/// Given
+/// Example matches x (matcher = varDecl(hasInitializer(callExpr())))
/// \code
-/// int y() { return 0; }
-/// void foo() {
-/// int x = y();
-/// }
+/// bool y() { return true; }
+/// bool x = y();
/// \endcode
-/// The matcher \matcher{varDecl(hasInitializer(callExpr()))}
-/// matches \match{int x = y()}
AST_MATCHER_P(
VarDecl, hasInitializer, internal::Matcher<Expr>,
InnerMatcher) {
@@ -5917,13 +4345,10 @@ AST_MATCHER_P(
/// Matches a variable serving as the implicit variable for a lambda init-
/// capture.
///
-/// Given
+/// Example matches x (matcher = varDecl(isInitCapture()))
/// \code
-/// auto f = [x = 3]() { return x; };
+/// auto f = [x=3]() { return x; };
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{varDecl(isInitCapture())}
-/// matches \match{x = 3}.
AST_MATCHER(VarDecl, isInitCapture) { return Node.isInitCapture(); }
/// Matches each lambda capture in a lambda expression.
@@ -5931,19 +4356,14 @@ AST_MATCHER(VarDecl, isInitCapture) { return Node.isInitCapture(); }
/// Given
/// \code
/// int main() {
-/// int x;
-/// int y;
+/// int x, y;
/// float z;
/// auto f = [=]() { return x + y + z; };
/// }
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{lambdaExpr(forEachLambdaCapture(
-/// lambdaCapture(capturesVar(
-/// varDecl(hasType(isInteger())).bind("captured")))))}
-/// matches \match{count=2$[=]() { return x + y + z; }} two times,
-/// with \matcher{type=sub$varDecl(hasType(isInteger()))} matching
-/// \match{sub=captured$int x} and \match{sub=captured$int y}.
+/// lambdaExpr(forEachLambdaCapture(
+/// lambdaCapture(capturesVar(varDecl(hasType(isInteger()))))))
+/// will trigger two matches, binding for 'x' and 'y' respectively.
AST_MATCHER_P(LambdaExpr, forEachLambdaCapture,
internal::Matcher<LambdaCapture>, InnerMatcher) {
BoundNodesTreeBuilder Result;
@@ -5963,7 +4383,7 @@ AST_MATCHER_P(LambdaExpr, forEachLambdaCapture,
/// \brief Matches a static variable with local scope.
///
-/// Given
+/// Example matches y (matcher = varDecl(isStaticLocal()))
/// \code
/// void f() {
/// int x;
@@ -5971,8 +4391,6 @@ AST_MATCHER_P(LambdaExpr, forEachLambdaCapture,
/// }
/// static int z;
/// \endcode
-/// The matcher \matcher{varDecl(isStaticLocal())}
-/// matches \match{static int y}.
AST_MATCHER(VarDecl, isStaticLocal) {
return Node.isStaticLocal();
}
@@ -5980,7 +4398,7 @@ AST_MATCHER(VarDecl, isStaticLocal) {
/// Matches a variable declaration that has function scope and is a
/// non-static local variable.
///
-/// Given
+/// Example matches x (matcher = varDecl(hasLocalStorage())
/// \code
/// void f() {
/// int x;
@@ -5988,15 +4406,13 @@ AST_MATCHER(VarDecl, isStaticLocal) {
/// }
/// int z;
/// \endcode
-/// The matcher \matcher{varDecl(hasLocalStorage())}
-/// matches \match{int x}.
AST_MATCHER(VarDecl, hasLocalStorage) {
return Node.hasLocalStorage();
}
/// Matches a variable declaration that does not have local storage.
///
-/// Given
+/// Example matches y and z (matcher = varDecl(hasGlobalStorage())
/// \code
/// void f() {
/// int x;
@@ -6004,15 +4420,14 @@ AST_MATCHER(VarDecl, hasLocalStorage) {
/// }
/// int z;
/// \endcode
-/// The matcher \matcher{varDecl(hasGlobalStorage())}
-/// matches \match{static int y} and \match{int z}.
AST_MATCHER(VarDecl, hasGlobalStorage) {
return Node.hasGlobalStorage();
}
/// Matches a variable declaration that has automatic storage duration.
///
-/// Given
+/// Example matches x, but not y, z, or a.
+/// (matcher = varDecl(hasAutomaticStorageDuration())
/// \code
/// void f() {
/// int x;
@@ -6021,11 +4436,6 @@ AST_MATCHER(VarDecl, hasGlobalStorage) {
/// }
/// int a;
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{varDecl(hasAutomaticStorageDuration())}
-/// matches \match{int x}
-/// but does not match \nomatch{static int y}, \nomatch{thread_local int z} or
-/// \nomatch{int a}
AST_MATCHER(VarDecl, hasAutomaticStorageDuration) {
return Node.getStorageDuration() == SD_Automatic;
}
@@ -6043,18 +4453,17 @@ AST_MATCHER(VarDecl, hasAutomaticStorageDuration) {
/// int a;
/// static int b;
/// extern int c;
+/// varDecl(hasStaticStorageDuration())
+/// matches the function declaration y, a, b and c.
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{varDecl(hasStaticStorageDuration())}
-/// matches \match{static int y}, \match{int a}, \match{static int b} and
-/// \match{extern int c}
AST_MATCHER(VarDecl, hasStaticStorageDuration) {
return Node.getStorageDuration() == SD_Static;
}
/// Matches a variable declaration that has thread storage duration.
///
-/// Given
+/// Example matches z, but not x, z, or a.
+/// (matcher = varDecl(hasThreadStorageDuration())
/// \code
/// void f() {
/// int x;
@@ -6063,10 +4472,6 @@ AST_MATCHER(VarDecl, hasStaticStorageDuration) {
/// }
/// int a;
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{varDecl(hasThreadStorageDuration())}
-/// matches \match{thread_local int z}
-/// but does not match \nomatch{int x} or \nomatch{type=name$a}.
AST_MATCHER(VarDecl, hasThreadStorageDuration) {
return Node.getStorageDuration() == SD_Thread;
}
@@ -6074,7 +4479,7 @@ AST_MATCHER(VarDecl, hasThreadStorageDuration) {
/// Matches a variable declaration that is an exception variable from
/// a C++ catch block, or an Objective-C \@catch statement.
///
-/// Given
+/// Example matches x (matcher = varDecl(isExceptionVariable())
/// \code
/// void f(int y) {
/// try {
@@ -6082,9 +4487,6 @@ AST_MATCHER(VarDecl, hasThreadStorageDuration) {
/// }
/// }
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{varDecl(isExceptionVariable())}
-/// matches \match{int x}.
AST_MATCHER(VarDecl, isExceptionVariable) {
return Node.isExceptionVariable();
}
@@ -6092,15 +4494,11 @@ AST_MATCHER(VarDecl, isExceptionVariable) {
/// Checks that a call expression or a constructor call expression has
/// a specific number of arguments (including absent default arguments).
///
-/// Given
+/// Example matches f(0, 0) (matcher = callExpr(argumentCountIs(2)))
/// \code
/// void f(int x, int y);
-/// void foo() {
-/// f(0, 0);
-/// }
+/// f(0, 0);
/// \endcode
-/// The matcher \matcher{callExpr(argumentCountIs(2))}
-/// matches \match{f(0, 0)}.
AST_POLYMORPHIC_MATCHER_P(argumentCountIs,
AST_POLYMORPHIC_SUPPORTED_TYPES(
CallExpr, CXXConstructExpr,
@@ -6120,17 +4518,14 @@ AST_POLYMORPHIC_MATCHER_P(argumentCountIs,
/// Checks that a call expression or a constructor call expression has at least
/// the specified number of arguments (including absent default arguments).
///
-/// Given
+/// Example matches f(0, 0) and g(0, 0, 0)
+/// (matcher = callExpr(argumentCountAtLeast(2)))
/// \code
/// void f(int x, int y);
/// void g(int x, int y, int z);
-/// void foo() {
-/// f(0, 0);
-/// g(0, 0, 0);
-/// }
+/// f(0, 0);
+/// g(0, 0, 0);
/// \endcode
-/// The matcher \matcher{callExpr(argumentCountAtLeast(2))}
-/// matches \match{f(0, 0)} and \match{g(0, 0, 0)}
AST_POLYMORPHIC_MATCHER_P(argumentCountAtLeast,
AST_POLYMORPHIC_SUPPORTED_TYPES(
CallExpr, CXXConstructExpr,
@@ -6150,13 +4545,11 @@ AST_POLYMORPHIC_MATCHER_P(argumentCountAtLeast,
/// Matches the n'th argument of a call expression or a constructor
/// call expression.
///
-/// Given
+/// Example matches y in x(y)
+/// (matcher = callExpr(hasArgument(0, declRefExpr())))
/// \code
/// void x(int) { int y; x(y); }
/// \endcode
-/// The matcher \matcher{callExpr(hasArgument(0, declRefExpr().bind("arg")))}
-/// matches \match{x(y)},
-/// with \matcher{type=sub$declRefExpr()} matching \match{sub="arg"$y}.
AST_POLYMORPHIC_MATCHER_P2(hasArgument,
AST_POLYMORPHIC_SUPPORTED_TYPES(
CallExpr, CXXConstructExpr,
@@ -6172,7 +4565,10 @@ AST_POLYMORPHIC_MATCHER_P2(hasArgument,
/// Matches the operand that does not contain the parameter pack.
///
-/// Given
+/// Example matches `(0 + ... + args)` and `(args * ... * 1)`
+/// (matcher = cxxFoldExpr(hasFoldInit(expr())))
+/// with hasFoldInit(...)
+/// matching `0` and `1` respectively
/// \code
/// template <typename... Args>
/// auto sum(Args... args) {
@@ -6184,12 +4580,6 @@ AST_POLYMORPHIC_MATCHER_P2(hasArgument,
/// return (args * ... * 1);
/// }
/// \endcode
-/// \compile_args{-std=c++17-or-later}
-///
-/// The matcher \matcher{cxxFoldExpr(hasFoldInit(expr().bind("init")))}
-/// matches \match{(0 + ... + args)} and \match{(args * ... * 1)}
-/// with \matcher{type=sub$hasFoldInit(expr().bind("init"))} matching
-/// \match{sub=init$0} and \match{sub=init$1}.
AST_MATCHER_P(CXXFoldExpr, hasFoldInit, internal::Matcher<Expr>, InnerMacher) {
const auto *const Init = Node.getInit();
return Init && InnerMacher.matches(*Init, Finder, Builder);
@@ -6197,7 +4587,10 @@ AST_MATCHER_P(CXXFoldExpr, hasFoldInit, internal::Matcher<Expr>, InnerMacher) {
/// Matches the operand that contains the parameter pack.
///
-/// Given
+/// Example matches `(0 + ... + args)`
+/// (matcher = cxxFoldExpr(hasPattern(expr())))
+/// with hasPattern(...)
+/// matching `args`
/// \code
/// template <typename... Args>
/// auto sum(Args... args) {
@@ -6209,12 +4602,6 @@ AST_MATCHER_P(CXXFoldExpr, hasFoldInit, internal::Matcher<Expr>, InnerMacher) {
/// return (args * ... * 1);
/// }
/// \endcode
-/// \compile_args{-std=c++17-or-later}
-///
-/// The matcher \matcher{cxxFoldExpr(hasPattern(expr().bind("pattern")))}
-/// matches \match{(0 + ... + args)} and \match{(args * ... * 1)},
-/// with \matcher{type=sub$hasPattern(expr().bind("pattern"))} matching
-/// \match{count=2;sub=pattern$args} two times.
AST_MATCHER_P(CXXFoldExpr, hasPattern, internal::Matcher<Expr>, InnerMacher) {
const Expr *const Pattern = Node.getPattern();
return Pattern && InnerMacher.matches(*Pattern, Finder, Builder);
@@ -6222,7 +4609,8 @@ AST_MATCHER_P(CXXFoldExpr, hasPattern, internal::Matcher<Expr>, InnerMacher) {
/// Matches right-folding fold expressions.
///
-/// Given
+/// Example matches `(args * ... * 1)`
+/// (matcher = cxxFoldExpr(isRightFold()))
/// \code
/// template <typename... Args>
/// auto sum(Args... args) {
@@ -6234,15 +4622,12 @@ AST_MATCHER_P(CXXFoldExpr, hasPattern, internal::Matcher<Expr>, InnerMacher) {
/// return (args * ... * 1);
/// }
/// \endcode
-/// \compile_args{-std=c++17-or-later}
-///
-/// The matcher \matcher{cxxFoldExpr(isRightFold())}
-/// matches \match{(args * ... * 1)}.
AST_MATCHER(CXXFoldExpr, isRightFold) { return Node.isRightFold(); }
/// Matches left-folding fold expressions.
///
-/// Given
+/// Example matches `(0 + ... + args)`
+/// (matcher = cxxFoldExpr(isLeftFold()))
/// \code
/// template <typename... Args>
/// auto sum(Args... args) {
@@ -6254,16 +4639,13 @@ AST_MATCHER(CXXFoldExpr, isRightFold) { return Node.isRightFold(); }
/// return (args * ... * 1);
/// }
/// \endcode
-/// \compile_args{-std=c++17-or-later}
-///
-/// The matcher \matcher{cxxFoldExpr(isLeftFold())}
-/// matches \match{(0 + ... + args)}.
AST_MATCHER(CXXFoldExpr, isLeftFold) { return Node.isLeftFold(); }
/// Matches unary fold expressions, i.e. fold expressions without an
/// initializer.
///
-/// Given
+/// Example matches `(args * ...)`
+/// (matcher = cxxFoldExpr(isUnaryFold()))
/// \code
/// template <typename... Args>
/// auto sum(Args... args) {
@@ -6275,15 +4657,12 @@ AST_MATCHER(CXXFoldExpr, isLeftFold) { return Node.isLeftFold(); }
/// return (args * ...);
/// }
/// \endcode
-/// \compile_args{-std=c++17-or-later}
-///
-/// The matcher \matcher{cxxFoldExpr(isUnaryFold())}
-/// matches \match{(args * ...)}, but not \nomatch{(0 + ... + args)}.
AST_MATCHER(CXXFoldExpr, isUnaryFold) { return Node.getInit() == nullptr; }
/// Matches binary fold expressions, i.e. fold expressions with an initializer.
///
-/// Given
+/// Example matches `(0 + ... + args)`
+/// (matcher = cxxFoldExpr(isBinaryFold()))
/// \code
/// template <typename... Args>
/// auto sum(Args... args) {
@@ -6295,42 +4674,32 @@ AST_MATCHER(CXXFoldExpr, isUnaryFold) { return Node.getInit() == nullptr; }
/// return (args * ...);
/// }
/// \endcode
-/// \compile_args{-std=c++17-or-later}
-///
-/// The matcher \matcher{cxxFoldExpr(isBinaryFold())}
-/// matches \match{(0 + ... + args)}.
AST_MATCHER(CXXFoldExpr, isBinaryFold) { return Node.getInit() != nullptr; }
/// Matches the n'th item of an initializer list expression.
///
-/// Given
+/// Example matches y.
+/// (matcher = initListExpr(hasInit(0, expr())))
/// \code
-/// int y = 42;
-/// int x{y};
+/// int x{y}.
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{initListExpr(hasInit(0, expr()))}
-/// matches \match{{y}}.
AST_MATCHER_P2(InitListExpr, hasInit, unsigned, N, internal::Matcher<Expr>,
InnerMatcher) {
return N < Node.getNumInits() &&
- InnerMatcher.matches(*Node.getInit(N), Finder, Builder);
+ InnerMatcher.matches(*Node.getInit(N), Finder, Builder);
}
/// Matches declaration statements that contain a specific number of
/// declarations.
///
-/// Given
+/// Example: Given
/// \code
-/// void foo() {
-/// int a, b;
-/// int c;
-/// int d = 2, e;
-/// }
+/// int a, b;
+/// int c;
+/// int d = 2, e;
/// \endcode
-/// The matcher \matcher{declStmt(declCountIs(2))}
-/// matches \match{int a, b;} and \match{int d = 2, e;},
-/// but does not match \nomatch{int c;}
+/// declCountIs(2)
+/// matches 'int a, b;' and 'int d = 2, e;', but not 'int c;'.
AST_MATCHER_P(DeclStmt, declCountIs, unsigned, N) {
return std::distance(Node.decl_begin(), Node.decl_end()) == (ptrdiff_t)N;
}
@@ -6340,21 +4709,20 @@ AST_MATCHER_P(DeclStmt, declCountIs, unsigned, N) {
/// Note that this does not work for global declarations because the AST
/// breaks up multiple-declaration DeclStmt's into multiple single-declaration
/// DeclStmt's.
-///
-/// Given non-global declarations
+/// Example: Given non-global declarations
/// \code
-/// void foo() {
-/// int a, b = 0;
-/// int c;
-/// int d = 2, e;
-/// }
+/// int a, b = 0;
+/// int c;
+/// int d = 2, e;
+/// \endcode
+/// declStmt(containsDeclaration(
+/// 0, varDecl(hasInitializer(anything()))))
+/// matches only 'int d = 2, e;', and
+/// declStmt(containsDeclaration(1, varDecl()))
+/// \code
+/// matches 'int a, b = 0' as well as 'int d = 2, e;'
+/// but 'int c;' is not matched.
/// \endcode
-/// The matcher \matcher{declStmt(containsDeclaration(
-/// 0, varDecl(hasInitializer(anything()))))}
-/// matches \match{int d = 2, e;}.
-/// The matcher \matcher{declStmt(containsDeclaration(1, varDecl()))}
-/// matches \match{int a, b = 0;} and \match{int d = 2, e;}
-/// but does not match \nomatch{int c;}.
AST_MATCHER_P2(DeclStmt, containsDeclaration, unsigned, N,
internal::Matcher<Decl>, InnerMatcher) {
const unsigned NumDecls = std::distance(Node.decl_begin(), Node.decl_end());
@@ -6369,16 +4737,15 @@ AST_MATCHER_P2(DeclStmt, containsDeclaration, unsigned, N,
///
/// Given
/// \code
-/// void foo() {
-/// try {}
-/// catch (int) {}
-/// catch (...) {}
+/// try {
+/// // ...
+/// } catch (int) {
+/// // ...
+/// } catch (...) {
+/// // ...
/// }
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxCatchStmt(isCatchAll())}
-/// matches \match{catch (...) {}}
-/// but does not match \nomatch{catch(int)}
+/// cxxCatchStmt(isCatchAll()) matches catch(...) but not catch(int).
AST_MATCHER(CXXCatchStmt, isCatchAll) {
return Node.getExceptionDecl() == nullptr;
}
@@ -6392,13 +4759,10 @@ AST_MATCHER(CXXCatchStmt, isCatchAll) {
/// int foo_;
/// };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxConstructorDecl(
-/// hasAnyConstructorInitializer(cxxCtorInitializer().bind("ctor_init"))
-/// )}
-/// matches \match{Foo() : foo_(1) { }},
-/// with \matcher{type=sub$cxxCtorInitializer()}
-/// matching \match{sub=ctor_init$foo_(1)}.
+/// cxxRecordDecl(has(cxxConstructorDecl(
+/// hasAnyConstructorInitializer(anything())
+/// )))
+/// record matches Foo, hasAnyConstructorInitializer matches foo_(1)
AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer,
internal::Matcher<CXXCtorInitializer>, InnerMatcher) {
auto MatchIt = matchesFirstInPointerRange(InnerMatcher, Node.init_begin(),
@@ -6417,13 +4781,10 @@ AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer,
/// int foo_;
/// };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{cxxConstructorDecl(hasAnyConstructorInitializer(
-/// forField(fieldDecl(hasName("foo_")).bind("field"))))}
-/// matches \match{Foo() : foo_(1) { }},
-/// with \matcher{type=sub$fieldDecl(hasName("foo_"))}
-/// matching \match{sub=field$foo_(1)}.
+/// cxxRecordDecl(has(cxxConstructorDecl(hasAnyConstructorInitializer(
+/// forField(hasName("foo_"))))))
+/// matches Foo
+/// with forField matching foo_
AST_MATCHER_P(CXXCtorInitializer, forField,
internal::Matcher<FieldDecl>, InnerMatcher) {
const FieldDecl *NodeAsDecl = Node.getAnyMember();
@@ -6440,13 +4801,10 @@ AST_MATCHER_P(CXXCtorInitializer, forField,
/// int foo_;
/// };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{cxxConstructorDecl(hasAnyConstructorInitializer(
-/// withInitializer(integerLiteral(equals(1)).bind("literal"))))}
-/// matches \match{Foo() : foo_(1) { }},
-/// with \matcher{type=sub$integerLiteral(equals(1))} matching
-/// \match{sub=literal$1}.
+/// cxxRecordDecl(has(cxxConstructorDecl(hasAnyConstructorInitializer(
+/// withInitializer(integerLiteral(equals(1)))))))
+/// matches Foo
+/// with withInitializer matching (1)
AST_MATCHER_P(CXXCtorInitializer, withInitializer,
internal::Matcher<Expr>, InnerMatcher) {
const Expr* NodeAsExpr = Node.getInit();
@@ -6459,17 +4817,14 @@ AST_MATCHER_P(CXXCtorInitializer, withInitializer,
///
/// Given
/// \code
-/// struct Bar { explicit Bar(const char*); };
/// struct Foo {
/// Foo() { }
/// Foo(int) : foo_("A") { }
-/// Bar foo_{""};
+/// string foo_;
/// };
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher
-/// \matcher{cxxConstructorDecl(hasAnyConstructorInitializer(isWritten()))} will
-/// match \match{Foo(int) : foo_("A") { }}, but not \nomatch{Foo() { }}
+/// cxxConstructorDecl(hasAnyConstructorInitializer(isWritten()))
+/// will match Foo(int), but not Foo()
AST_MATCHER(CXXCtorInitializer, isWritten) {
return Node.isWritten();
}
@@ -6488,12 +4843,8 @@ AST_MATCHER(CXXCtorInitializer, isWritten) {
/// E() : B() {}
/// };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{cxxConstructorDecl(hasAnyConstructorInitializer(isBaseInitializer()))}
-/// matches \match{E() : B() {}} and \match{D(int i) : I(i) {}}.
-/// The constructor of \c D is matched, because it implicitly has a constructor
-/// initializer for \c B .
+/// cxxConstructorDecl(hasAnyConstructorInitializer(isBaseInitializer()))
+/// will match E(), but not match D(int).
AST_MATCHER(CXXCtorInitializer, isBaseInitializer) {
return Node.isBaseInitializer();
}
@@ -6512,11 +4863,8 @@ AST_MATCHER(CXXCtorInitializer, isBaseInitializer) {
/// E() : B() {}
/// };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{cxxConstructorDecl(hasAnyConstructorInitializer(isMemberInitializer()))}
-/// will match \match{D(int i) : I(i) {}}, but not match \nomatch{E() : B()
-/// {}}.
+/// cxxConstructorDecl(hasAnyConstructorInitializer(isMemberInitializer()))
+/// will match D(int), but not match E().
AST_MATCHER(CXXCtorInitializer, isMemberInitializer) {
return Node.isMemberInitializer();
}
@@ -6526,11 +4874,11 @@ AST_MATCHER(CXXCtorInitializer, isMemberInitializer) {
///
/// Given
/// \code
-/// void x(int, int, int) { int y = 42; x(1, y, 42); }
+/// void x(int, int, int) { int y; x(1, y, 42); }
/// \endcode
-/// The matcher
-/// \matcher{callExpr(hasAnyArgument(ignoringImplicit(declRefExpr())))} matches
-/// \match{x(1, y, 42)} with hasAnyArgument(...)
+/// callExpr(hasAnyArgument(declRefExpr()))
+/// matches x(1, y, 42)
+/// with hasAnyArgument(...)
/// matching y
///
/// For ObjectiveC, given
@@ -6538,10 +4886,8 @@ AST_MATCHER(CXXCtorInitializer, isMemberInitializer) {
/// @interface I - (void) f:(int) y; @end
/// void foo(I *i) { [i f:12]; }
/// \endcode
-/// \compile_args{-ObjC}
-/// The matcher
-/// \matcher{objcMessageExpr(hasAnyArgument(integerLiteral(equals(12))))}
-/// matches \match{[i f:12]}
+/// objcMessageExpr(hasAnyArgument(integerLiteral(equals(12))))
+/// matches [i f:12]
AST_POLYMORPHIC_MATCHER_P(hasAnyArgument,
AST_POLYMORPHIC_SUPPORTED_TYPES(
CallExpr, CXXConstructExpr,
@@ -6570,12 +4916,8 @@ AST_POLYMORPHIC_MATCHER_P(hasAnyArgument,
/// auto g = [x = 1](){};
/// }
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher
-/// \matcher{lambdaExpr(hasAnyCapture(lambdaCapture().bind("capture")))},
-/// matches \match{[x](){}} and \match{[x = 1](){}},
-/// with \matcher{type=sub$lambdaCapture()} matching
-/// \match{sub=capture$x} and \match{sub=capture$x = 1}.
+/// In the matcher `lambdaExpr(hasAnyCapture(lambdaCapture()))`,
+/// `lambdaCapture()` matches `x` and `x=1`.
extern const internal::VariadicAllOfMatcher<LambdaCapture> lambdaCapture;
/// Matches any capture in a lambda expression.
@@ -6587,10 +4929,9 @@ extern const internal::VariadicAllOfMatcher<LambdaCapture> lambdaCapture;
/// auto f = [=](){ return t; };
/// }
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{lambdaExpr(hasAnyCapture(lambdaCapture()))} and
-/// \matcher{lambdaExpr(hasAnyCapture(lambdaCapture(capturesVar(hasName("t")))))}
-/// both match \match{[=](){ return t; }}.
+/// lambdaExpr(hasAnyCapture(lambdaCapture())) and
+/// lambdaExpr(hasAnyCapture(lambdaCapture(refersToVarDecl(hasName("t")))))
+/// both match `[=](){ return t; }`.
AST_MATCHER_P(LambdaExpr, hasAnyCapture, internal::Matcher<LambdaCapture>,
InnerMatcher) {
for (const LambdaCapture &Capture : Node.captures()) {
@@ -6615,13 +4956,9 @@ AST_MATCHER_P(LambdaExpr, hasAnyCapture, internal::Matcher<LambdaCapture>,
/// auto g = [x = 1](){};
/// }
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher
-/// \matcher{lambdaExpr(hasAnyCapture(
-/// lambdaCapture(capturesVar(hasName("x"))).bind("capture")))}
-/// matches \match{[x](){}} and \match{[x = 1](){}}, with
-/// \matcher{type=sub$lambdaCapture(capturesVar(hasName("x"))).bind("capture")}
-/// matching \match{sub=capture$x} and \match{sub=capture$x = 1}.
+/// In the matcher
+/// lambdaExpr(hasAnyCapture(lambdaCapture(capturesVar(hasName("x")))),
+/// capturesVar(hasName("x")) matches `x` and `x = 1`.
AST_MATCHER_P(LambdaCapture, capturesVar, internal::Matcher<ValueDecl>,
InnerMatcher) {
if (!Node.capturesVariable())
@@ -6642,36 +4979,11 @@ AST_MATCHER_P(LambdaCapture, capturesVar, internal::Matcher<ValueDecl>,
/// }
/// };
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher
-/// \matcher{lambdaExpr(hasAnyCapture(lambdaCapture(capturesThis())))}
-/// matches \match{[this]() { return cc; }}.
+/// lambdaExpr(hasAnyCapture(lambdaCapture(capturesThis())))
+/// matches `[this]() { return cc; }`.
AST_MATCHER(LambdaCapture, capturesThis) { return Node.capturesThis(); }
/// Matches a constructor call expression which uses list initialization.
-///
-/// Given
-/// \code
-/// namespace std {
-/// template <typename T>
-/// class initializer_list {
-/// const T* begin;
-/// const T* end;
-/// };
-/// }
-/// template <typename T> class vector {
-/// public: vector(std::initializer_list<T>) {}
-/// };
-///
-/// vector<int> a({ 1, 2, 3 });
-/// vector<int> b = { 4, 5 };
-/// int c[] = { 6, 7 };
-/// struct pair { int x; int y; };
-/// pair d = { 8, 9 };
-/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++11-or-later}
-/// The matcher \matcher{cxxConstructExpr(isListInitialization())}
-/// matches \match{{ 4, 5 }}.
AST_MATCHER(CXXConstructExpr, isListInitialization) {
return Node.isListInitialization();
}
@@ -6682,16 +4994,12 @@ AST_MATCHER(CXXConstructExpr, isListInitialization) {
/// Given
/// \code
/// void foo() {
-/// struct Foo {
-/// double x;
-/// };
-/// auto Val = Foo();
+/// struct point { double x; double y; };
+/// point pt[2] = { { 1.0, 2.0 } };
/// }
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{cxxConstructExpr(requiresZeroInitialization())}
-/// matches \match{Foo()} because the \c x member has to be zero initialized.
+/// initListExpr(has(cxxConstructExpr(requiresZeroInitialization()))
+/// will match the implicit array filler for pt[1].
AST_MATCHER(CXXConstructExpr, requiresZeroInitialization) {
return Node.requiresZeroInitialization();
}
@@ -6703,20 +5011,17 @@ AST_MATCHER(CXXConstructExpr, requiresZeroInitialization) {
/// \code
/// class X { void f(int x) {} };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{cxxMethodDecl(hasParameter(0, hasType(asString("int"))))}
-/// matches \match{void f(int x) {}}
+/// cxxMethodDecl(hasParameter(0, hasType(varDecl())))
+/// matches f(int x) {}
/// with hasParameter(...)
-/// matching int x.
+/// matching int x
///
/// For ObjectiveC, given
/// \code
/// @interface I - (void) f:(int) y; @end
/// \endcode
-/// \compile_args{-ObjC}
-///
-/// The matcher \matcher{objcMethodDecl(hasParameter(0, hasName("y")))}
+//
+/// the matcher objcMethodDecl(hasParameter(0, hasName("y")))
/// matches the declaration of method f with hasParameter
/// matching y.
AST_POLYMORPHIC_MATCHER_P2(hasParameter,
@@ -6741,13 +5046,9 @@ AST_POLYMORPHIC_MATCHER_P2(hasParameter,
/// int operator+(int);
/// };
/// \endcode
-/// \compile_args{-std=c++23-or-later}
///
-/// The matcher \matcher{cxxMethodDecl(isExplicitObjectMemberFunction())}
-/// matches \match{int operator-(this A, int)} and
-/// \match{void fun(this A &&self)},
-/// but not \nomatch{static int operator()(int)} or
-/// \nomatch{int operator+(int)}.
+/// cxxMethodDecl(isExplicitObjectMemberFunction()) matches the first two
+/// methods but not the last two.
AST_MATCHER(CXXMethodDecl, isExplicitObjectMemberFunction) {
return Node.isExplicitObjectMemberFunction();
}
@@ -6758,16 +5059,14 @@ AST_MATCHER(CXXMethodDecl, isExplicitObjectMemberFunction) {
/// \code
/// void f(int i);
/// int y;
-/// void foo() {
-/// f(y);
-/// }
+/// f(y);
/// \endcode
-/// The matcher \matcher{callExpr(
+/// callExpr(
/// forEachArgumentWithParam(
/// declRefExpr(to(varDecl(hasName("y")))),
/// parmVarDecl(hasType(isInteger()))
-/// ))}
-/// matches \match{f(y)};
+/// ))
+/// matches f(y);
/// with declRefExpr(...)
/// matching int y
/// and parmVarDecl(...)
@@ -6820,18 +5119,17 @@ AST_POLYMORPHIC_MATCHER_P2(forEachArgumentWithParam,
/// Given
/// \code
/// void f(int i);
-/// void foo(int y) {
-/// f(y);
-/// void (*f_ptr)(int) = f;
-/// f_ptr(y);
-/// }
+/// int y;
+/// f(y);
+/// void (*f_ptr)(int) = f;
+/// f_ptr(y);
/// \endcode
-/// The matcher \matcher{callExpr(
+/// callExpr(
/// forEachArgumentWithParamType(
/// declRefExpr(to(varDecl(hasName("y")))),
-/// qualType(isInteger()).bind("type")
-/// ))}
-/// matches \match{f(y)} and \match{f_ptr(y)}
+/// qualType(isInteger()).bind("type)
+/// ))
+/// matches f(y) and f_ptr(y)
/// with declRefExpr(...)
/// matching int y
/// and qualType(...)
@@ -6924,11 +5222,9 @@ AST_POLYMORPHIC_MATCHER_P2(forEachArgumentWithParamType,
/// }
/// \endcode
///
-/// The matcher \matcher{parmVarDecl(isAtPosition(0))} matches
-/// \match{int a}.
+/// ``parmVarDecl(isAtPosition(0))`` matches ``int a``.
///
-/// The matcher \matcher{parmVarDecl(isAtPosition(1))}
-/// matches \match{int b}.
+/// ``parmVarDecl(isAtPosition(1))`` matches ``int b``.
AST_MATCHER_P(ParmVarDecl, isAtPosition, unsigned, N) {
const clang::DeclContext *Context = Node.getParentFunctionOrMethod();
@@ -6951,32 +5247,27 @@ AST_MATCHER_P(ParmVarDecl, isAtPosition, unsigned, N) {
/// \code
/// class X { void f(int x, int y, int z) {} };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{cxxMethodDecl(hasAnyParameter(
-/// parmVarDecl(hasName("y")).bind("parm")))}
-/// matches \match{void f(int x, int y, int z) {}},
-/// with \matcher{type=sub$parmVarDecl(hasName("y"))}
-/// matching \match{sub=parm$int y}.
+/// cxxMethodDecl(hasAnyParameter(hasName("y")))
+/// matches f(int x, int y, int z) {}
+/// with hasAnyParameter(...)
+/// matching int y
///
/// For ObjectiveC, given
/// \code
/// @interface I - (void) f:(int) y; @end
/// \endcode
-/// \compile_args{-ObjC}
-///
-/// the matcher \matcher{objcMethodDecl(hasAnyParameter(hasName("y")))}
-/// matches the declaration of method f with hasParameter
+//
+/// the matcher objcMethodDecl(hasAnyParameter(hasName("y")))
+/// matches the declaration of method f with hasParameter
/// matching y.
///
/// For blocks, given
/// \code
/// b = ^(int y) { printf("%d", y) };
/// \endcode
-/// \compile_args{-ObjC}
///
-/// the matcher \matcher{blockDecl(hasAnyParameter(hasName("y")))}
-/// matches the declaration of the block b with hasParameter
+/// the matcher blockDecl(hasAnyParameter(hasName("y")))
+/// matches the declaration of the block b with hasParameter
/// matching y.
AST_POLYMORPHIC_MATCHER_P(hasAnyParameter,
AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
@@ -7000,12 +5291,12 @@ AST_POLYMORPHIC_MATCHER_P(hasAnyParameter,
/// void j(int i);
/// void k(int x, int y, int z, ...);
/// \endcode
-/// The matcher \matcher{functionDecl(parameterCountIs(2))}
-/// matches \match{void g(int i, int j) {}} and \match{void h(int i, int j)}
-/// The matcher \matcher{functionProtoType(parameterCountIs(1))}
-/// matches the type \match{type=typestr;count=2$void (int)} of \c f and \c j.
-/// The matcher \matcher{functionProtoType(parameterCountIs(3))} matches the
-/// type \match{type=typestr$void (int, int, int, ...)} of \c k.
+/// functionDecl(parameterCountIs(2))
+/// matches \c g and \c h
+/// functionProtoType(parameterCountIs(2))
+/// matches \c g and \c h
+/// functionProtoType(parameterCountIs(3))
+/// matches \c k
AST_POLYMORPHIC_MATCHER_P(parameterCountIs,
AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
FunctionProtoType),
@@ -7029,24 +5320,14 @@ AST_POLYMORPHIC_MATCHER_P(parameterCountIs,
/// template <typename T, typename U>
/// void f(T&& t, U&& u) {}
///
-/// void foo() {
-/// bool B = false;
-/// f(R, B);
-/// }
+/// bool B = false;
+/// f(R, B);
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++11-or-later}
-/// The matcher
-/// \matcher{templateSpecializationType(forEachTemplateArgument(isExpr(expr().bind("t_arg"))))}
-/// matches \match{type=typestr;count=2$Matrix<int, R * 2, R * 4>} twice, with
-/// \matcher{type=sub$expr()} matching \match{sub=t_arg$R * 2} and
-/// \match{sub=t_arg$R * 4}.
-/// The matcher
-/// \matcher{functionDecl(forEachTemplateArgument(refersToType(qualType().bind("type"))))}
-/// matches the specialization of \match{count=2$void f(T&& t, U&& u) {}} twice
-/// for each of the template arguments, with \matcher{type=sub$qualType()}
-/// matching
-/// \match{sub=type;type=typestr$unsigned} and
-/// \match{sub=type;type=typestr$bool}.
+/// templateSpecializationType(forEachTemplateArgument(isExpr(expr())))
+/// matches twice, with expr() matching 'R * 2' and 'R * 4'
+/// functionDecl(forEachTemplateArgument(refersToType(builtinType())))
+/// matches the specialization f<unsigned, bool> twice, for 'unsigned'
+/// and 'bool'
AST_POLYMORPHIC_MATCHER_P(
forEachTemplateArgument,
AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
@@ -7075,23 +5356,23 @@ AST_POLYMORPHIC_MATCHER_P(
/// void nope();
/// [[noreturn]] void a();
/// __attribute__((noreturn)) void b();
-/// struct C { [[noreturn]] void c(); };
+/// struct c { [[noreturn]] c(); };
+/// \endcode
+/// functionDecl(isNoReturn())
+/// matches all of those except
+/// \code
+/// void nope();
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{functionDecl(isNoReturn())}
-/// matches \match{void a()}, \match{__attribute__((noreturn)) void b()} and
-/// \match{void c()} but does not match \nomatch{void nope()}.
AST_MATCHER(FunctionDecl, isNoReturn) { return Node.isNoReturn(); }
/// Matches the return type of a function declaration.
///
-/// Given
+/// Given:
/// \code
/// class X { int f() { return 1; } };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxMethodDecl(returns(asString("int")))}
-/// matches \match{int f() { return 1; }}.
+/// cxxMethodDecl(returns(asString("int")))
+/// matches int f() { return 1; }
AST_MATCHER_P(FunctionDecl, returns,
internal::Matcher<QualType>, InnerMatcher) {
return InnerMatcher.matches(Node.getReturnType(), Finder, Builder);
@@ -7099,21 +5380,19 @@ AST_MATCHER_P(FunctionDecl, returns,
/// Matches extern "C" function or variable declarations.
///
-/// Given
+/// Given:
/// \code
/// extern "C" void f() {}
/// extern "C" { void g() {} }
/// void h() {}
/// extern "C" int x = 1;
-/// extern "C" { int y = 2; }
+/// extern "C" int y = 2;
/// int z = 3;
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{functionDecl(isExternC())}
-/// matches \match{void f() {}} and \match{void g() {}}.
-/// The matcher \matcher{varDecl(isExternC())}
-/// matches \match{int x = 1} and \match{int y = 2}, but does not
-/// match \nomatch{int z = 3}.
+/// functionDecl(isExternC())
+/// matches the declaration of f and g, but not the declaration of h.
+/// varDecl(isExternC())
+/// matches the declaration of x and y, but not the declaration of z.
AST_POLYMORPHIC_MATCHER(isExternC, AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
VarDecl)) {
return Node.isExternC();
@@ -7122,17 +5401,17 @@ AST_POLYMORPHIC_MATCHER(isExternC, AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
/// Matches variable/function declarations that have "static" storage
/// class specifier ("static" keyword) written in the source.
///
-/// Given
+/// Given:
/// \code
/// static void f() {}
/// static int i = 0;
/// extern int j;
/// int k;
/// \endcode
-/// The matcher \matcher{functionDecl(isStaticStorageClass())}
-/// matches \match{static void f() {}}.
-/// The matcher \matcher{varDecl(isStaticStorageClass())}
-/// matches \match{static int i = 0}.
+/// functionDecl(isStaticStorageClass())
+/// matches the function declaration f.
+/// varDecl(isStaticStorageClass())
+/// matches the variable declaration i.
AST_POLYMORPHIC_MATCHER(isStaticStorageClass,
AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
VarDecl)) {
@@ -7141,77 +5420,56 @@ AST_POLYMORPHIC_MATCHER(isStaticStorageClass,
/// Matches deleted function declarations.
///
-/// Given
+/// Given:
/// \code
/// void Func();
/// void DeletedFunc() = delete;
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{functionDecl(isDeleted())}
-/// matches \match{void DeletedFunc()},
-/// but does not match \nomatch{void Func()}.
+/// functionDecl(isDeleted())
+/// matches the declaration of DeletedFunc, but not Func.
AST_MATCHER(FunctionDecl, isDeleted) {
return Node.isDeleted();
}
/// Matches defaulted function declarations.
///
-/// Given
+/// Given:
/// \code
/// class A { ~A(); };
/// class B { ~B() = default; };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{functionDecl(isDefaulted())}
-/// matches \match{~B() = default},
-/// but does not match \nomatch{~A()}.
+/// functionDecl(isDefaulted())
+/// matches the declaration of ~B, but not ~A.
AST_MATCHER(FunctionDecl, isDefaulted) {
return Node.isDefaulted();
}
/// Matches weak function declarations.
///
-/// Given
+/// Given:
/// \code
-/// static void f();
-/// void g() __attribute__((weak));
+/// void foo() __attribute__((__weakref__("__foo")));
+/// void bar();
/// \endcode
-/// The matcher \matcher{functionDecl(isWeak())}
-/// matches the weak declaration
-/// \match{void g() __attribute__((weak))},
-/// but does not match \nomatch{static void foo_v1()}.
+/// functionDecl(isWeak())
+/// matches the weak declaration "foo", but not "bar".
AST_MATCHER(FunctionDecl, isWeak) { return Node.isWeak(); }
/// Matches functions that have a dynamic exception specification.
///
-/// Given
+/// Given:
/// \code
-/// void f(int);
-/// void g(int) noexcept;
-/// void h(int) noexcept(true);
-/// void i(int) noexcept(false);
-/// void j(int) throw();
-/// void k(int) throw(int);
-/// void l(int) throw(...);
-/// \endcode
-/// \compile_args{-std=c++11-14}
-/// The matcher \matcher{functionDecl(hasDynamicExceptionSpec())}
-/// matches the declarations \match{void j(int) throw()},
-/// \match{void k(int) throw(int)}
-/// and \match{void l(int) throw(...)},
-/// but does not match \nomatch{void f(int)}, \nomatch{void g(int) noexcept},
-/// \nomatch{void h(int) noexcept(true)}
-/// or \nomatch{void i(int) noexcept(true)}.
-/// The matcher
-/// \matcher{functionProtoType(hasDynamicExceptionSpec())} matches
-/// the type \match{type=typestr$void (int) throw()} of \c j ,
-/// the type \match{type=typestr$void (int) throw(int)} of \c k and
-/// the type \match{type=typestr$void (int) throw(...)} of \c l .
-/// It does not match
-/// the type \nomatch{type=typestr$void (int) noexcept} of \c f ,
-/// the type \nomatch{type=typestr$void (int) noexcept} of \c g ,
-/// the type \nomatch{type=typestr$void (int) noexcept(int)} of \c h or
-/// the type \nomatch{type=typestr$void (int) noexcept(...)} of \c i .
+/// void f();
+/// void g() noexcept;
+/// void h() noexcept(true);
+/// void i() noexcept(false);
+/// void j() throw();
+/// void k() throw(int);
+/// void l() throw(...);
+/// \endcode
+/// functionDecl(hasDynamicExceptionSpec()) and
+/// functionProtoType(hasDynamicExceptionSpec())
+/// match the declarations of j, k, and l, but not f, g, h, or i.
AST_POLYMORPHIC_MATCHER(hasDynamicExceptionSpec,
AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
FunctionProtoType)) {
@@ -7222,29 +5480,16 @@ AST_POLYMORPHIC_MATCHER(hasDynamicExceptionSpec,
/// Matches functions that have a non-throwing exception specification.
///
-/// Given
+/// Given:
/// \code
-/// void f(int);
-/// void g(int) noexcept;
-/// void h(int) noexcept(false);
-/// void i(int) throw();
-/// void j(int) throw(int);
+/// void f();
+/// void g() noexcept;
+/// void h() throw();
+/// void i() throw(int);
+/// void j() noexcept(false);
/// \endcode
-/// \compile_args{-std=c++11-14}
-/// The matcher \matcher{functionDecl(isNoThrow())}
-/// matches the declaration \match{void g(int) noexcept}
-/// and \match{void i(int) throw()},
-/// but does not match \nomatch{void f(int)},
-/// \nomatch{void h(int) noexcept(false)}
-/// or \nomatch{void j(int) throw(int)}.
-/// The matcher
-/// \matcher{functionProtoType(isNoThrow())}
-/// matches the type \match{type=typestr$void (int) throw()} of \c i
-/// and the type \match{type=typestr$void (int) noexcept} of \c g,
-/// but does not match
-/// the type \nomatch{type=typestr$void (int)} of \c f ,
-/// the type \nomatch{type=typestr$void (int) noexcept(false)} of \c h or
-/// the type \nomatch{type=typestr$void (int) throw(int)} of \c j .
+/// functionDecl(isNoThrow()) and functionProtoType(isNoThrow())
+/// match the declarations of g, and h, but not f, i or j.
AST_POLYMORPHIC_MATCHER(isNoThrow,
AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
FunctionProtoType)) {
@@ -7266,20 +5511,17 @@ AST_POLYMORPHIC_MATCHER(isNoThrow,
/// Matches consteval function declarations and if consteval/if ! consteval
/// statements.
///
-/// Given
+/// Given:
/// \code
/// consteval int a();
/// void b() { if consteval {} }
/// void c() { if ! consteval {} }
/// void d() { if ! consteval {} else {} }
/// \endcode
-/// \compile_args{-std=c++23-or-later}
-/// The matcher \matcher{functionDecl(isConsteval())}
-/// matches \match{consteval int a()}.
-/// The matcher \matcher{ifStmt(isConsteval())}
-/// matches the if statements
-/// \match{if consteval {}}, \match{if ! consteval {}} and
-/// \match{if ! consteval {} else {}}.
+/// functionDecl(isConsteval())
+/// matches the declaration of "int a()".
+/// ifStmt(isConsteval())
+/// matches the if statement in "void b()", "void c()", "void d()".
AST_POLYMORPHIC_MATCHER(isConsteval,
AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, IfStmt)) {
return Node.isConsteval();
@@ -7288,19 +5530,18 @@ AST_POLYMORPHIC_MATCHER(isConsteval,
/// Matches constexpr variable and function declarations,
/// and if constexpr.
///
-/// Given
+/// Given:
/// \code
/// constexpr int foo = 42;
/// constexpr int bar();
/// void baz() { if constexpr(1 > 0) {} }
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{varDecl(isConstexpr())}
-/// matches \match{constexpr int foo = 42}.
-/// The matcher \matcher{functionDecl(isConstexpr())}
-/// matches \match{constexpr int bar()}.
-/// The matcher \matcher{ifStmt(isConstexpr())}
-/// matches \match{if constexpr(1 > 0) {}}.
+/// varDecl(isConstexpr())
+/// matches the declaration of foo.
+/// functionDecl(isConstexpr())
+/// matches the declaration of bar.
+/// ifStmt(isConstexpr())
+/// matches the if statement in baz.
AST_POLYMORPHIC_MATCHER(isConstexpr,
AST_POLYMORPHIC_SUPPORTED_TYPES(VarDecl,
FunctionDecl,
@@ -7310,19 +5551,15 @@ AST_POLYMORPHIC_MATCHER(isConstexpr,
/// Matches constinit variable declarations.
///
-/// Given
+/// Given:
/// \code
/// constinit int foo = 42;
/// constinit const char* bar = "bar";
/// int baz = 42;
/// [[clang::require_constant_initialization]] int xyz = 42;
/// \endcode
-/// \compile_args{-std=c++20-or-later}
-/// The matcher \matcher{varDecl(isConstinit())}
-/// matches the declaration of \match{constinit int foo = 42}
-/// and \match{constinit const char* bar = "bar"},
-/// but does not match \nomatch{int baz = 42} or
-/// \nomatch{[[clang::require_constant_initialization]] int xyz = 42}.
+/// varDecl(isConstinit())
+/// matches the declaration of `foo` and `bar`, but not `baz` and `xyz`.
AST_MATCHER(VarDecl, isConstinit) {
if (const auto *CIA = Node.getAttr<ConstInitAttr>())
return CIA->isConstinit();
@@ -7331,11 +5568,8 @@ AST_MATCHER(VarDecl, isConstinit) {
/// Matches selection statements with initializer.
///
-/// Given
+/// Given:
/// \code
-/// struct vec { int* begin(); int* end(); };
-/// int foobar();
-/// vec& get_range();
/// void foo() {
/// if (int i = foobar(); i > 0) {}
/// switch (int i = foobar(); i) {}
@@ -7347,17 +5581,12 @@ AST_MATCHER(VarDecl, isConstinit) {
/// for (auto& x : get_range()) {}
/// }
/// \endcode
-/// \compile_args{-std=c++20-or-later}
-/// The matcher \matcher{ifStmt(hasInitStatement(anything()))}
-/// matches the if statement \match{if (int i = foobar(); i > 0) {}}
-/// in foo but not \nomatch{if (foobar() > 0) {}} in bar.
-/// The matcher \matcher{switchStmt(hasInitStatement(anything()))}
-/// matches the switch statement \match{switch (int i = foobar(); i) {}}
-/// in foo but not \nomatch{switch (foobar()) {}} in bar.
-/// The matcher \matcher{cxxForRangeStmt(hasInitStatement(anything()))}
-/// matches the range for statement
-/// \match{for (auto& a = get_range(); auto& x : a) {}} in foo
-/// but not \nomatch{for (auto& x : get_range()) {}} in bar.
+/// ifStmt(hasInitStatement(anything()))
+/// matches the if statement in foo but not in bar.
+/// switchStmt(hasInitStatement(anything()))
+/// matches the switch statement in foo but not in bar.
+/// cxxForRangeStmt(hasInitStatement(anything()))
+/// matches the range for statement in foo but not in bar.
AST_POLYMORPHIC_MATCHER_P(hasInitStatement,
AST_POLYMORPHIC_SUPPORTED_TYPES(IfStmt, SwitchStmt,
CXXForRangeStmt),
@@ -7369,15 +5598,10 @@ AST_POLYMORPHIC_MATCHER_P(hasInitStatement,
/// Matches the condition expression of an if statement, for loop,
/// switch statement or conditional operator.
///
-/// Given
+/// Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
/// \code
-/// void foo() {
/// if (true) {}
-/// }
/// \endcode
-/// \compile_args{-std=c++,c23-or-later}
-/// The matcher \matcher{ifStmt(hasCondition(cxxBoolLiteral(equals(true))))}
-/// \match{if (true) {}}
AST_POLYMORPHIC_MATCHER_P(
hasCondition,
AST_POLYMORPHIC_SUPPORTED_TYPES(IfStmt, ForStmt, WhileStmt, DoStmt,
@@ -7390,15 +5614,11 @@ AST_POLYMORPHIC_MATCHER_P(
/// Matches the then-statement of an if statement.
///
-/// Given
+/// Examples matches the if statement
+/// (matcher = ifStmt(hasThen(cxxBoolLiteral(equals(true)))))
/// \code
-/// void foo() {
/// if (false) true; else false;
-/// }
/// \endcode
-/// \compile_args{-std=c++,c23-or-later}
-/// The matcher \matcher{ifStmt(hasThen(cxxBoolLiteral(equals(true))))}
-/// \match{if (false) true; else false}
AST_MATCHER_P(IfStmt, hasThen, internal::Matcher<Stmt>, InnerMatcher) {
const Stmt *const Then = Node.getThen();
return (Then != nullptr && InnerMatcher.matches(*Then, Finder, Builder));
@@ -7406,15 +5626,11 @@ AST_MATCHER_P(IfStmt, hasThen, internal::Matcher<Stmt>, InnerMatcher) {
/// Matches the else-statement of an if statement.
///
-/// Given
+/// Examples matches the if statement
+/// (matcher = ifStmt(hasElse(cxxBoolLiteral(equals(true)))))
/// \code
-/// void foo() {
/// if (false) false; else true;
-/// }
/// \endcode
-/// \compile_args{-std=c++,c23-or-later}
-/// The matcher \matcher{ifStmt(hasElse(cxxBoolLiteral(equals(true))))}
-/// \match{if (false) false; else true}
AST_MATCHER_P(IfStmt, hasElse, internal::Matcher<Stmt>, InnerMatcher) {
const Stmt *const Else = Node.getElse();
return (Else != nullptr && InnerMatcher.matches(*Else, Finder, Builder));
@@ -7428,12 +5644,10 @@ AST_MATCHER_P(IfStmt, hasElse, internal::Matcher<Stmt>, InnerMatcher) {
/// \code
/// class X { int a; int b; };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxRecordDecl(
+/// cxxRecordDecl(
/// has(fieldDecl(hasName("a"), hasType(type().bind("t")))),
-/// has(fieldDecl(hasName("b"), hasType(type(equalsBoundNode("t"))))))}
-/// matches \match{class X { int a; int b; }}, as \c a and \c b have the same
-/// type.
+/// has(fieldDecl(hasName("b"), hasType(type(equalsBoundNode("t"))))))
+/// matches the class \c X, as \c a and \c b have the same type.
///
/// Note that when multiple matches are involved via \c forEach* matchers,
/// \c equalsBoundNodes acts as a filter.
@@ -7463,19 +5677,14 @@ AST_POLYMORPHIC_MATCHER_P(equalsBoundNode,
///
/// Given
/// \code
-/// struct A {};
-/// A* GetAPointer();
-/// void foo() {
/// if (A* a = GetAPointer()) {}
-/// }
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{ifStmt(hasConditionVariableStatement(declStmt()))}
-/// \match{if (A* a = GetAPointer()) {}}
+/// hasConditionVariableStatement(...)
+/// matches 'A* a = GetAPointer()'.
AST_MATCHER_P(IfStmt, hasConditionVariableStatement,
internal::Matcher<DeclStmt>, InnerMatcher) {
- const DeclStmt *const DeclarationStatement =
- Node.getConditionVariableDeclStmt();
+ const DeclStmt* const DeclarationStatement =
+ Node.getConditionVariableDeclStmt();
return DeclarationStatement != nullptr &&
InnerMatcher.matches(*DeclarationStatement, Finder, Builder);
}
@@ -7487,11 +5696,11 @@ AST_MATCHER_P(IfStmt, hasConditionVariableStatement,
/// int i[5];
/// void f() { i[1] = 42; }
/// \endcode
-/// The matcher \matcher{arraySubscriptExpr(hasIndex(integerLiteral()))}
-/// matches \match{i[1]} with the \c integerLiteral() matching \c 1
-AST_MATCHER_P(ArraySubscriptExpr, hasIndex, internal::Matcher<Expr>,
- InnerMatcher) {
- if (const Expr *Expression = Node.getIdx())
+/// arraySubscriptExpression(hasIndex(integerLiteral()))
+/// matches \c i[1] with the \c integerLiteral() matching \c 1
+AST_MATCHER_P(ArraySubscriptExpr, hasIndex,
+ internal::Matcher<Expr>, InnerMatcher) {
+ if (const Expr* Expression = Node.getIdx())
return InnerMatcher.matches(*Expression, Finder, Builder);
return false;
}
@@ -7503,9 +5712,9 @@ AST_MATCHER_P(ArraySubscriptExpr, hasIndex, internal::Matcher<Expr>,
/// int i[5];
/// void f() { i[1] = 42; }
/// \endcode
-/// The matcher \matcher{arraySubscriptExpr(hasBase(implicitCastExpr(
-/// hasSourceExpression(declRefExpr()))))}
-/// matches \match{i[1]} with the \c declRefExpr() matching \c i
+/// arraySubscriptExpression(hasBase(implicitCastExpr(
+/// hasSourceExpression(declRefExpr()))))
+/// matches \c i[1] with the \c declRefExpr() matching \c i
AST_MATCHER_P(ArraySubscriptExpr, hasBase,
internal::Matcher<Expr>, InnerMatcher) {
if (const Expr* Expression = Node.getBase())
@@ -7520,25 +5729,23 @@ AST_MATCHER_P(ArraySubscriptExpr, hasBase,
///
/// Given
/// \code
-/// void foo() {
/// for (;;) {}
-/// }
/// \endcode
-/// The matcher \matcher{forStmt(hasBody(compoundStmt().bind("body")))}
-/// matches \match{for (;;) {}}
-/// with \matcher{type=sub$compoundStmt()}
-/// matching \match{sub=body${}}
+/// forStmt(hasBody(compoundStmt()))
+/// matches 'for (;;) {}'
+/// with compoundStmt()
+/// matching '{}'
///
/// Given
/// \code
/// void f();
/// void f() {}
/// \endcode
-/// The matcher \matcher{functionDecl(hasBody(compoundStmt().bind("compound")))}
-/// \match{void f() {}}
-/// with \matcher{type=sub$compoundStmt()}
-/// matching \match{sub=compound${}},
-/// but it does not match \nomatch{void f();}.
+/// functionDecl(hasBody(compoundStmt()))
+/// matches 'void f() {}'
+/// with compoundStmt()
+/// matching '{}'
+/// but does not match 'void f();'
AST_POLYMORPHIC_MATCHER_P(
hasBody,
AST_POLYMORPHIC_SUPPORTED_TYPES(DoStmt, ForStmt, WhileStmt, CXXForRangeStmt,
@@ -7561,28 +5768,31 @@ AST_POLYMORPHIC_MATCHER_P(
/// void f() {}
/// void g();
/// \endcode
-/// The matcher \matcher{functionDecl(hasAnyBody(compoundStmt().bind("body")))}
-/// matches \match{void f() {}} and the declaration \match{void f()},
-/// with \matcher{type=sub$compoundStmt()} matching \match{sub=body${}}, but it
-/// does not match \nomatch{void g()}.
-AST_MATCHER_P(FunctionDecl, hasAnyBody, internal::Matcher<Stmt>, InnerMatcher) {
+/// functionDecl(hasAnyBody(compoundStmt()))
+/// matches both 'void f();'
+/// and 'void f() {}'
+/// with compoundStmt()
+/// matching '{}'
+/// but does not match 'void g();'
+AST_MATCHER_P(FunctionDecl, hasAnyBody,
+ internal::Matcher<Stmt>, InnerMatcher) {
const Stmt *const Statement = Node.getBody();
return (Statement != nullptr &&
InnerMatcher.matches(*Statement, Finder, Builder));
}
+
/// Matches compound statements where at least one substatement matches
/// a given matcher. Also matches StmtExprs that have CompoundStmt as children.
///
/// Given
/// \code
-/// void foo() { { {}; 1+2; } }
+/// { {}; 1+2; }
/// \endcode
-/// The matcher
-/// \matcher{compoundStmt(hasAnySubstatement(compoundStmt().bind("compound")))}
-/// \match{{ {}; 1+2; }} and \match{{ { {}; 1+2; } }}
-/// with \matcher{type=sub$compoundStmt()}
-/// matching \match{sub=compound${}} and \match{sub=compound${ {}; 1+2; }}.
+/// hasAnySubstatement(compoundStmt())
+/// matches '{ {}; 1+2; }'
+/// with compoundStmt()
+/// matching '{}'
AST_POLYMORPHIC_MATCHER_P(hasAnySubstatement,
AST_POLYMORPHIC_SUPPORTED_TYPES(CompoundStmt,
StmtExpr),
@@ -7598,12 +5808,10 @@ AST_POLYMORPHIC_MATCHER_P(hasAnySubstatement,
///
/// Example: Given
/// \code
-/// void foo() {
/// { for (;;) {} }
-/// }
/// \endcode
-/// The matcher \matcher{compoundStmt(statementCountIs(0))}
-/// \match{{}}
+/// compoundStmt(statementCountIs(0)))
+/// matches '{}'
/// but does not match the outer compound statement.
AST_MATCHER_P(CompoundStmt, statementCountIs, unsigned, N) {
return Node.size() == N;
@@ -7613,31 +5821,24 @@ AST_MATCHER_P(CompoundStmt, statementCountIs, unsigned, N) {
///
/// Given
/// \code
-/// void f(char, bool, double, int);
-/// void foo() {
/// f('\0', false, 3.14, 42);
-/// }
/// \endcode
-/// \compile_args{-std=c++,c23-or-later}
-/// The matcher \matcher{characterLiteral(equals(0U))} matches \match{'\0'}.
-/// The matchers \matcher{cxxBoolLiteral(equals(false))} and
-/// \matcher{cxxBoolLiteral(equals(0))} match \match{false}.
-/// The matcher \matcher{floatLiteral(equals(3.14))} matches \match{3.14}.
-/// The matcher \matcher{integerLiteral(equals(42))} matches \match{42}.
+/// characterLiteral(equals(0))
+/// matches '\0'
+/// cxxBoolLiteral(equals(false)) and cxxBoolLiteral(equals(0))
+/// match false
+/// floatLiteral(equals(3.14)) and floatLiteral(equals(314e-2))
+/// match 3.14
+/// integerLiteral(equals(42))
+/// matches 42
///
/// Note that you cannot directly match a negative numeric literal because the
/// minus sign is not part of the literal: It is a unary operator whose operand
/// is the positive numeric literal. Instead, you must use a unaryOperator()
/// matcher to match the minus sign:
///
-/// Given
-/// \code
-/// int val = -1;
-/// \endcode
-///
-/// The matcher \matcher{unaryOperator(hasOperatorName("-"),
-/// hasUnaryOperand(integerLiteral(equals(1))))}
-/// matches \match{-1}.
+/// unaryOperator(hasOperatorName("-"),
+/// hasUnaryOperand(integerLiteral(equals(13))))
///
/// Usable as: Matcher<CharacterLiteral>, Matcher<CXXBoolLiteralExpr>,
/// Matcher<FloatingLiteral>, Matcher<IntegerLiteral>
@@ -7681,26 +5882,19 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(equals,
/// Matches the operator Name of operator expressions and fold expressions
/// (binary or unary).
///
-/// Given
+/// Example matches a || b (matcher = binaryOperator(hasOperatorName("||")))
/// \code
-//// void foo(bool a, bool b) {
-/// !(a || b);
-/// }
+/// !(a || b)
/// \endcode
-/// \compile_args{-std=c++,c23-or-later}
-/// The matcher \matcher{binaryOperator(hasOperatorName("||"))}
-/// matches \match{a || b}
///
-/// Given
+/// Example matches `(0 + ... + args)`
+/// (matcher = cxxFoldExpr(hasOperatorName("+")))
/// \code
/// template <typename... Args>
/// auto sum(Args... args) {
/// return (0 + ... + args);
/// }
/// \endcode
-/// \compile_args{-std=c++17-or-later}
-/// The matcher \matcher{cxxFoldExpr(hasOperatorName("+"))}
-/// matches \match{(0 + ... + args)}.
AST_POLYMORPHIC_MATCHER_P(
hasOperatorName,
AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, CXXOperatorCallExpr,
@@ -7715,28 +5909,9 @@ AST_POLYMORPHIC_MATCHER_P(
/// Matches operator expressions (binary or unary) that have any of the
/// specified names.
///
-/// It provides a compact way of writing if an operator has any of the specified
-/// names:
-/// The matcher
-/// \c hasAnyOperatorName("+", "-")
-/// Is equivalent to
-/// \c{anyOf(hasOperatorName("+"), hasOperatorName("-"))}
-///
-/// Given
-/// \code
-//// void foo(bool a, bool b) {
-/// !(a || b);
-/// }
-///
-//// void bar(bool a, bool b) {
-/// a && b;
-/// }
-/// \endcode
-/// \compile_args{-std=c++,c23-or-later}
-/// The matcher \matcher{binaryOperator(hasAnyOperatorName("||", "&&"))}
-/// matches \match{a || b} and \match{a && b}.
-/// The matcher \matcher{unaryOperator(hasAnyOperatorName("-", "!"))}
-/// matches \match{!(a || b)}.
+/// hasAnyOperatorName("+", "-")
+/// Is equivalent to
+/// anyOf(hasOperatorName("+"), hasOperatorName("-"))
extern const internal::VariadicFunction<
internal::PolymorphicMatcher<internal::HasAnyOperatorNameMatcher,
AST_POLYMORPHIC_SUPPORTED_TYPES(
@@ -7748,24 +5923,18 @@ extern const internal::VariadicFunction<
/// Matches all kinds of assignment operators.
///
-/// Given
+/// Example 1: matches a += b (matcher = binaryOperator(isAssignmentOperator()))
/// \code
-/// void foo(int a, int b) {
/// if (a == b)
/// a += b;
-/// }
/// \endcode
-/// The matcher \matcher{binaryOperator(isAssignmentOperator())}
-/// matches \match{a += b}.
///
-/// Given
+/// Example 2: matches s1 = s2
+/// (matcher = cxxOperatorCallExpr(isAssignmentOperator()))
/// \code
/// struct S { S& operator=(const S&); };
/// void x() { S s1, s2; s1 = s2; }
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxOperatorCallExpr(isAssignmentOperator())}
-/// matches \match{s1 = s2}.
AST_POLYMORPHIC_MATCHER(
isAssignmentOperator,
AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, CXXOperatorCallExpr,
@@ -7775,24 +5944,18 @@ AST_POLYMORPHIC_MATCHER(
/// Matches comparison operators.
///
-/// Given
+/// Example 1: matches a == b (matcher = binaryOperator(isComparisonOperator()))
/// \code
-/// void foo(int a, int b) {
/// if (a == b)
/// a += b;
-/// }
/// \endcode
-/// The matcher \matcher{binaryOperator(isComparisonOperator())}
-/// matches \match{a == b}
///
-/// Given
+/// Example 2: matches s1 < s2
+/// (matcher = cxxOperatorCallExpr(isComparisonOperator()))
/// \code
/// struct S { bool operator<(const S& other); };
/// void x(S s1, S s2) { bool b1 = s1 < s2; }
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxOperatorCallExpr(isComparisonOperator())}
-/// matches \match{s1 < s2}
AST_POLYMORPHIC_MATCHER(
isComparisonOperator,
AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, CXXOperatorCallExpr,
@@ -7802,17 +5965,10 @@ AST_POLYMORPHIC_MATCHER(
/// Matches the left hand side of binary operator expressions.
///
-/// Given
+/// Example matches a (matcher = binaryOperator(hasLHS()))
/// \code
-/// void foo(bool a, bool b) {
-/// a || b;
-/// }
+/// a || b
/// \endcode
-/// \compile_args{-std=c++,c23-or-later}
-/// The matcher \matcher{binaryOperator(hasLHS(expr().bind("lhs")))}
-/// matches \match{a || b},
-/// with \matcher{type=sub$expr()}
-/// matching \match{sub=lhs$a}.
AST_POLYMORPHIC_MATCHER_P(
hasLHS,
AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, CXXOperatorCallExpr,
@@ -7826,17 +5982,10 @@ AST_POLYMORPHIC_MATCHER_P(
/// Matches the right hand side of binary operator expressions.
///
-/// Given
+/// Example matches b (matcher = binaryOperator(hasRHS()))
/// \code
-/// void foo(bool a, bool b) {
-/// a || b;
-/// }
+/// a || b
/// \endcode
-/// \compile_args{-std=c++,c23-or-later}
-/// The matcher \matcher{binaryOperator(hasRHS(expr().bind("rhs")))}
-/// matches \match{a || b},
-/// with \matcher{type=sub$expr()}
-/// matching \match{sub=rhs$b}.
AST_POLYMORPHIC_MATCHER_P(
hasRHS,
AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, CXXOperatorCallExpr,
@@ -7850,32 +5999,6 @@ AST_POLYMORPHIC_MATCHER_P(
/// Matches if either the left hand side or the right hand side of a
/// binary operator or fold expression matches.
-///
-/// Given
-/// \code
-/// struct S {};
-/// bool operator ==(const S&, const S&);
-///
-/// void f(int a, const S&lhs, const S&rhs) {
-/// a + 0;
-/// lhs == rhs;
-/// lhs != rhs;
-/// }
-///
-/// template <typename ...Ts>
-/// auto sum(Ts... args) {
-/// return (0 + ... + args);
-/// }
-/// \endcode
-/// \compile_args{-std=c++20-or-later}
-///
-/// The matcher \matcher{binaryOperator(hasEitherOperand(integerLiteral()))}
-/// matches \match{a + 0}.
-/// The matcher \matcher{cxxOperatorCallExpr(hasEitherOperand(declRefExpr(to(
-/// parmVarDecl(hasName("lhs"))))))} matches \match{lhs == rhs} and
-/// \match{lhs != rhs}.
-/// The matcher \matcher{cxxFoldExpr(hasEitherOperand(integerLiteral()))}
-/// matches \match{(0 + ... + args)}.
AST_POLYMORPHIC_MATCHER_P(
hasEitherOperand,
AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, CXXOperatorCallExpr,
@@ -7889,20 +6012,14 @@ AST_POLYMORPHIC_MATCHER_P(
/// Matches if both matchers match with opposite sides of the binary operator
/// or fold expression.
///
-/// Given
+/// Example matcher = binaryOperator(hasOperands(integerLiteral(equals(1),
+/// integerLiteral(equals(2)))
/// \code
-/// void foo() {
-/// 1 + 2; // Match
-/// 2 + 1; // Match
-/// 1 + 1; // No match
-/// 2 + 2; // No match
-/// }
+/// 1 + 2 // Match
+/// 2 + 1 // Match
+/// 1 + 1 // No match
+/// 2 + 2 // No match
/// \endcode
-/// The matcher \matcher{binaryOperator(hasOperands(integerLiteral(equals(1)),
-/// integerLiteral(equals(2))))}
-/// matches \match{1 + 2} and \match{2 + 1},
-/// but does not match \nomatch{1 + 1}
-/// or \nomatch{2 + 2}.
AST_POLYMORPHIC_MATCHER_P2(
hasOperands,
AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, CXXOperatorCallExpr,
@@ -7916,15 +6033,11 @@ AST_POLYMORPHIC_MATCHER_P2(
/// Matches if the operand of a unary operator matches.
///
+/// Example matches true (matcher = hasUnaryOperand(
+/// cxxBoolLiteral(equals(true))))
/// \code
-/// void foo() {
-/// !true;
-/// }
+/// !true
/// \endcode
-/// \compile_args{-std=c++,c23-or-later}
-/// The matcher
-/// \matcher{unaryOperator(hasUnaryOperand(cxxBoolLiteral(equals(true))))}
-/// matches \match{!true}.
AST_POLYMORPHIC_MATCHER_P(hasUnaryOperand,
AST_POLYMORPHIC_SUPPORTED_TYPES(UnaryOperator,
CXXOperatorCallExpr),
@@ -7937,27 +6050,18 @@ AST_POLYMORPHIC_MATCHER_P(hasUnaryOperand,
/// Matches if the cast's source expression
/// or opaque value's source expression matches the given matcher.
///
-/// Given
+/// Example 1: matches "a string"
+/// (matcher = castExpr(hasSourceExpression(cxxConstructExpr())))
/// \code
-/// struct URL { URL(const char*); };
-/// URL url = "a string";
+/// class URL { URL(string); };
+/// URL url = "a string";
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{castExpr(hasSourceExpression(cxxConstructExpr()))}
-/// matches \match{"a string"}.
///
-/// Given
+/// Example 2: matches 'b' (matcher =
+/// opaqueValueExpr(hasSourceExpression(implicitCastExpr(declRefExpr())))
/// \code
-/// void foo(bool b) {
-/// int a = b ?: 1;
-/// }
+/// int a = b ?: 1;
/// \endcode
-/// \compile_args{-std=c++,c23-or-later}
-/// The matcher
-/// \matcher{opaqueValueExpr(hasSourceExpression(
-/// implicitCastExpr(has(
-/// implicitCastExpr(has(declRefExpr()))))))}
-/// matches \match{count=2$b} twice, for the condition and the true expression.
AST_POLYMORPHIC_MATCHER_P(hasSourceExpression,
AST_POLYMORPHIC_SUPPORTED_TYPES(CastExpr,
OpaqueValueExpr),
@@ -7970,12 +6074,11 @@ AST_POLYMORPHIC_MATCHER_P(hasSourceExpression,
/// Matches casts that has a given cast kind.
///
-/// Given
+/// Example: matches the implicit cast around \c 0
+/// (matcher = castExpr(hasCastKind(CK_NullToPointer)))
/// \code
/// int *p = 0;
/// \endcode
-/// The matcher \matcher{castExpr(hasCastKind(CK_NullToPointer))}
-/// matches the implicit cast around \match{0}
///
/// If the matcher is use from clang-query, CastKind parameter
/// should be passed as a quoted string. e.g., hasCastKind("CK_NullToPointer").
@@ -7987,30 +6090,14 @@ AST_MATCHER_P(CastExpr, hasCastKind, CastKind, Kind) {
///
/// (Note: Clang's AST refers to other conversions as "casts" too, and calls
/// actual casts "explicit" casts.)
-///
-/// \code
-/// unsigned int a = (unsigned int)0;
-/// \endcode
-///
-/// The matcher \matcher{explicitCastExpr(hasDestinationType(
-/// qualType(isUnsignedInteger())))} matches \match{(unsigned int)0}.
-AST_MATCHER_P(ExplicitCastExpr, hasDestinationType, internal::Matcher<QualType>,
- InnerMatcher) {
+AST_MATCHER_P(ExplicitCastExpr, hasDestinationType,
+ internal::Matcher<QualType>, InnerMatcher) {
const QualType NodeType = Node.getTypeAsWritten();
return InnerMatcher.matches(NodeType, Finder, Builder);
}
/// Matches implicit casts whose destination type matches a given
/// matcher.
-///
-/// Given
-/// \code
-/// unsigned int a = 0;
-/// \endcode
-///
-/// The matcher
-/// \matcher{implicitCastExpr(hasImplicitDestinationType(
-/// qualType(isUnsignedInteger())))} matches \match{0}.
AST_MATCHER_P(ImplicitCastExpr, hasImplicitDestinationType,
internal::Matcher<QualType>, InnerMatcher) {
return InnerMatcher.matches(Node.getType(), Finder, Builder);
@@ -8020,66 +6107,50 @@ AST_MATCHER_P(ImplicitCastExpr, hasImplicitDestinationType,
///
/// Example matches S, but not C, U or E.
/// \code
-/// struct S;
-/// class C;
-/// union U;
+/// struct S {};
+/// class C {};
+/// union U {};
/// enum E {};
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{tagDecl(isStruct())} matches \match{struct S},
-/// but does not match \nomatch{class C}, \nomatch{union U} or
-/// \nomatch{enum E {}}.
AST_MATCHER(TagDecl, isStruct) {
return Node.isStruct();
}
/// Matches TagDecl object that are spelled with "union."
///
-/// Given
+/// Example matches U, but not C, S or E.
/// \code
-/// struct S;
-/// class C;
-/// union U;
+/// struct S {};
+/// class C {};
+/// union U {};
/// enum E {};
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{tagDecl(isUnion())} matches \match{union U},
-/// but does not match \nomatch{struct S}, \nomatch{class C} or
-/// \nomatch{enum E {}}.
AST_MATCHER(TagDecl, isUnion) {
return Node.isUnion();
}
/// Matches TagDecl object that are spelled with "class."
///
-/// Given
+/// Example matches C, but not S, U or E.
/// \code
-/// struct S;
-/// class C;
-/// union U;
+/// struct S {};
+/// class C {};
+/// union U {};
/// enum E {};
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{tagDecl(isClass())} matches \match{class C},
-/// but does not match \nomatch{struct S}, \nomatch{union U} or
-/// \nomatch{enum E {}}.
AST_MATCHER(TagDecl, isClass) {
return Node.isClass();
}
/// Matches TagDecl object that are spelled with "enum."
///
-/// Given
+/// Example matches E, but not C, S or U.
/// \code
-/// struct S;
-/// class C;
-/// union U;
+/// struct S {};
+/// class C {};
+/// union U {};
/// enum E {};
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{tagDecl(isEnum())} matches \match{enum E {}},
-/// but does not match \nomatch{struct S}, \nomatch{class C} or
-/// \nomatch{union U}.
AST_MATCHER(TagDecl, isEnum) {
return Node.isEnum();
}
@@ -8087,29 +6158,14 @@ AST_MATCHER(TagDecl, isEnum) {
/// Matches the true branch expression of a conditional operator.
///
/// Example 1 (conditional ternary operator): matches a
-/// Given
/// \code
-/// void foo(bool condition, int a, int b) {
-/// condition ? a : b;
-/// }
+/// condition ? a : b
/// \endcode
-/// \compile_args{-std=c++,c23-or-later}
-/// The matcher
-/// \matcher{conditionalOperator(hasTrueExpression(expr().bind("true")))}
-/// matches \match{condition ? a : b},
-/// with \matcher{type=sub$expr()} matching \match{sub=true$a}.
///
/// Example 2 (conditional binary operator): matches opaqueValueExpr(condition)
-/// Given
/// \code
-/// void foo(bool condition, int a, int b) {
-/// condition ?: b;
-/// }
+/// condition ?: b
/// \endcode
-/// \compile_args{-std=c++,c23-or-later}
-/// The matcher \matcher{binaryConditionalOperator(hasTrueExpression(expr()))}
-/// matches \match{condition ?: b},
-/// with \matcher{type=sub$expr()} matching \match{sub=true$conditoin}.
AST_MATCHER_P(AbstractConditionalOperator, hasTrueExpression,
internal::Matcher<Expr>, InnerMatcher) {
const Expr *Expression = Node.getTrueExpr();
@@ -8122,20 +6178,9 @@ AST_MATCHER_P(AbstractConditionalOperator, hasTrueExpression,
///
/// Example matches b
/// \code
-/// void foo(bool condition, int a, int b) {
-/// condition ? a : b;
-/// condition ?: b;
-/// }
+/// condition ? a : b
+/// condition ?: b
/// \endcode
-/// \compile_args{-std=c++,c23-or-later}
-/// The matcher
-/// \matcher{conditionalOperator(hasFalseExpression(expr().bind("false")))}
-/// matches \match{condition ? a : b},
-/// with \matcher{type=sub$expr()} matching \match{sub=false$b}.
-/// The matcher
-/// \matcher{binaryConditionalOperator(hasFalseExpression(expr().bind("false")))}
-/// matches \match{condition ?: b},
-/// with \matcher{type=sub$expr()} matching \match{sub=false$b}.
AST_MATCHER_P(AbstractConditionalOperator, hasFalseExpression,
internal::Matcher<Expr>, InnerMatcher) {
const Expr *Expression = Node.getFalseExpr();
@@ -8153,16 +6198,6 @@ AST_MATCHER_P(AbstractConditionalOperator, hasFalseExpression,
/// extern int vb; // Doesn't match, as it doesn't define the variable.
/// void fa() {}
/// void fb(); // Doesn't match, as it has no body.
-/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{tagDecl(isDefinition())}
-/// matches \match{class A {}}.
-/// The matcher \matcher{varDecl(isDefinition())}
-/// matches \match{int va}.
-/// The matcher \matcher{functionDecl(isDefinition())}
-/// matches \match{void fa() {}}.
-///
-/// \code
/// @interface X
/// - (void)ma; // Doesn't match, interface is declaration.
/// @end
@@ -8170,9 +6205,6 @@ AST_MATCHER_P(AbstractConditionalOperator, hasFalseExpression,
/// - (void)ma {}
/// @end
/// \endcode
-/// \compile_args{-ObjC}
-/// The matcher \matcher{objcMethodDecl(isDefinition())}
-/// matches \match{- (void)ma {}}
///
/// Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl>,
/// Matcher<ObjCMethodDecl>
@@ -8193,12 +6225,6 @@ AST_POLYMORPHIC_MATCHER(isDefinition,
/// template <typename... Ts> void h(Ts...);
/// void i();
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{functionDecl(isVariadic())}
-/// matches \match{void f(...)},
-/// but does not match \nomatch{void g(int)},
-/// \nomatch{template <typename... Ts> void h(Ts...)},
-/// or \nomatch{void i()}.
AST_MATCHER(FunctionDecl, isVariadic) {
return Node.isVariadic();
}
@@ -8210,17 +6236,16 @@ AST_MATCHER(FunctionDecl, isVariadic) {
/// FIXME: What other kind of declarations would we need to generalize
/// this to?
///
-/// Given
+/// Example matches A() in the last line
+/// (matcher = cxxConstructExpr(hasDeclaration(cxxMethodDecl(
+/// ofClass(hasName("A"))))))
/// \code
/// class A {
/// public:
/// A();
-/// void foo();
/// };
+/// A a = A();
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxMethodDecl(ofClass(hasName("A")))}
-/// matches \match{A()} and \match{void foo()}.
AST_MATCHER_P(CXXMethodDecl, ofClass,
internal::Matcher<CXXRecordDecl>, InnerMatcher) {
@@ -8240,14 +6265,10 @@ AST_MATCHER_P(CXXMethodDecl, ofClass,
/// class B : public A { void f(); };
/// class C : public B { void f(); };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxMethodDecl(ofClass(hasName("C")),
-/// forEachOverridden(cxxMethodDecl().bind("b")))}
-/// matches \match{void f()} of \c C ,
-/// with \matcher{type=sub$cxxMethodDecl()} matching
-/// \match{sub=b$virtual void f()} of \c A ,
-/// but the matcher does not match \nomatch{void f()} of \c B because
-/// it is not overridden by C::f.
+/// cxxMethodDecl(ofClass(hasName("C")),
+/// forEachOverridden(cxxMethodDecl().bind("b"))).bind("d")
+/// matches once, with "b" binding "A::f" and "d" binding "C::f" (Note
+/// that B::f is not overridden by C::f).
///
/// The check can produce multiple matches in case of multiple inheritance, e.g.
/// \code
@@ -8255,14 +6276,10 @@ AST_MATCHER_P(CXXMethodDecl, ofClass,
/// class A2 { virtual void f(); };
/// class C : public A1, public A2 { void f(); };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxMethodDecl(ofClass(hasName("C")),
-/// forEachOverridden(cxxMethodDecl().bind("b")))}
-/// matches \match{void f()} of \c C with the inner
-/// \matcher{type=sub$cxxMethodDecl()} matching \match{sub=b$virtual void f()}
-/// inside of \c A1 , and \match{void f()} of \c C with the inner
-/// \matcher{type=sub$cxxMethodDecl()} matching \match{sub=b$virtual void f()}
-/// inside of \c A2.
+/// cxxMethodDecl(ofClass(hasName("C")),
+/// forEachOverridden(cxxMethodDecl().bind("b"))).bind("d")
+/// matches twice, once with "b" binding "A1::f" and "d" binding "C::f", and
+/// once with "b" binding "A2::f" and "d" binding "C::f".
AST_MATCHER_P(CXXMethodDecl, forEachOverridden,
internal::Matcher<CXXMethodDecl>, InnerMatcher) {
BoundNodesTreeBuilder Result;
@@ -8283,27 +6300,20 @@ AST_MATCHER_P(CXXMethodDecl, forEachOverridden,
/// Matches declarations of virtual methods and C++ base specifers that specify
/// virtual inheritance.
///
-/// Given
+/// Example:
/// \code
/// class A {
/// public:
/// virtual void x(); // matches x
/// };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxMethodDecl(isVirtual())}
-/// matches \match{virtual void x()}.
///
-/// Given
+/// Example:
/// \code
-/// struct Base {};
-/// struct DirectlyDerived : virtual Base {}; // matches Base
-/// struct IndirectlyDerived : DirectlyDerived, Base {}; // matches Base
+/// class Base {};
+/// class DirectlyDerived : virtual Base {}; // matches Base
+/// class IndirectlyDerived : DirectlyDerived, Base {}; // matches Base
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{cxxRecordDecl(hasDirectBase(cxxBaseSpecifier(isVirtual())))}
-/// matches \match{struct DirectlyDerived : virtual Base {}}.
///
/// Usable as: Matcher<CXXMethodDecl>, Matcher<CXXBaseSpecifier>
AST_POLYMORPHIC_MATCHER(isVirtual,
@@ -8325,10 +6335,7 @@ AST_POLYMORPHIC_MATCHER(isVirtual,
/// void x();
/// };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxMethodDecl(isVirtualAsWritten())}
-/// matches \match{virtual void x()} of \c A,
-/// but does not match \notmatch{void x()} of \c B .
+/// matches A::x but not B::x
AST_MATCHER(CXXMethodDecl, isVirtualAsWritten) {
return Node.isVirtualAsWritten();
}
@@ -8339,7 +6346,7 @@ AST_MATCHER(CXXConstructorDecl, isInheritingConstructor) {
/// Matches if the given method or class declaration is final.
///
-/// Given
+/// Given:
/// \code
/// class A final {};
///
@@ -8351,13 +6358,7 @@ AST_MATCHER(CXXConstructorDecl, isInheritingConstructor) {
/// void f() final;
/// };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxRecordDecl(isFinal())}
-/// matches \match{class A final {}},
-/// but does not match \nomatch{type=name$B} or \nomatch{type=name$C}.
-/// The matcher \matcher{cxxMethodDecl(isFinal())}
-/// matches \match{void f() final} in \c C ,
-/// but it does not match \nomatch{virtual void f()} in \c B .
+/// matches A and C::f, but not B, C, or B::f
AST_POLYMORPHIC_MATCHER(isFinal,
AST_POLYMORPHIC_SUPPORTED_TYPES(CXXRecordDecl,
CXXMethodDecl)) {
@@ -8373,9 +6374,7 @@ AST_POLYMORPHIC_MATCHER(isFinal,
/// virtual void x() = 0;
/// };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxMethodDecl(isPure())}
-/// matches \match{virtual void x() = 0}
+/// matches A::x
AST_MATCHER(CXXMethodDecl, isPure) { return Node.isPureVirtual(); }
/// Matches if the given method declaration is const.
@@ -8387,10 +6386,8 @@ AST_MATCHER(CXXMethodDecl, isPure) { return Node.isPureVirtual(); }
/// void bar();
/// };
/// \endcode
-/// \compile_args{-std=c++}
///
-/// The matcher \matcher{cxxMethodDecl(isConst())}
-/// matches \match{void foo() const} but not \nomatch{void bar()}.
+/// cxxMethodDecl(isConst()) matches A::foo() but not A::bar()
AST_MATCHER(CXXMethodDecl, isConst) {
return Node.isConst();
}
@@ -8405,11 +6402,9 @@ AST_MATCHER(CXXMethodDecl, isConst) {
/// A &operator=(A &&);
/// };
/// \endcode
-/// \compile_args{-std=c++}
///
-/// The matcher \matcher{cxxMethodDecl(isCopyAssignmentOperator())}
-/// matches \match{A &operator=(const A &)}
-/// but does not match \nomatch{A &operator=(A &&)}
+/// cxxMethodDecl(isCopyAssignmentOperator()) matches the first method but not
+/// the second one.
AST_MATCHER(CXXMethodDecl, isCopyAssignmentOperator) {
return Node.isCopyAssignmentOperator();
}
@@ -8424,11 +6419,9 @@ AST_MATCHER(CXXMethodDecl, isCopyAssignmentOperator) {
/// A &operator=(A &&);
/// };
/// \endcode
-/// \compile_args{-std=c++}
///
-/// The matcher \matcher{cxxMethodDecl(isMoveAssignmentOperator())}
-/// matches \match{A &operator=(A &&)}
-/// but does not match \nomatch{A &operator=(const A &)}
+/// cxxMethodDecl(isMoveAssignmentOperator()) matches the second method but not
+/// the first one.
AST_MATCHER(CXXMethodDecl, isMoveAssignmentOperator) {
return Node.isMoveAssignmentOperator();
}
@@ -8443,12 +6436,10 @@ AST_MATCHER(CXXMethodDecl, isMoveAssignmentOperator) {
/// };
/// class B : public A {
/// public:
-/// void x() override;
+/// virtual void x();
/// };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxMethodDecl(isOverride())}
-/// matches \match{void x() override}
+/// matches B::x
AST_MATCHER(CXXMethodDecl, isOverride) {
return Node.size_overridden_methods() > 0 || Node.hasAttr<OverrideAttr>();
}
@@ -8463,10 +6454,7 @@ AST_MATCHER(CXXMethodDecl, isOverride) {
/// S(S &&) = delete; // #3
/// };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxConstructorDecl(isUserProvided())}
-/// will match \match{S()}, but not \notmatch{S(const S &) = default} or
-/// \notmatch{S(S &&) = delete}
+/// cxxConstructorDecl(isUserProvided()) will match #1, but not #2 or #3.
AST_MATCHER(CXXMethodDecl, isUserProvided) {
return Node.isUserProvided();
}
@@ -8486,26 +6474,15 @@ AST_MATCHER(CXXMethodDecl, isUserProvided) {
/// };
/// template <class T>
/// class Z {
-/// void x() {
-/// this->m;
-/// this->t;
-/// this->t->m;
-/// }
-/// int m;
-/// T* t;
+/// void x() { this->m; }
/// };
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{memberExpr(isArrow())}
-/// matches \match{this->x}, \match{x}, \match{a},
-/// \match{this->b}, \match{this->m} and two times \match{count=2$this->t},
-/// once for the standalone member expression, and once for the member
-/// expression that later accesses \c m .
-/// Additionally, it does not match \nomatch{this->t->t}.
-/// The matcher \matcher{cxxDependentScopeMemberExpr(isArrow())}
-/// matches \match{this->t->m}, but not \nomatch{this->m} or \nomatch{this->t}.
-/// The matcher \matcher{unresolvedMemberExpr(isArrow())}
-/// matches \match{this->f<T>}, \match{f<T>}
+/// memberExpr(isArrow())
+/// matches this->x, x, y.x, a, this->b
+/// cxxDependentScopeMemberExpr(isArrow())
+/// matches this->m
+/// unresolvedMemberExpr(isArrow())
+/// matches this->f<T>, f<T>
AST_POLYMORPHIC_MATCHER(
isArrow, AST_POLYMORPHIC_SUPPORTED_TYPES(MemberExpr, UnresolvedMemberExpr,
CXXDependentScopeMemberExpr)) {
@@ -8520,8 +6497,8 @@ AST_POLYMORPHIC_MATCHER(
/// void b(long);
/// void c(double);
/// \endcode
-/// The matcher \matcher{functionDecl(hasAnyParameter(hasType(isInteger())))}
-/// \match{void a(int)}, \match{void b(long)}, but not \nomatch{void c(double)}.
+/// functionDecl(hasAnyParameter(hasType(isInteger())))
+/// matches "a(int)", "b(long)", but not "c(double)".
AST_MATCHER(QualType, isInteger) {
return Node->isIntegerType();
}
@@ -8534,10 +6511,8 @@ AST_MATCHER(QualType, isInteger) {
/// void b(unsigned long);
/// void c(double);
/// \endcode
-/// The matcher
-/// \matcher{functionDecl(hasAnyParameter(hasType(isUnsignedInteger())))}
-/// matches \match{void b(unsigned long)},
-/// but it does not match \nomatch{void a(int)} and \nomatch{void c(double)}.
+/// functionDecl(hasAnyParameter(hasType(isUnsignedInteger())))
+/// matches "b(unsigned long)", but not "a(int)" and "c(double)".
AST_MATCHER(QualType, isUnsignedInteger) {
return Node->isUnsignedIntegerType();
}
@@ -8550,10 +6525,8 @@ AST_MATCHER(QualType, isUnsignedInteger) {
/// void b(unsigned long);
/// void c(double);
/// \endcode
-/// The matcher
-/// \matcher{functionDecl(hasAnyParameter(hasType(isSignedInteger())))} matches
-/// \match{void a(int)}, but not \notmatch{void b(unsigned long)} or
-/// \notmatch{void c(double)}.
+/// functionDecl(hasAnyParameter(hasType(isSignedInteger())))
+/// matches "a(int)", but not "b(unsigned long)" and "c(double)".
AST_MATCHER(QualType, isSignedInteger) {
return Node->isSignedIntegerType();
}
@@ -8566,12 +6539,8 @@ AST_MATCHER(QualType, isSignedInteger) {
/// void b(wchar_t);
/// void c(double);
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher
-/// \matcher{functionDecl(hasAnyParameter(hasType(isAnyCharacter())))}
-/// \match{void a(char)}, \match{void b(wchar_t)}, but not
-/// \notmatch{void c(double)}.
+/// functionDecl(hasAnyParameter(hasType(isAnyCharacter())))
+/// matches "a(char)", "b(wchar_t)", but not "c(double)".
AST_MATCHER(QualType, isAnyCharacter) {
return Node->isAnyCharacterType();
}
@@ -8590,9 +6559,8 @@ AST_MATCHER(QualType, isAnyCharacter) {
///
/// int j;
/// \endcode
-/// \compile_args{-ObjC}
-/// The matcher \matcher{varDecl(hasType(isAnyPointer()))}
-/// \match{int *i} and \match{Foo *f}, but not \nomatch{int j}.
+/// varDecl(hasType(isAnyPointer()))
+/// matches "int *i" and "Foo *f", but not "int j".
AST_MATCHER(QualType, isAnyPointer) {
return Node->isAnyPointerType();
}
@@ -8606,12 +6574,12 @@ AST_MATCHER(QualType, isAnyPointer) {
/// void b(int const);
/// void c(const int);
/// void d(const int*);
+/// void e(int const) {};
/// \endcode
-/// The matcher
-/// \matcher{functionDecl(hasAnyParameter(hasType(isConstQualified())))}
-/// matches \match{void b(int const)} and \match{void c(const int)}.
-/// It does not match \notmatch{void d(const int*)} as there
-/// is no top-level \c const on the parameter type \c{const int *}.
+/// functionDecl(hasAnyParameter(hasType(isConstQualified())))
+/// matches "void b(int const)", "void c(const int)" and
+/// "void e(int const) {}". It does not match d as there
+/// is no top-level const on the parameter type "const int *".
AST_MATCHER(QualType, isConstQualified) {
return Node.isConstQualified();
}
@@ -8625,12 +6593,12 @@ AST_MATCHER(QualType, isConstQualified) {
/// void b(int volatile);
/// void c(volatile int);
/// void d(volatile int*);
+/// void e(int volatile) {};
/// \endcode
-/// The matcher
-/// \matcher{functionDecl(hasAnyParameter(hasType(isVolatileQualified())))}
-/// matches \match{void b(int volatile)} and \match{void c(volatile int)}.
-/// It does not match \notmatch{void d(volatile int*)} as there
-/// is no top-level volatile on the parameter type "volatile int *".
+/// functionDecl(hasAnyParameter(hasType(isVolatileQualified())))
+/// matches "void b(int volatile)", "void c(volatile int)" and
+/// "void e(int volatile) {}". It does not match d as there
+/// is no top-level volatile on the parameter type "volatile int *".
AST_MATCHER(QualType, isVolatileQualified) {
return Node.isVolatileQualified();
}
@@ -8641,16 +6609,13 @@ AST_MATCHER(QualType, isVolatileQualified) {
/// Given
/// \code
/// typedef const int const_int;
-/// const_int i = 0;
-/// int *const j = nullptr;
+/// const_int i;
+/// int *const j;
/// int *volatile k;
/// int m;
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-///
-/// The matcher \matcher{varDecl(hasType(hasLocalQualifiers()))} matches
-/// \match{int *const j = nullptr} and \match{int *volatile k},
-/// bot not \notmatch{const_int i} because the const qualifier is not local.
+/// \c varDecl(hasType(hasLocalQualifiers())) matches only \c j and \c k.
+/// \c i is const-qualified but the qualifier is not local.
AST_MATCHER(QualType, hasLocalQualifiers) {
return Node.hasLocalQualifiers();
}
@@ -8660,15 +6625,13 @@ AST_MATCHER(QualType, hasLocalQualifiers) {
///
/// Given
/// \code
-/// struct { int first = 0, second = 1; } first, second;
-/// int i = second.first;
-/// int j = first.second;
+/// struct { int first, second; } first, second;
+/// int i(second.first);
+/// int j(first.second);
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{memberExpr(member(hasName("first")))}
-/// matches \match{second.first}
-/// but not \notmatch{first.second}.
+/// memberExpr(member(hasName("first")))
+/// matches second.first
+/// but not first.second (because the member name there is "second").
AST_MATCHER_P(MemberExpr, member,
internal::Matcher<ValueDecl>, InnerMatcher) {
return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder);
@@ -8685,14 +6648,11 @@ AST_MATCHER_P(MemberExpr, member,
/// int f(X x) { x.m; return m; }
/// };
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher
-/// \matcher{memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))))}
-/// matches \match{x.m}, but not \nomatch{m}; however,
-/// The matcher \matcher{memberExpr(hasObjectExpression(hasType(pointsTo(
-/// cxxRecordDecl(hasName("X"))))))}
-/// matches \match{m} (aka. this->m), but not \nomatch{x.m}.
+/// memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))))
+/// matches `x.m`, but not `m`; however,
+/// memberExpr(hasObjectExpression(hasType(pointsTo(
+// cxxRecordDecl(hasName("X"))))))
+/// matches `m` (aka. `this->m`), but not `x.m`.
AST_POLYMORPHIC_MATCHER_P(
hasObjectExpression,
AST_POLYMORPHIC_SUPPORTED_TYPES(MemberExpr, UnresolvedMemberExpr,
@@ -8714,9 +6674,8 @@ AST_POLYMORPHIC_MATCHER_P(
/// namespace X { void b(); }
/// using X::b;
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{usingDecl(hasAnyUsingShadowDecl(hasName("b")))}
-/// matches \match{using X::b}
+/// usingDecl(hasAnyUsingShadowDecl(hasName("b"))))
+/// matches \code using X::b \endcode
AST_MATCHER_P(BaseUsingDecl, hasAnyUsingShadowDecl,
internal::Matcher<UsingShadowDecl>, InnerMatcher) {
return matchesFirstInPointerRange(InnerMatcher, Node.shadow_begin(),
@@ -8733,11 +6692,9 @@ AST_MATCHER_P(BaseUsingDecl, hasAnyUsingShadowDecl,
/// using X::a;
/// using X::b;
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher
-/// \matcher{usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(functionDecl())))}
-/// matches \match{using X::b}
-/// but not \notmatch{using X::a}
+/// usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(functionDecl())))
+/// matches \code using X::b \endcode
+/// but not \code using X::a \endcode
AST_MATCHER_P(UsingShadowDecl, hasTargetDecl,
internal::Matcher<NamedDecl>, InnerMatcher) {
return InnerMatcher.matches(*Node.getTargetDecl(), Finder, Builder);
@@ -8748,44 +6705,26 @@ AST_MATCHER_P(UsingShadowDecl, hasTargetDecl,
///
/// Given
/// \code
-/// template <typename T> class X {};
-/// class A {};
-/// X<A> x;
+/// template <typename T> class X {}; class A {}; X<A> x;
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{cxxRecordDecl(hasName("::X"),
-/// isTemplateInstantiation())}
-/// matches \match{type=typestr$class X<class A>}.
+/// or
/// \code
-/// template <typename T> class X {};
-/// class A {};
-/// template class X<A>;
+/// template <typename T> class X {}; class A {}; template class X<A>;
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{cxxRecordDecl(hasName("::X"),
-/// isTemplateInstantiation())}
-/// matches \match{template class X<A>}
+/// or
/// \code
-/// template <typename T> class X {};
-/// class A {};
-/// extern template class X<A>;
+/// template <typename T> class X {}; class A {}; extern template class X<A>;
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{cxxRecordDecl(hasName("::X"),
-/// isTemplateInstantiation())}
-/// matches \match{extern template class X<A>}
+/// cxxRecordDecl(hasName("::X"), isTemplateInstantiation())
+/// matches the template instantiation of X<A>.
///
/// But given
/// \code
-/// template <typename T> class X {};
-/// class A {};
-/// template <> class X<A> {};
-/// X<A> x;
+/// template <typename T> class X {}; class A {};
+/// template <> class X<A> {}; X<A> x;
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{cxxRecordDecl(hasName("::X"),
-/// isTemplateInstantiation())}
-/// \nomatch{} does not match, as X<A> is an explicit template specialization.
+/// cxxRecordDecl(hasName("::X"), isTemplateInstantiation())
+/// does not match, as X<A> is an explicit template specialization.
///
/// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl>
AST_POLYMORPHIC_MATCHER(isTemplateInstantiation,
@@ -8804,15 +6743,11 @@ AST_POLYMORPHIC_MATCHER(isTemplateInstantiation,
/// Given
/// \code
/// template<typename T> void A(T t) { T i; }
-/// void foo() {
-/// A(0);
-/// A(0U);
-/// }
+/// A(0);
+/// A(0U);
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{functionDecl(isInstantiated())}
-/// matches the two instantiations of \match{count=2$void A(T t) { T i; }} that
-/// are generated for \c int , and for \c{unsigned int}.
+/// functionDecl(isInstantiated())
+/// matches 'A(int) {...};' and 'A(unsigned) {...}'.
AST_MATCHER_FUNCTION(internal::Matcher<Decl>, isInstantiated) {
auto IsInstantiation = decl(anyOf(cxxRecordDecl(isTemplateInstantiation()),
functionDecl(isTemplateInstantiation()),
@@ -8825,19 +6760,15 @@ AST_MATCHER_FUNCTION(internal::Matcher<Decl>, isInstantiated) {
/// Given
/// \code
/// int j;
-/// template<typename T> void A(T t) { T i; }
-/// void foo() {
-/// A(0);
-/// A(0U);
-/// }
-/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{declStmt(isInTemplateInstantiation())}
-/// matches \match{count=2$T i;} twice, once for \c int and once for
-/// \c{unsigned int}.
-/// The matcher \matcher{declStmt(unless(isInTemplateInstantiation()))} will
-/// match \match{T i;} once inside the template definition, but not for any of
-/// the instantiated bodies.
+/// template<typename T> void A(T t) { T i; j += 42;}
+/// A(0);
+/// A(0U);
+/// \endcode
+/// declStmt(isInTemplateInstantiation())
+/// matches 'int i;' and 'unsigned i'.
+/// unless(stmt(isInTemplateInstantiation()))
+/// will NOT match j += 42; as it's shared between the template definition and
+/// instantiation.
AST_MATCHER_FUNCTION(internal::Matcher<Stmt>, isInTemplateInstantiation) {
return stmt(hasAncestor(decl(anyOf(cxxRecordDecl(isTemplateInstantiation()),
functionDecl(isTemplateInstantiation()),
@@ -8852,9 +6783,8 @@ AST_MATCHER_FUNCTION(internal::Matcher<Stmt>, isInTemplateInstantiation) {
/// template<typename T> void A(T t) { }
/// template<> void A(int N) { }
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{functionDecl(isExplicitTemplateSpecialization())}
-/// matches the specialization \match{template<> void A(int N) { }}.
+/// functionDecl(isExplicitTemplateSpecialization())
+/// matches the specialization A<int>().
///
/// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl>
AST_POLYMORPHIC_MATCHER(isExplicitTemplateSpecialization,
@@ -8865,13 +6795,6 @@ AST_POLYMORPHIC_MATCHER(isExplicitTemplateSpecialization,
/// Matches \c TypeLocs for which the given inner
/// QualType-matcher matches.
-///
-/// \code
-/// int a = 10;
-/// \endcode
-///
-/// The matcher \matcher{typeLoc(loc(qualType(isInteger())))}
-/// matches the \match{int} of \c a .
AST_MATCHER_FUNCTION_P_OVERLOAD(internal::BindableMatcher<TypeLoc>, loc,
internal::Matcher<QualType>, InnerMatcher, 0) {
return internal::BindableMatcher<TypeLoc>(
@@ -8884,11 +6807,8 @@ AST_MATCHER_FUNCTION_P_OVERLOAD(internal::BindableMatcher<TypeLoc>, loc,
/// \code
/// const int x = 0;
/// \endcode
-///
-/// The matcher \matcher{qualifiedTypeLoc()}
-/// matches the type of the variable declaration \c x . However, the
-/// current implementation of \c QualifiedTypeLoc does not store the source
-/// locations for the qualifiers of the type \match{int}.
+/// qualifiedTypeLoc()
+/// matches `const int`.
extern const internal::VariadicDynCastAllOfMatcher<TypeLoc, QualifiedTypeLoc>
qualifiedTypeLoc;
@@ -8897,14 +6817,11 @@ extern const internal::VariadicDynCastAllOfMatcher<TypeLoc, QualifiedTypeLoc>
///
/// Given
/// \code
-/// int* const x = nullptr;
-/// const int y = 0;
+/// int* const x;
+/// const int y;
/// \endcode
-/// \compile_args{-std=c++11-or-later,c23-or-later}
-///
-/// The matcher \matcher{qualifiedTypeLoc(hasUnqualifiedLoc(pointerTypeLoc()))}
-/// matches the type \match{int*} of the variable declaration \c{x}, but
-/// not \c{y}.
+/// qualifiedTypeLoc(hasUnqualifiedLoc(pointerTypeLoc()))
+/// matches the `TypeLoc` of the variable declaration of `x`, but not `y`.
AST_MATCHER_P(QualifiedTypeLoc, hasUnqualifiedLoc, internal::Matcher<TypeLoc>,
InnerMatcher) {
return InnerMatcher.matches(Node.getUnqualifiedLoc(), Finder, Builder);
@@ -8917,11 +6834,8 @@ AST_MATCHER_P(QualifiedTypeLoc, hasUnqualifiedLoc, internal::Matcher<TypeLoc>,
/// int f() { return 5; }
/// void g() {}
/// \endcode
-/// The matcher
-/// \matcher{functionDecl(hasReturnTypeLoc(typeLoc(loc(asString("int")))))}
-/// matches the declaration of \match{int f() { return 5; }} with
-/// \matcher{type=sub$typeLoc(loc(asString("int")))} matching the spelling of
-/// \match{sub=loc$int}, but the matcher does not match \notmatch{void g() {}}.
+/// functionDecl(hasReturnTypeLoc(loc(asString("int"))))
+/// matches the declaration of `f`, but not `g`.
AST_MATCHER_P(FunctionDecl, hasReturnTypeLoc, internal::Matcher<TypeLoc>,
ReturnMatcher) {
auto Loc = Node.getFunctionTypeLoc();
@@ -8934,8 +6848,8 @@ AST_MATCHER_P(FunctionDecl, hasReturnTypeLoc, internal::Matcher<TypeLoc>,
/// \code
/// int* x;
/// \endcode
-/// The matcher \matcher{pointerTypeLoc()}
-/// matches \match{int*}.
+/// pointerTypeLoc()
+/// matches `int*`.
extern const internal::VariadicDynCastAllOfMatcher<TypeLoc, PointerTypeLoc>
pointerTypeLoc;
@@ -8946,8 +6860,8 @@ extern const internal::VariadicDynCastAllOfMatcher<TypeLoc, PointerTypeLoc>
/// \code
/// int* x;
/// \endcode
-/// The matcher \matcher{pointerTypeLoc(hasPointeeLoc(loc(asString("int"))))}
-/// matches \match{int*}.
+/// pointerTypeLoc(hasPointeeLoc(loc(asString("int"))))
+/// matches `int*`.
AST_MATCHER_P(PointerTypeLoc, hasPointeeLoc, internal::Matcher<TypeLoc>,
PointeeMatcher) {
return PointeeMatcher.matches(Node.getPointeeLoc(), Finder, Builder);
@@ -8961,10 +6875,8 @@ AST_MATCHER_P(PointerTypeLoc, hasPointeeLoc, internal::Matcher<TypeLoc>,
/// int& l = x;
/// int&& r = 3;
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{referenceTypeLoc()}
-/// matches \match{int&} and \match{int&&}.
+/// referenceTypeLoc()
+/// matches `int&` and `int&&`.
extern const internal::VariadicDynCastAllOfMatcher<TypeLoc, ReferenceTypeLoc>
referenceTypeLoc;
@@ -8976,10 +6888,8 @@ extern const internal::VariadicDynCastAllOfMatcher<TypeLoc, ReferenceTypeLoc>
/// int x = 3;
/// int& xx = x;
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{referenceTypeLoc(hasReferentLoc(loc(asString("int"))))}
-/// matches \match{int&}.
+/// referenceTypeLoc(hasReferentLoc(loc(asString("int"))))
+/// matches `int&`.
AST_MATCHER_P(ReferenceTypeLoc, hasReferentLoc, internal::Matcher<TypeLoc>,
ReferentMatcher) {
return ReferentMatcher.matches(Node.getPointeeLoc(), Finder, Builder);
@@ -8992,11 +6902,8 @@ AST_MATCHER_P(ReferenceTypeLoc, hasReferentLoc, internal::Matcher<TypeLoc>,
/// template <typename T> class C {};
/// C<char> var;
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher
-/// \matcher{varDecl(hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
-/// templateSpecializationTypeLoc(typeLoc())))))}
-/// matches \match{C<char> var}.
+/// varDecl(hasTypeLoc(templateSpecializationTypeLoc(typeLoc())))
+/// matches `C<char> var`.
extern const internal::VariadicDynCastAllOfMatcher<
TypeLoc, TemplateSpecializationTypeLoc>
templateSpecializationTypeLoc;
@@ -9011,11 +6918,9 @@ extern const internal::VariadicDynCastAllOfMatcher<
/// template<typename T> class A {};
/// A<int> a;
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher
-/// \matcher{varDecl(hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
-/// templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
-/// hasTypeLoc(loc(asString("int")))))))))} matches \match{A<int> a}.
+/// varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
+/// hasTypeLoc(loc(asString("int")))))))
+/// matches `A<int> a`.
AST_POLYMORPHIC_MATCHER_P(
hasAnyTemplateArgumentLoc,
AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
@@ -9038,12 +6943,9 @@ AST_POLYMORPHIC_MATCHER_P(
/// A<double, int> b;
/// A<int, double> c;
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher
-/// \matcher{varDecl(hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
-/// templateSpecializationTypeLoc(hasTemplateArgumentLoc(0,
-/// hasTypeLoc(loc(asString("double")))))))))}
-/// matches \match{A<double, int> b}, but not \notmatch{A<int, double> c}.
+/// varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(0,
+/// hasTypeLoc(loc(asString("double")))))))
+/// matches `A<double, int> b`, but not `A<int, double> c`.
AST_POLYMORPHIC_MATCHER_P2(
hasTemplateArgumentLoc,
AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
@@ -9062,8 +6964,8 @@ AST_POLYMORPHIC_MATCHER_P2(
/// struct s {};
/// struct s ss;
/// \endcode
-/// The matcher \matcher{elaboratedTypeLoc()}
-/// matches the type \match{struct s} of \c ss.
+/// elaboratedTypeLoc()
+/// matches the `TypeLoc` of the variable declaration of `ss`.
extern const internal::VariadicDynCastAllOfMatcher<TypeLoc, ElaboratedTypeLoc>
elaboratedTypeLoc;
@@ -9079,10 +6981,8 @@ extern const internal::VariadicDynCastAllOfMatcher<TypeLoc, ElaboratedTypeLoc>
/// class D {};
/// class D d;
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher
-/// \matcher{elaboratedTypeLoc(hasNamedTypeLoc(templateSpecializationTypeLoc()))}
-/// matches \match{class C<int>}, but not \notmatch{ckass D}
+/// elaboratedTypeLoc(hasNamedTypeLoc(templateSpecializationTypeLoc()));
+/// matches the `TypeLoc` of the variable declaration of `c`, but not `d`.
AST_MATCHER_P(ElaboratedTypeLoc, hasNamedTypeLoc, internal::Matcher<TypeLoc>,
InnerMatcher) {
return InnerMatcher.matches(Node.getNamedTypeLoc(), Finder, Builder);
@@ -9094,9 +6994,8 @@ AST_MATCHER_P(ElaboratedTypeLoc, hasNamedTypeLoc, internal::Matcher<TypeLoc>,
/// \code
/// struct S { bool func(); };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{functionDecl(returns(booleanType()))}
-/// \match{bool func()}.
+/// functionDecl(returns(booleanType()))
+/// matches "bool func();"
AST_MATCHER(Type, booleanType) {
return Node.isBooleanType();
}
@@ -9107,10 +7006,8 @@ AST_MATCHER(Type, booleanType) {
/// \code
/// struct S { void func(); };
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{functionDecl(returns(voidType()))}
-/// \match{void func()}.
+/// functionDecl(returns(voidType()))
+/// matches "void func();"
AST_MATCHER(Type, voidType) {
return Node.isVoidType();
}
@@ -9122,13 +7019,14 @@ using AstTypeMatcher = internal::VariadicDynCastAllOfMatcher<Type, NodeType>;
///
/// Given
/// \code
-/// enum E { Ok };
-/// enum E e;
+/// struct A {};
+/// A a;
/// int b;
/// float c;
+/// bool d;
/// \endcode
-/// The matcher \matcher{varDecl(hasType(builtinType()))}
-/// matches \match{int b} and \match{float c}.
+/// builtinType()
+/// matches "int b", "float c" and "bool d"
extern const AstTypeMatcher<BuiltinType> builtinType;
/// Matches all kinds of arrays.
@@ -9139,9 +7037,8 @@ extern const AstTypeMatcher<BuiltinType> builtinType;
/// int b[4];
/// void f() { int c[a[0]]; }
/// \endcode
-/// The matcher \matcher{arrayType()}
-/// \match{type=typestr$int[4]}, \match{type=typestr$int[a[0]]} and
-/// \match{type=typestr$int[]};
+/// arrayType()
+/// matches "int a[]", "int b[4]" and "int c[a[0]]";
extern const AstTypeMatcher<ArrayType> arrayType;
/// Matches C99 complex types.
@@ -9150,8 +7047,8 @@ extern const AstTypeMatcher<ArrayType> arrayType;
/// \code
/// _Complex float f;
/// \endcode
-/// The matcher \matcher{complexType()}
-/// \match{type=typestr$_Complex float}
+/// complexType()
+/// matches "_Complex float f"
extern const AstTypeMatcher<ComplexType> complexType;
/// Matches any real floating-point type (float, double, long double).
@@ -9161,9 +7058,8 @@ extern const AstTypeMatcher<ComplexType> complexType;
/// int i;
/// float f;
/// \endcode
-/// The matcher \matcher{type(realFloatingPointType())}
-/// matches \match{type=typestr$float}
-/// but does not match \nomatch{type=typestr$int}.
+/// realFloatingPointType()
+/// matches "float f" but not "int i"
AST_MATCHER(Type, realFloatingPointType) {
return Node.isRealFloatingType();
}
@@ -9177,10 +7073,8 @@ AST_MATCHER(Type, realFloatingPointType) {
/// A a[7];
/// int b[7];
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{arrayType(hasElementType(builtinType()))}
-/// \match{type=typestr$int[7]}
+/// arrayType(hasElementType(builtinType()))
+/// matches "int b[7]"
///
/// Usable as: Matcher<ArrayType>, Matcher<ComplexType>
AST_TYPELOC_TRAVERSE_MATCHER_DECL(hasElementType, getElement,
@@ -9191,14 +7085,14 @@ AST_TYPELOC_TRAVERSE_MATCHER_DECL(hasElementType, getElement,
///
/// Given
/// \code
-/// void foo() {
+/// void() {
/// int a[2];
/// int b[] = { 2, 3 };
/// int c[b[0]];
/// }
/// \endcode
-/// The matcher \matcher{constantArrayType()}
-/// \match{type=typestr$int[2]}
+/// constantArrayType()
+/// matches "int a[2]"
extern const AstTypeMatcher<ConstantArrayType> constantArrayType;
/// Matches nodes that have the specified size.
@@ -9212,11 +7106,10 @@ extern const AstTypeMatcher<ConstantArrayType> constantArrayType;
/// wchar_t *ws = L"abcd";
/// char *w = "a";
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{constantArrayType(hasSize(42))}
-/// matches \match{type=typestr;count=2$int[42]} twice.
-/// The matcher \matcher{stringLiteral(hasSize(4))}
-/// matches \match{"abcd"} and \match{L"abcd"}.
+/// constantArrayType(hasSize(42))
+/// matches "int a[42]" and "int b[2 * 21]"
+/// stringLiteral(hasSize(4))
+/// matches "abcd", L"abcd"
AST_POLYMORPHIC_MATCHER_P(hasSize,
AST_POLYMORPHIC_SUPPORTED_TYPES(ConstantArrayType,
StringLiteral),
@@ -9233,9 +7126,8 @@ AST_POLYMORPHIC_MATCHER_P(hasSize,
/// T data[Size];
/// };
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{dependentSizedArrayType()}
-/// \match{type=typestr$T[Size]}
+/// dependentSizedArrayType()
+/// matches "T data[Size]"
extern const AstTypeMatcher<DependentSizedArrayType> dependentSizedArrayType;
/// Matches C++ extended vector type where either the type or size is
@@ -9248,9 +7140,8 @@ extern const AstTypeMatcher<DependentSizedArrayType> dependentSizedArrayType;
/// typedef T __attribute__((ext_vector_type(Size))) type;
/// };
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{dependentSizedExtVectorType()}
-/// \match{type=typestr$T __attribute__((ext_vector_type(Size)))}
+/// dependentSizedExtVectorType()
+/// matches "T __attribute__((ext_vector_type(Size)))"
extern const AstTypeMatcher<DependentSizedExtVectorType>
dependentSizedExtVectorType;
@@ -9262,8 +7153,8 @@ extern const AstTypeMatcher<DependentSizedExtVectorType>
/// int b[42];
/// void f(int c[]) { int d[a[0]]; };
/// \endcode
-/// The matcher \matcher{incompleteArrayType()}
-/// \match{type=typestr$int[]} and \match{type=typestr$int[]}
+/// incompleteArrayType()
+/// matches "int a[]" and "int c[]"
extern const AstTypeMatcher<IncompleteArrayType> incompleteArrayType;
/// Matches C arrays with a specified size that is not an
@@ -9272,13 +7163,13 @@ extern const AstTypeMatcher<IncompleteArrayType> incompleteArrayType;
/// Given
/// \code
/// void f() {
-/// int a[] = { 2, 3 };
+/// int a[] = { 2, 3 }
/// int b[42];
/// int c[a[0]];
/// }
/// \endcode
-/// The matcher \matcher{variableArrayType()}
-/// \match{type=typestr$int[a[0]]}
+/// variableArrayType()
+/// matches "int c[a[0]]"
extern const AstTypeMatcher<VariableArrayType> variableArrayType;
/// Matches \c VariableArrayType nodes that have a specific size
@@ -9290,10 +7181,9 @@ extern const AstTypeMatcher<VariableArrayType> variableArrayType;
/// int a[b];
/// }
/// \endcode
-/// The matcher
-/// \matcher{variableArrayType(hasSizeExpr(ignoringImpCasts(declRefExpr(to(
-/// varDecl(hasName("b")))))))}
-/// matches \match{type=typestr$int[b]}
+/// variableArrayType(hasSizeExpr(ignoringImpCasts(declRefExpr(to(
+/// varDecl(hasName("b")))))))
+/// matches "int a[b]"
AST_MATCHER_P(VariableArrayType, hasSizeExpr,
internal::Matcher<Expr>, InnerMatcher) {
return InnerMatcher.matches(*Node.getSizeExpr(), Finder, Builder);
@@ -9305,8 +7195,8 @@ AST_MATCHER_P(VariableArrayType, hasSizeExpr,
/// \code
/// _Atomic(int) i;
/// \endcode
-/// The matcher \matcher{atomicType()}
-/// \match{type=typestr$_Atomic(int)}
+/// atomicType()
+/// matches "_Atomic(int) i"
extern const AstTypeMatcher<AtomicType> atomicType;
/// Matches atomic types with a specific value type.
@@ -9316,8 +7206,8 @@ extern const AstTypeMatcher<AtomicType> atomicType;
/// _Atomic(int) i;
/// _Atomic(float) f;
/// \endcode
-/// The matcher \matcher{atomicType(hasValueType(isInteger()))}
-/// \match{type=typestr$_Atomic(int)}.
+/// atomicType(hasValueType(isInteger()))
+/// matches "_Atomic(int) i"
///
/// Usable as: Matcher<AtomicType>
AST_TYPELOC_TRAVERSE_MATCHER_DECL(hasValueType, getValue,
@@ -9325,32 +7215,26 @@ AST_TYPELOC_TRAVERSE_MATCHER_DECL(hasValueType, getValue,
/// Matches types nodes representing C++11 auto types.
///
-/// Given
+/// Given:
/// \code
-/// void foo() {
-/// auto n = 4;
-/// int v[] = { 2, 3 };
-/// for (auto i : v) { };
-/// }
+/// auto n = 4;
+/// int v[] = { 2, 3 }
+/// for (auto i : v) { }
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{autoType()}
-/// matches the \match{type=typestr;count=5$auto} of \c n and \c i ,
-/// as well as the auto types for the implicitly generated code of the range-for
-/// loop (for the range, the begin iterator and the end iterator).
+/// autoType()
+/// matches "auto n" and "auto i"
extern const AstTypeMatcher<AutoType> autoType;
/// Matches types nodes representing C++11 decltype(<expr>) types.
///
-/// Given
+/// Given:
/// \code
/// short i = 1;
/// int j = 42;
/// decltype(i + j) result = i + j;
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{decltypeType()}
-/// \match{type=typestr$decltype(i + j)}
+/// decltypeType()
+/// matches "decltype(i + j)"
extern const AstTypeMatcher<DecltypeType> decltypeType;
/// Matches \c AutoType nodes where the deduced type is a specific type.
@@ -9363,10 +7247,8 @@ extern const AstTypeMatcher<DecltypeType> decltypeType;
/// auto a = 1;
/// auto b = 2.0;
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher
-/// \matcher{varDecl(hasType(autoType(hasDeducedType(isInteger()))))}
-/// matches \match{auto a = 1}, but does not match \nomatch{auto b = 2.0}.
+/// autoType(hasDeducedType(isInteger()))
+/// matches "auto a"
///
/// Usable as: Matcher<AutoType>
AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType,
@@ -9379,11 +7261,8 @@ AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType,
/// decltype(1) a = 1;
/// decltype(2.0) b = 2.0;
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-///
-/// The matcher \matcher{decltypeType(hasUnderlyingType(isInteger()))}
-/// matches the type \match{type=typestr$decltype(1)} of the variable
-/// declaration of \c a .
+/// decltypeType(hasUnderlyingType(isInteger()))
+/// matches the type of "a"
///
/// Usable as: Matcher<DecltypeType>, Matcher<UsingType>
AST_TYPE_TRAVERSE_MATCHER(hasUnderlyingType, getUnderlyingType,
@@ -9397,12 +7276,8 @@ AST_TYPE_TRAVERSE_MATCHER(hasUnderlyingType, getUnderlyingType,
/// int (*f)(int);
/// void g();
/// \endcode
-/// The matcher \matcher{functionType()}
-/// \match{type=typestr$int (int)} and the type of
-/// \match{std=c++,c23-or-later;type=typestr$void (void)} in C++ and in C23 and
-/// later. Before C23, the function type for \c f will be matched the same way,
-/// but the function type for \c g will match
-/// \match{std=c17-or-earlier;type=typestr$void ()}.
+/// functionType()
+/// matches "int (*f)(int)" and the type of "g".
extern const AstTypeMatcher<FunctionType> functionType;
/// Matches \c FunctionProtoType nodes.
@@ -9412,11 +7287,9 @@ extern const AstTypeMatcher<FunctionType> functionType;
/// int (*f)(int);
/// void g();
/// \endcode
-/// The matcher \matcher{functionProtoType()}
-/// matches the type \match{type=typestr$int (int)} of 'f' and the type
-/// \match{std=c++,c23-or-later;type=typestr$void (void)} of 'g' in C++ mode.
-/// In C, the type \nomatch{std=c;type=typestr$void ()} of 'g' is not
-/// matched because it does not contain a prototype.
+/// functionProtoType()
+/// matches "int (*f)(int)" and the type of "g" in C++ mode.
+/// In C mode, "g" is not matched because it does not contain a prototype.
extern const AstTypeMatcher<FunctionProtoType> functionProtoType;
/// Matches \c ParenType nodes.
@@ -9427,9 +7300,8 @@ extern const AstTypeMatcher<FunctionProtoType> functionProtoType;
/// int *array_of_ptrs[4];
/// \endcode
///
-/// The matcher \matcher{varDecl(hasType(pointsTo(parenType())))}
-/// matches \match{int (*ptr_to_array)[4]}, but not
-/// \nomatch{int *array_of_ptrs[4]}.
+/// \c varDecl(hasType(pointsTo(parenType()))) matches \c ptr_to_array but not
+/// \c array_of_ptrs.
extern const AstTypeMatcher<ParenType> parenType;
/// Matches \c ParenType nodes where the inner type is a specific type.
@@ -9440,10 +7312,8 @@ extern const AstTypeMatcher<ParenType> parenType;
/// int (*ptr_to_func)(int);
/// \endcode
///
-/// The matcher
-/// \matcher{varDecl(hasType(pointsTo(parenType(innerType(functionType())))))}
-/// matches \match{int (*ptr_to_func)(int)} but not
-/// \nomatch{int (*ptr_to_array)[4]}.
+/// \c varDecl(hasType(pointsTo(parenType(innerType(functionType()))))) matches
+/// \c ptr_to_func but not \c ptr_to_array.
///
/// Usable as: Matcher<ParenType>
AST_TYPE_TRAVERSE_MATCHER(innerType, getInnerType,
@@ -9458,12 +7328,11 @@ extern const AstTypeMatcher<BlockPointerType> blockPointerType;
/// Matches member pointer types.
/// Given
/// \code
-/// struct A { int i; };
-/// int A::* ptr = &A::i;
+/// struct A { int i; }
+/// A::* ptr = A::i;
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{memberPointerType()}
-/// matches \match{type=typestr$int struct A::*}.
+/// memberPointerType()
+/// matches "A::* ptr"
extern const AstTypeMatcher<MemberPointerType> memberPointerType;
/// Matches pointer types, but does not match Objective-C object pointer
@@ -9471,24 +7340,16 @@ extern const AstTypeMatcher<MemberPointerType> memberPointerType;
///
/// Given
/// \code
-/// typedef int* int_ptr;
-/// void foo(char *str,
-/// int val,
-/// int *val_ptr,
-/// int_ptr not_a_ptr,
-/// int_ptr *ptr);
-/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{parmVarDecl(hasType(pointerType()))}
-/// matches \match{char *str}, \match{int *val_ptr} and
-/// \match{int_ptr *ptr}.
+/// int *a;
+/// int &b = *a;
+/// int c = 5;
///
-/// \code
/// @interface Foo
/// @end
/// Foo *f;
/// \endcode
-/// \compile_args{-ObjC}
+/// pointerType()
+/// matches "int *a", but does not match "Foo *f".
extern const AstTypeMatcher<PointerType> pointerType;
/// Matches an Objective-C object pointer type, which is different from
@@ -9502,10 +7363,8 @@ extern const AstTypeMatcher<PointerType> pointerType;
/// @end
/// Foo *f;
/// \endcode
-/// \compile_args{-ObjC}
-/// The matcher \matcher{pointerType()}
-/// matches \match{type=typestr$Foo *}, but does not match
-/// \nomatch{type=typestr$int *}.
+/// pointerType()
+/// matches "Foo *f", but does not match "int *a".
extern const AstTypeMatcher<ObjCObjectPointerType> objcObjectPointerType;
/// Matches both lvalue and rvalue reference types.
@@ -9520,18 +7379,13 @@ extern const AstTypeMatcher<ObjCObjectPointerType> objcObjectPointerType;
/// auto &&f = 2;
/// int g = 5;
/// \endcode
-/// \compile_args{-std=c++11-or-later}
///
-/// The matcher \matcher{referenceType()} matches the type
-/// \match{type=typestr$int &} of \c b , the type \match{type=typestr$int &&} of
-/// \c c, the type
-/// \match{type=typestr$auto &} \c d, and the type
-/// \match{type=typestr;count=2$auto &&} of \c e and \c f.
+/// \c referenceType() matches the types of \c b, \c c, \c d, \c e, and \c f.
extern const AstTypeMatcher<ReferenceType> referenceType;
/// Matches lvalue reference types.
///
-/// Given
+/// Given:
/// \code
/// int *a;
/// int &b = *a;
@@ -9541,17 +7395,14 @@ extern const AstTypeMatcher<ReferenceType> referenceType;
/// auto &&f = 2;
/// int g = 5;
/// \endcode
-/// \compile_args{-std=c++11-or-later}
///
-/// The matcher \matcher{lValueReferenceType()} matches the type
-/// \match{type=typestr$int &} of \c b and the type \match{type=typestr$auto &}
-/// of \c d.
-/// FIXME: figure out why auto changechange matches twice
+/// \c lValueReferenceType() matches the types of \c b, \c d, and \c e. \c e is
+/// matched since the type is deduced as int& by reference collapsing rules.
extern const AstTypeMatcher<LValueReferenceType> lValueReferenceType;
/// Matches rvalue reference types.
///
-/// Given
+/// Given:
/// \code
/// int *a;
/// int &b = *a;
@@ -9561,11 +7412,9 @@ extern const AstTypeMatcher<LValueReferenceType> lValueReferenceType;
/// auto &&f = 2;
/// int g = 5;
/// \endcode
-/// \compile_args{-std=c++11-or-later}
///
-/// The matcher \matcher{rValueReferenceType()} matches the type
-/// \match{type=typestr$int &&} of \c c and the type
-/// \match{type=typestr;count=2$auto &&} of \c e and \c f.
+/// \c rValueReferenceType() matches the types of \c c and \c f. \c e is not
+/// matched as it is deduced to int& by reference collapsing rules.
extern const AstTypeMatcher<RValueReferenceType> rValueReferenceType;
/// Narrows PointerType (and similar) matchers to those where the
@@ -9574,15 +7423,11 @@ extern const AstTypeMatcher<RValueReferenceType> rValueReferenceType;
/// Given
/// \code
/// int *a;
-/// const int *b;
-/// int * const c = nullptr;
-/// const float *f;
+/// int const *b;
+/// float const *f;
/// \endcode
-/// \compile_args{-std=c++11-or-later,c23-or-later}
-/// The matcher \matcher{pointerType(pointee(isConstQualified(), isInteger()))}
-/// matches \match{type=typestr$const int *},
-/// but does not match \nomatch{type=typestr$int * const}
-/// or \nomatch{type=typestr$const float *}.
+/// pointerType(pointee(isConstQualified(), isInteger()))
+/// matches "int const *b"
///
/// Usable as: Matcher<BlockPointerType>, Matcher<MemberPointerType>,
/// Matcher<PointerType>, Matcher<ReferenceType>
@@ -9596,10 +7441,9 @@ AST_TYPELOC_TRAVERSE_MATCHER_DECL(
/// Given
/// \code
/// typedef int X;
-/// X x = 0;
/// \endcode
-/// The matcher \matcher{typedefType()}
-/// matches \match{type=typestr$X}.
+/// typedefType()
+/// matches "typedef int X"
extern const AstTypeMatcher<TypedefType> typedefType;
/// Matches qualified types when the qualifier is applied via a macro.
@@ -9610,12 +7454,8 @@ extern const AstTypeMatcher<TypedefType> typedefType;
/// typedef void (CDECL *X)();
/// typedef void (__attribute__((cdecl)) *Y)();
/// \endcode
-/// The matcher \matcher{macroQualifiedType()}
-/// matches the type \match{type=typestr;std=c++,c23-or-later$CDECL void
-/// (void)} of the typedef declaration of \c X , unless when in C98-C17, there
-/// \match{type=typestr;std=c17-or-earlier$CDECL void ()},
-/// but it does not match the type
-/// \nomatch{type=typestr$__attribute((cdecl)) void ()} of \c Y .
+/// macroQualifiedType()
+/// matches the type of the typedef declaration of \c X but not \c Y.
extern const AstTypeMatcher<MacroQualifiedType> macroQualifiedType;
/// Matches enum types.
@@ -9628,11 +7468,9 @@ extern const AstTypeMatcher<MacroQualifiedType> macroQualifiedType;
/// C c;
/// S s;
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-///
-/// The matcher \matcher{enumType()} matches the type
-/// \match{type=typestr$enum C} of \c c ,
-/// and the type \match{type=typestr$enum S} of \c s .
+//
+/// \c enumType() matches the type of the variable declarations of both \c c and
+/// \c s.
extern const AstTypeMatcher<EnumType> enumType;
/// Matches template specialization types.
@@ -9642,16 +7480,12 @@ extern const AstTypeMatcher<EnumType> enumType;
/// template <typename T>
/// class C { };
///
-/// template class C<int>;
-/// C<int> intvar;
-/// C<char> charvar;
+/// template class C<int>; // A
+/// C<char> var; // B
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
///
-/// The matcher \matcher{templateSpecializationType()} matches the type
-/// \match{type=typestr$C<int>} of the explicit instantiation in \c A and the
-/// type \match{type=typestr$C<char>} of the variable declaration in
-/// \c B.
+/// \c templateSpecializationType() matches the type of the explicit
+/// instantiation in \c A and the type of the variable declaration in \c B.
extern const AstTypeMatcher<TemplateSpecializationType>
templateSpecializationType;
@@ -9665,23 +7499,19 @@ extern const AstTypeMatcher<TemplateSpecializationType>
///
/// C c(123);
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++17-or-later}
-/// The matcher \matcher{deducedTemplateSpecializationType()} matches the type
-/// \match{type=typestr$C} of the declaration of the variable \c c.
+/// \c deducedTemplateSpecializationType() matches the type in the declaration
+/// of the variable \c c.
extern const AstTypeMatcher<DeducedTemplateSpecializationType>
deducedTemplateSpecializationType;
/// Matches types nodes representing unary type transformations.
///
-/// Given
+/// Given:
/// \code
-/// template <typename T> struct A {
-/// typedef __underlying_type(T) type;
-/// };
+/// typedef __underlying_type(T) type;
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{unaryTransformType()}
-/// matches \match{type=typestr$__underlying_type(T)}
+/// unaryTransformType()
+/// matches "__underlying_type(T)"
extern const AstTypeMatcher<UnaryTransformType> unaryTransformType;
/// Matches record types (e.g. structs, classes).
@@ -9694,34 +7524,24 @@ extern const AstTypeMatcher<UnaryTransformType> unaryTransformType;
/// C c;
/// S s;
/// \endcode
-/// \compile_args{-std=c++11-or-later}
///
-/// The matcher \matcher{recordType()} matches the type
-/// \match{type=typestr;count=3$class C} of the variable declaration of \c c and
-/// matches the type \match{type=typestr;count=3$struct S} of the variable
-/// declaration of \c s.
-/// Both of these types are matched three times, once for the type of the
-/// variable, once for the definition of the class, and once for the type of the
-/// implicit class declaration.
+/// \c recordType() matches the type of the variable declarations of both \c c
+/// and \c s.
extern const AstTypeMatcher<RecordType> recordType;
/// Matches tag types (record and enum types).
///
/// Given
/// \code
-/// enum E { Ok };
+/// enum E {};
/// class C {};
///
/// E e;
/// C c;
/// \endcode
-/// \compile_args{-std=c++11-or-later}
///
-/// The matcher \matcher{tagType()} matches the type
-/// \match{type=typestr$enum E} of variable \c e and the type
-/// \match{type=typestr;count=3;std=c++$class C} three times, once for the type
-/// of the variable \c c , once for the type of the class definition and once of
-/// the type in the implicit class declaration.
+/// \c tagType() matches the type of the variable declarations of both \c e
+/// and \c c.
extern const AstTypeMatcher<TagType> tagType;
/// Matches types specified with an elaborated type keyword or with a
@@ -9736,22 +7556,16 @@ extern const AstTypeMatcher<TagType> tagType;
/// }
/// class C {};
///
-/// C c;
+/// class C c;
/// N::M::D d;
/// \endcode
-/// \compile_args{-std=c++11-or-later}
///
-/// The matcher \matcher{elaboratedType()} matches the type
-/// \match{type=typestr;count=3$C} three times. Once for the type of the
-/// variable \c c, once for the type of the class definition and once for the
-/// type in the implicit class declaration. For \c{class D}, it matches
-/// \match{type=typestr$N::M::D} of variable \c d and its class definition and
-/// implicit class declaration \match{type=typestr;count=2$D} one time
-/// respectively.
+/// \c elaboratedType() matches the type of the variable declarations of both
+/// \c c and \c d.
extern const AstTypeMatcher<ElaboratedType> elaboratedType;
/// Matches ElaboratedTypes whose qualifier, a NestedNameSpecifier,
-/// matches \c InnerMatcher if the qualifier exists.
+/// matches \c InnerMatcher if the qualifier exists.
///
/// Given
/// \code
@@ -9762,12 +7576,9 @@ extern const AstTypeMatcher<ElaboratedType> elaboratedType;
/// }
/// N::M::D d;
/// \endcode
-/// \compile_args{-std=c++}
///
-/// The matcher
-/// \matcher{elaboratedType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N")))))}
-/// matches the type \match{type=typestr$N::M::D} of the variable declaration
-/// of \c d.
+/// \c elaboratedType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N"))))
+/// matches the type of the variable declaration of \c d.
AST_MATCHER_P(ElaboratedType, hasQualifier,
internal::Matcher<NestedNameSpecifier>, InnerMatcher) {
if (const NestedNameSpecifier *Qualifier = Node.getQualifier())
@@ -9782,15 +7593,15 @@ AST_MATCHER_P(ElaboratedType, hasQualifier,
/// \code
/// namespace N {
/// namespace M {
-/// enum E { Ok };
+/// class D {};
/// }
/// }
-/// N::M::E e = N::M::Ok;
+/// N::M::D d;
/// \endcode
-/// \compile_args{-std=c++}
///
-/// The matcher \matcher{elaboratedType(namesType(enumType()))}
-/// matches the type \match{type=typestr$N::M::E} of the declaration of \c e .
+/// \c elaboratedType(namesType(recordType(
+/// hasDeclaration(namedDecl(hasName("D")))))) matches the type of the variable
+/// declaration of \c d.
AST_MATCHER_P(ElaboratedType, namesType, internal::Matcher<QualType>,
InnerMatcher) {
return InnerMatcher.matches(Node.getNamedType(), Finder, Builder);
@@ -9804,10 +7615,8 @@ AST_MATCHER_P(ElaboratedType, namesType, internal::Matcher<QualType>,
/// using a::S;
/// S s;
/// \endcode
-/// \compile_args{-std=c++11-or-later}
///
-/// The matcher \matcher{usingType()} matches the type \match{type=typestr$a::S}
-/// of the variable declaration of \c s.
+/// \c usingType() matches the type of the variable declaration of \c s.
extern const AstTypeMatcher<UsingType> usingType;
/// Matches types that represent the result of substituting a type for a
@@ -9817,18 +7626,11 @@ extern const AstTypeMatcher<UsingType> usingType;
/// \code
/// template <typename T>
/// void F(T t) {
-/// T local;
/// int i = 1 + t;
/// }
-/// void f() {
-/// F(0);
-/// }
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
///
-/// The matcher \matcher{varDecl(hasType(substTemplateTypeParmType()))}
-/// matches \match{T t} and \match{T local} for the substituted template type
-/// \c int in the instantiation of \c F .
+/// \c substTemplateTypeParmType() matches the type of 't' but not '1'
extern const AstTypeMatcher<SubstTemplateTypeParmType>
substTemplateTypeParmType;
@@ -9842,67 +7644,46 @@ extern const AstTypeMatcher<SubstTemplateTypeParmType>
/// int i;
/// double j = F(i);
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
///
-/// The matcher \matcher{substTemplateTypeParmType(hasReplacementType(type()))}
-/// matches \match{type=typestr$int}.
+/// \c substTemplateTypeParmType(hasReplacementType(type())) matches int
AST_TYPE_TRAVERSE_MATCHER(
hasReplacementType, getReplacementType,
AST_POLYMORPHIC_SUPPORTED_TYPES(SubstTemplateTypeParmType));
/// Matches template type parameter types.
///
-/// Given
+/// Example matches T, but not int.
+/// (matcher = templateTypeParmType())
/// \code
/// template <typename T> void f(int i);
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher \matcher{templateTypeParmType()} matches \match{type=typestr$T},
-/// but does not match \nomatch{type=typestr$int}.
extern const AstTypeMatcher<TemplateTypeParmType> templateTypeParmType;
/// Matches injected class name types.
///
-/// Given
+/// Example matches S s, but not S<T> s.
+/// (matcher = parmVarDecl(hasType(injectedClassNameType())))
/// \code
/// template <typename T> struct S {
/// void f(S s);
/// void g(S<T> s);
/// };
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++}
-/// The matcher
-/// \matcher{parmVarDecl(hasType(elaboratedType(namesType(injectedClassNameType()))))}
-/// matches \match{S s}, but not \notmatch{S<T> s}
extern const AstTypeMatcher<InjectedClassNameType> injectedClassNameType;
/// Matches decayed type
+/// Example matches i[] in declaration of f.
+/// (matcher = valueDecl(hasType(decayedType(hasDecayedType(pointerType())))))
+/// Example matches i[1].
+/// (matcher = expr(hasType(decayedType(hasDecayedType(pointerType())))))
/// \code
/// void f(int i[]) {
/// i[1] = 0;
/// }
/// \endcode
-/// The matcher
-/// \matcher{valueDecl(hasType(decayedType(hasDecayedType(pointerType()))))}
-/// matches \match{int i[]} in declaration of \c{f}.
-/// The matcher
-/// \matcher{expr(hasType(decayedType(hasDecayedType(pointerType()))))}
-/// matches \match{count=2$i} twice, once for the \c DeclRefExpr and oncde for
-/// the cast from an l- to an r-value in \c{i[1]}.
-///
extern const AstTypeMatcher<DecayedType> decayedType;
/// Matches the decayed type, whoes decayed type matches \c InnerMatcher
-///
-/// Given
-/// \code
-/// void f(int i[]) {
-/// i[1] = 0;
-/// }
-/// \endcode
-///
-/// The matcher \matcher{parmVarDecl(hasType(decayedType()))}
-/// matches \match{int i[]}.
AST_MATCHER_P(DecayedType, hasDecayedType, internal::Matcher<QualType>,
InnerType) {
return InnerType.matches(Node.getDecayedType(), Finder, Builder);
@@ -9919,10 +7700,9 @@ AST_MATCHER_P(DecayedType, hasDecayedType, internal::Matcher<QualType>,
/// }
/// }
/// \endcode
-/// \compile_args{-std=c++}
///
-/// The matcher \matcher{cxxRecordDecl(hasDeclContext(namedDecl(hasName("M"))))}
-/// matches the definition of \match{class D {}}.
+/// \c cxxRcordDecl(hasDeclContext(namedDecl(hasName("M")))) matches the
+/// declaration of \c class \c D.
AST_MATCHER_P(Decl, hasDeclContext, internal::Matcher<Decl>, InnerMatcher) {
const DeclContext *DC = Node.getDeclContext();
if (!DC) return false;
@@ -9940,49 +7720,17 @@ AST_MATCHER_P(Decl, hasDeclContext, internal::Matcher<Decl>, InnerMatcher) {
/// }
/// ns::A a;
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{nestedNameSpecifier()}
-/// matches \match{type=name$ns} and both spellings of
-/// \match{type=name;count=2$A} in \c A::f() and \c ns::A .
+/// nestedNameSpecifier()
+/// matches "ns::" and both "A::"
extern const internal::VariadicAllOfMatcher<NestedNameSpecifier>
nestedNameSpecifier;
/// Same as \c nestedNameSpecifier but matches \c NestedNameSpecifierLoc.
-///
-/// Given
-/// \code
-/// namespace ns {
-/// struct A { static void f(); };
-/// void A::f() {}
-/// void g() { A::f(); }
-/// }
-/// ns::A a;
-/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{nestedNameSpecifierLoc()} matches
-/// \match{count=2$A::} twice for the spellings in \c A::f() and \c ns::A ,
-/// and \match{ns::} once.
extern const internal::VariadicAllOfMatcher<NestedNameSpecifierLoc>
nestedNameSpecifierLoc;
/// Matches \c NestedNameSpecifierLocs for which the given inner
/// NestedNameSpecifier-matcher matches.
-///
-/// Given
-/// \code
-/// namespace ns {
-/// struct A { static void f(); };
-/// void A::f() {}
-/// void g() { A::f(); }
-/// }
-/// ns::A a;
-/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{nestedNameSpecifierLoc(loc(specifiesType(
-/// hasDeclaration(namedDecl(hasName("A"))))))} matches \match{count=2$A::}
-/// twice for the spellings in \c A::f() and \c ns::A .
AST_MATCHER_FUNCTION_P_OVERLOAD(
internal::BindableMatcher<NestedNameSpecifierLoc>, loc,
internal::Matcher<NestedNameSpecifier>, InnerMatcher, 1) {
@@ -9999,11 +7747,10 @@ AST_MATCHER_FUNCTION_P_OVERLOAD(
/// struct A { struct B { struct C {}; }; };
/// A::B::C c;
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{nestedNameSpecifier(specifiesType(
+/// nestedNameSpecifier(specifiesType(
/// hasDeclaration(cxxRecordDecl(hasName("A")))
-/// ))}
-/// matches the spelling of \match{type=name$A} in \c A::B::C .
+/// ))
+/// matches "A::"
AST_MATCHER_P(NestedNameSpecifier, specifiesType,
internal::Matcher<QualType>, InnerMatcher) {
if (!Node.getAsType())
@@ -10019,10 +7766,9 @@ AST_MATCHER_P(NestedNameSpecifier, specifiesType,
/// struct A { struct B { struct C {}; }; };
/// A::B::C c;
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{nestedNameSpecifierLoc(specifiesTypeLoc(loc(qualType(
-/// hasDeclaration(cxxRecordDecl(hasName("A")))))))}
-/// matches \match{A::}
+/// nestedNameSpecifierLoc(specifiesTypeLoc(loc(type(
+/// hasDeclaration(cxxRecordDecl(hasName("A")))))))
+/// matches "A::"
AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc,
internal::Matcher<TypeLoc>, InnerMatcher) {
return Node && Node.getNestedNameSpecifier()->getAsType() &&
@@ -10036,10 +7782,8 @@ AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc,
/// struct A { struct B { struct C {}; }; };
/// A::B::C c;
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{nestedNameSpecifier(hasPrefix(specifiesType(asString(
-/// "struct A"))))} matches \match{type=typestr$struct A::B}
+/// nestedNameSpecifier(hasPrefix(specifiesType(asString("struct A")))) and
+/// matches "A::"
AST_MATCHER_P_OVERLOAD(NestedNameSpecifier, hasPrefix,
internal::Matcher<NestedNameSpecifier>, InnerMatcher,
0) {
@@ -10056,10 +7800,8 @@ AST_MATCHER_P_OVERLOAD(NestedNameSpecifier, hasPrefix,
/// struct A { struct B { struct C {}; }; };
/// A::B::C c;
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{nestedNameSpecifierLoc(hasPrefix(loc(specifiesType(asString(
-/// "struct A")))))} matches \match{A::B::}.
+/// nestedNameSpecifierLoc(hasPrefix(loc(specifiesType(asString("struct A")))))
+/// matches "A::"
AST_MATCHER_P_OVERLOAD(NestedNameSpecifierLoc, hasPrefix,
internal::Matcher<NestedNameSpecifierLoc>, InnerMatcher,
1) {
@@ -10077,10 +7819,8 @@ AST_MATCHER_P_OVERLOAD(NestedNameSpecifierLoc, hasPrefix,
/// namespace ns { struct A {}; }
/// ns::A a;
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher
-/// \matcher{nestedNameSpecifier(specifiesNamespace(hasName("ns")))} matches
-/// the spelling of \match{type=name$ns} in \c ns::A .
+/// nestedNameSpecifier(specifiesNamespace(hasName("ns")))
+/// matches "ns::"
AST_MATCHER_P(NestedNameSpecifier, specifiesNamespace,
internal::Matcher<NamespaceDecl>, InnerMatcher) {
if (!Node.getAsNamespace())
@@ -10102,10 +7842,8 @@ AST_MATCHER_P(NestedNameSpecifier, specifiesNamespace,
/// #pragma omp declare simd
/// int min();
/// \endcode
-/// \compile_args{-fdeclspec;-fopenmp}
-/// The matcher \matcher{attr()}
-/// matches \match{nodiscard}, \match{nonnull}, \match{noinline}, and
-/// \match{declare simd}.
+/// attr()
+/// matches "nodiscard", "nonnull", "noinline", and the whole "#pragma" line.
extern const internal::VariadicAllOfMatcher<Attr> attr;
/// Overloads for the \c equalsNode matcher.
@@ -10138,19 +7876,12 @@ AST_MATCHER_P_OVERLOAD(Type, equalsNode, const Type*, Other, 2) {
///
/// Given
/// \code
-/// void foo() {
-/// switch (1) { case 1: case 2: default: switch (2) { case 3: case 4: ; } }
-/// }
+/// switch (1) { case 1: case 2: default: switch (2) { case 3: case 4: ; } }
/// \endcode
-/// The matcher
-/// \matcher{switchStmt(forEachSwitchCase(caseStmt().bind("c")))}
-/// matches four times, matching
-/// \match{count=2$switch (1) { case 1: case 2: default: switch (2) { case 3:
-/// case 4: ; } }} twice and
-/// \match{count=2$switch (2) { case 3: case 4: ; }} twice, with
-/// \matcher{type=sub$caseStmt()} matching each of \match{sub=c$case 1:},
-/// \match{sub=c$case 2:}, \match{sub=c$case 3:}
-/// and \match{sub=c$case 4:}.
+/// switchStmt(forEachSwitchCase(caseStmt().bind("c"))).bind("s")
+/// matches four times, with "c" binding each of "case 1:", "case 2:",
+/// "case 3:" and "case 4:", and "s" respectively binding "switch (1)",
+/// "switch (1)", "switch (2)" and "switch (2)".
AST_MATCHER_P(SwitchStmt, forEachSwitchCase, internal::Matcher<SwitchCase>,
InnerMatcher) {
BoundNodesTreeBuilder Result;
@@ -10178,12 +7909,10 @@ AST_MATCHER_P(SwitchStmt, forEachSwitchCase, internal::Matcher<SwitchCase>,
/// \code
/// class A { A() : i(42), j(42) {} int i; int j; };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxConstructorDecl(forEachConstructorInitializer(
-/// forField(fieldDecl().bind("x"))))}
-/// matches the constructor of \match{count=2$A() : i(42), j(42) {}} twice, with
-/// \matcher{type=sub$fieldDecl()} matching \match{sub=field$i} and
-/// \match{sub=field$j} respectively.
+/// cxxConstructorDecl(forEachConstructorInitializer(
+/// forField(decl().bind("x"))
+/// ))
+/// will trigger two matches, binding for 'i' and 'j' respectively.
AST_MATCHER_P(CXXConstructorDecl, forEachConstructorInitializer,
internal::Matcher<CXXCtorInitializer>, InnerMatcher) {
BoundNodesTreeBuilder Result;
@@ -10211,10 +7940,7 @@ AST_MATCHER_P(CXXConstructorDecl, forEachConstructorInitializer,
/// S(S &&); // #3
/// };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxConstructorDecl(isCopyConstructor())}
-/// matches \match{S(const S &)},
-/// but does not match \nomatch{S()} or \nomatch{S(S &&)}.
+/// cxxConstructorDecl(isCopyConstructor()) will match #2, but not #1 or #3.
AST_MATCHER(CXXConstructorDecl, isCopyConstructor) {
return Node.isCopyConstructor();
}
@@ -10229,10 +7955,7 @@ AST_MATCHER(CXXConstructorDecl, isCopyConstructor) {
/// S(S &&); // #3
/// };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxConstructorDecl(isMoveConstructor())}
-/// matches \match{S(S &&)}
-/// but does not match \nomatch{S();} or \nomatch{S(S &&);}
+/// cxxConstructorDecl(isMoveConstructor()) will match #3, but not #1 or #2.
AST_MATCHER(CXXConstructorDecl, isMoveConstructor) {
return Node.isMoveConstructor();
}
@@ -10247,10 +7970,7 @@ AST_MATCHER(CXXConstructorDecl, isMoveConstructor) {
/// S(S &&); // #3
/// };
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxConstructorDecl(isDefaultConstructor())}
-/// matches \match{S()}
-/// but does not match \nomatch{S(const S &);} or \nomatch{S(S &&);}.
+/// cxxConstructorDecl(isDefaultConstructor()) will match #1, but not #2 or #3.
AST_MATCHER(CXXConstructorDecl, isDefaultConstructor) {
return Node.isDefaultConstructor();
}
@@ -10266,10 +7986,8 @@ AST_MATCHER(CXXConstructorDecl, isDefaultConstructor) {
/// };
/// S::S() : S(0) {} // #4
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{cxxConstructorDecl(isDelegatingConstructor())}
-/// matches \match{S(S &&) : S() {}} and \match{S::S() : S(0) {}},
-/// but does not match \nomatch{S()} or \nomatch{S(int)}.
+/// cxxConstructorDecl(isDelegatingConstructor()) will match #3 and #4, but not
+/// #1 or #2.
AST_MATCHER(CXXConstructorDecl, isDelegatingConstructor) {
return Node.isDelegatingConstructor();
}
@@ -10286,28 +8004,16 @@ AST_MATCHER(CXXConstructorDecl, isDelegatingConstructor) {
/// explicit S(double); // #2
/// operator int(); // #3
/// explicit operator bool(); // #4
-/// explicit(false) S(bool); // # 7
-/// explicit(true) S(char); // # 8
-/// explicit(b) S(float); // # 9
+/// explicit(false) S(bool) // # 7
+/// explicit(true) S(char) // # 8
+/// explicit(b) S(S) // # 9
/// };
-/// S(int) -> S<true>; // #5
-/// explicit S(double) -> S<false>; // #6
-/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++20-or-later}
-/// The matcher \matcher{cxxConstructorDecl(isExplicit())}
-/// matches \match{explicit S(double)}
-/// and \match{explicit(true) S(char)}
-/// but does not match \nomatch{S(int);}, \nomatch{explicit(false) S(bool);} or
-/// \nomatch{explicit(b) S(float)}
-/// The matcher \matcher{cxxConversionDecl(isExplicit())}
-/// matches \match{explicit operator bool()}
-/// but does not match \nomatch{operator int()}.
-/// The matcher \matcher{cxxDeductionGuideDecl(isExplicit())}
-/// matches the deduction guide \match{explicit S(double) -> S<false>},
-/// the implicit copy deduction candiate
-/// \match{type=typestr$auto (double) -> S<b>} and
-/// the implicitly generated deduction guide for \match{explicit(true) S(char)},
-/// but does not match \nomatch{S(int) -> S<true>}.
+/// S(int) -> S<true> // #5
+/// explicit S(double) -> S<false> // #6
+/// \endcode
+/// cxxConstructorDecl(isExplicit()) will match #2 and #8, but not #1, #7 or #9.
+/// cxxConversionDecl(isExplicit()) will match #4, but not #3.
+/// cxxDeductionGuideDecl(isExplicit()) will match #6, but not #5.
AST_POLYMORPHIC_MATCHER(isExplicit, AST_POLYMORPHIC_SUPPORTED_TYPES(
CXXConstructorDecl, CXXConversionDecl,
CXXDeductionGuideDecl)) {
@@ -10325,28 +8031,16 @@ AST_POLYMORPHIC_MATCHER(isExplicit, AST_POLYMORPHIC_SUPPORTED_TYPES(
/// explicit S(double); // #2
/// operator int(); // #3
/// explicit operator bool(); // #4
-/// explicit(false) S(bool); // # 7
-/// explicit(true) S(char); // # 8
-/// explicit(b) S(float); // # 9
+/// explicit(false) S(bool) // # 7
+/// explicit(true) S(char) // # 8
+/// explicit(b) S(S) // # 9
/// };
-/// S(int) -> S<true>; // #5
-/// explicit S(double) -> S<false>; // #6
+/// S(int) -> S<true> // #5
+/// explicit S(double) -> S<false> // #6
/// \endcode
-/// \compile_args{-fno-delayed-template-parsing;-std=c++20-or-later}
-/// The matcher
-/// \matcher{cxxConstructorDecl(hasExplicitSpecifier(constantExpr()))} matches
-/// \match{explicit(false) S(bool)} and \match{explicit(true) S(char)},
-/// but does not match \nomatch{explicit(b) S(float)}, \nomatch{S(int)} or
-/// \nomatch{explicit S(double)}.
-/// The matcher
-/// \matcher{cxxConversionDecl(hasExplicitSpecifier(constantExpr()))} does not
-/// match \nomatch{operator int()} or \nomatch{explicit operator bool()}.
-/// Matcher
-/// The matcher
-/// \matcher{cxxDeductionGuideDecl(hasExplicitSpecifier(declRefExpr()))}
-/// matches the implicitly generated deduction guide
-/// \match{type=typestr$auto (float) -> S<b>} of the constructor
-/// \c{explicit(b) S(float)}.
+/// cxxConstructorDecl(hasExplicitSpecifier(constantExpr())) will match #7, #8 and #9, but not #1 or #2.
+/// cxxConversionDecl(hasExplicitSpecifier(constantExpr())) will not match #3 or #4.
+/// cxxDeductionGuideDecl(hasExplicitSpecifier(constantExpr())) will not match #5 or #6.
AST_MATCHER_P(FunctionDecl, hasExplicitSpecifier, internal::Matcher<Expr>,
InnerMatcher) {
ExplicitSpecifier ES = ExplicitSpecifier::getFromDecl(&Node);
@@ -10370,13 +8064,9 @@ AST_MATCHER_P(FunctionDecl, hasExplicitSpecifier, internal::Matcher<Expr>,
/// }
/// inline int Foo = 5;
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{functionDecl(isInline())} matches
-/// \match{inline void f()}.
-/// The matcher \matcher{namespaceDecl(isInline())} matches
-/// \match{inline namespace m {}}.
-/// The matcher \matcher{varDecl(isInline())} matches
-/// \match{inline int Foo = 5}.
+/// functionDecl(isInline()) will match ::f().
+/// namespaceDecl(isInline()) will match n::m.
+/// varDecl(isInline()) will match Foo;
AST_POLYMORPHIC_MATCHER(isInline, AST_POLYMORPHIC_SUPPORTED_TYPES(NamespaceDecl,
FunctionDecl,
VarDecl)) {
@@ -10399,9 +8089,7 @@ AST_POLYMORPHIC_MATCHER(isInline, AST_POLYMORPHIC_SUPPORTED_TYPES(NamespaceDecl,
/// namespace {} // #1
/// }
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{namespaceDecl(isAnonymous())}
-/// matches \match{namespace {}}, but not \nomatch{namespace n}.
+/// namespaceDecl(isAnonymous()) will match #1 but not ::n.
AST_MATCHER(NamespaceDecl, isAnonymous) {
return Node.isAnonymousNamespace();
}
@@ -10426,9 +8114,7 @@ AST_MATCHER(NamespaceDecl, isAnonymous) {
/// }
/// }
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxRecordDecl(hasName("vector"), isInStdNamespace())}
-/// matches \match{class vector {}} inside of namespace std.
+/// cxxRecordDecl(hasName("vector"), isInStdNamespace()) will match only #1.
AST_MATCHER(Decl, isInStdNamespace) { return Node.isInStdNamespace(); }
/// Matches declarations in an anonymous namespace.
@@ -10445,16 +8131,12 @@ AST_MATCHER(Decl, isInStdNamespace) { return Node.isInStdNamespace(); }
/// namespace {
/// class vector {}; // #2
/// namespace foo {
-/// class vector {}; // #3
+/// class vector{}; // #3
/// }
/// }
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxRecordDecl(hasName("vector"),
-/// isInAnonymousNamespace())}
-/// matches \match{type=name;count=6$vector},
-/// two times for the definition and the implicit class declaration
-/// for each of the three definitions of \c vector .
+/// cxxRecordDecl(hasName("vector"), isInAnonymousNamespace()) will match
+/// #1, #2 and #3.
AST_MATCHER(Decl, isInAnonymousNamespace) {
return Node.isInAnonymousNamespace();
}
@@ -10464,13 +8146,10 @@ AST_MATCHER(Decl, isInAnonymousNamespace) {
///
/// Given
/// \code
-/// void foo() {
-/// switch (1) { case 1: break; case 1+1: break; case 3 ... 4: break; }
-/// }
+/// switch (1) { case 1: case 1+1: case 3 ... 4: ; }
/// \endcode
-/// The matcher
-/// \matcher{caseStmt(hasCaseConstant(constantExpr(has(integerLiteral()))))}
-/// matches \match{case 1: break}.
+/// caseStmt(hasCaseConstant(integerLiteral()))
+/// matches "case 1:"
AST_MATCHER_P(CaseStmt, hasCaseConstant, internal::Matcher<Expr>,
InnerMatcher) {
if (Node.getRHS())
@@ -10483,14 +8162,11 @@ AST_MATCHER_P(CaseStmt, hasCaseConstant, internal::Matcher<Expr>,
///
/// Given
/// \code
-/// __attribute__((device)) void f() {}
+/// __attribute__((device)) void f() { ... }
/// \endcode
-/// \compile_args{--cuda-gpu-arch=sm_70;-std=c++}
-/// The matcher \matcher{decl(hasAttr(clang::attr::CUDADevice))}
-/// matches \match{__attribute__((device)) void f() {}}.
-/// If the matcher is used from clang-query, attr::Kind
-/// parameter should be passed as a quoted string. e.g.,
-/// \c hasAttr("attr::CUDADevice").
+/// decl(hasAttr(clang::attr::CUDADevice)) matches the function declaration of
+/// f. If the matcher is used from clang-query, attr::Kind parameter should be
+/// passed as a quoted string. e.g., hasAttr("attr::CUDADevice").
AST_MATCHER_P(Decl, hasAttr, attr::Kind, AttrKind) {
for (const auto *Attr : Node.attrs()) {
if (Attr->getKind() == AttrKind)
@@ -10503,14 +8179,12 @@ AST_MATCHER_P(Decl, hasAttr, attr::Kind, AttrKind) {
///
/// Given
/// \code
-/// int foo(int a, int b) {
-/// return a + b;
-/// }
+/// return a + b;
/// \endcode
-/// The matcher
-/// \matcher{returnStmt(hasReturnValue(binaryOperator().bind("op")))} matches
-/// \match{return a + b}, with \matcher{type=sub$binaryOperator()} matching
-/// \match{sub=op$a + b}.
+/// hasReturnValue(binaryOperator())
+/// matches 'return a + b'
+/// with binaryOperator()
+/// matching 'a + b'
AST_MATCHER_P(ReturnStmt, hasReturnValue, internal::Matcher<Expr>,
InnerMatcher) {
if (const auto *RetValue = Node.getRetValue())
@@ -10520,25 +8194,18 @@ AST_MATCHER_P(ReturnStmt, hasReturnValue, internal::Matcher<Expr>,
/// Matches CUDA kernel call expression.
///
-/// Given
+/// Example matches,
/// \code
-/// __global__ void kernel() {}
-/// void f() {
-/// kernel<<<32, 32>>>();
-/// }
+/// kernel<<<i,j>>>();
/// \endcode
-/// \compile_args{--cuda-gpu-arch=sm_70;-std=c++}
-/// The matcher \matcher{cudaKernelCallExpr()}
-/// matches \match{kernel<<<32, 32>>>()}
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CUDAKernelCallExpr>
cudaKernelCallExpr;
/// Matches expressions that resolve to a null pointer constant, such as
/// GNU's __null, C++11's nullptr, or C's NULL macro.
///
-/// Given
+/// Given:
/// \code
-/// #define NULL 0
/// void *v1 = NULL;
/// void *v2 = nullptr;
/// void *v3 = __null; // GNU extension
@@ -10546,14 +8213,9 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CUDAKernelCallExpr>
/// int *ip = 0;
/// int i = 0;
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{expr(nullPointerConstant())}
-/// matches the initializer \match{NULL} of v1,
-/// matches the initializer \match{nullptr} of v2,
-/// matches the initializer \match{__null} of v3,
-/// matches the initializer \match{0} of cp and
-/// matches the initializer \match{0} of ip,
-/// but does not match the initializer \nomatch{i} of i.
+/// expr(nullPointerConstant())
+/// matches the initializer for v1, v2, v3, cp, and ip. Does not match the
+/// initializer for i.
AST_MATCHER_FUNCTION(internal::Matcher<Expr>, nullPointerConstant) {
return anyOf(
gnuNullExpr(), cxxNullPtrLiteralExpr(),
@@ -10562,7 +8224,7 @@ AST_MATCHER_FUNCTION(internal::Matcher<Expr>, nullPointerConstant) {
/// Matches the DecompositionDecl the binding belongs to.
///
-/// Given
+/// For example, in:
/// \code
/// void foo()
/// {
@@ -10572,10 +8234,12 @@ AST_MATCHER_FUNCTION(internal::Matcher<Expr>, nullPointerConstant) {
/// f = 42;
/// }
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{bindingDecl(hasName("f"),
-/// forDecomposition(decompositionDecl()))}
-/// matches \match{type=name$f} in \c{auto &[f, s, t]}.
+/// The matcher:
+/// \code
+/// bindingDecl(hasName("f"),
+/// forDecomposition(decompositionDecl())
+/// \endcode
+/// matches 'f' in 'auto &[f, s, t]'.
AST_MATCHER_P(BindingDecl, forDecomposition, internal::Matcher<ValueDecl>,
InnerMatcher) {
if (const ValueDecl *VD = Node.getDecomposedDecl())
@@ -10585,7 +8249,7 @@ AST_MATCHER_P(BindingDecl, forDecomposition, internal::Matcher<ValueDecl>,
/// Matches the Nth binding of a DecompositionDecl.
///
-/// Given
+/// For example, in:
/// \code
/// void foo()
/// {
@@ -10595,10 +8259,12 @@ AST_MATCHER_P(BindingDecl, forDecomposition, internal::Matcher<ValueDecl>,
/// f = 42;
/// }
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{decompositionDecl(hasBinding(0,
-/// bindingDecl(hasName("f")).bind("fBinding")))}
-/// matches \match{auto &[f, s, t] = arr} with 'f' bound to "fBinding".
+/// The matcher:
+/// \code
+/// decompositionDecl(hasBinding(0,
+/// bindingDecl(hasName("f").bind("fBinding"))))
+/// \endcode
+/// matches the decomposition decl with 'f' bound to "fBinding".
AST_MATCHER_P2(DecompositionDecl, hasBinding, unsigned, N,
internal::Matcher<BindingDecl>, InnerMatcher) {
if (Node.bindings().size() <= N)
@@ -10618,10 +8284,11 @@ AST_MATCHER_P2(DecompositionDecl, hasBinding, unsigned, N,
/// f = 42;
/// }
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher
-/// \matcher{decompositionDecl(hasAnyBinding(bindingDecl(hasName("f")).bind("fBinding")))}
-/// matches \match{auto &[f, s, t] = arr} with 'f' bound to "fBinding".
+/// The matcher:
+/// \code
+/// decompositionDecl(hasAnyBinding(bindingDecl(hasName("f").bind("fBinding"))))
+/// \endcode
+/// matches the decomposition decl with 'f' bound to "fBinding".
AST_MATCHER_P(DecompositionDecl, hasAnyBinding, internal::Matcher<BindingDecl>,
InnerMatcher) {
return llvm::any_of(Node.bindings(), [&](const auto *Binding) {
@@ -10633,23 +8300,19 @@ AST_MATCHER_P(DecompositionDecl, hasAnyBinding, internal::Matcher<BindingDecl>,
///
/// Deprecated. Use forCallable() to correctly handle the situation when
/// the declaration is not a function (but a block or an Objective-C method).
-/// The matcher \c forFunction() not only fails to take non-functions
-/// into account but also may match the wrong declaration in their presence.
+/// forFunction() not only fails to take non-functions into account but also
+/// may match the wrong declaration in their presence.
///
-/// Given
+/// Given:
/// \code
-/// struct F {
-/// F& operator=(const F& other) {
-/// []() { return 42 == 42; };
-/// return *this;
-/// }
-/// };
+/// F& operator=(const F& o) {
+/// std::copy_if(o.begin(), o.end(), begin(), [](V v) { return v > 0; });
+/// return *this;
+/// }
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-///
-/// The matcher \matcher{returnStmt(forFunction(hasName("operator=")))}
-/// matches \match{return *this}
-/// but does not match \nomatch{return 42 == 42}.
+/// returnStmt(forFunction(hasName("operator=")))
+/// matches 'return *this'
+/// but does not match 'return v > 0'
AST_MATCHER_P(Stmt, forFunction, internal::Matcher<FunctionDecl>,
InnerMatcher) {
const auto &Parents = Finder->getASTContext().getParents(Node);
@@ -10677,34 +8340,30 @@ AST_MATCHER_P(Stmt, forFunction, internal::Matcher<FunctionDecl>,
/// Matches declaration of the function, method, or block the statement
/// belongs to.
///
-/// Given
+/// Given:
/// \code
-/// struct F {
-/// F& operator=(const F& other) {
-/// []() { return 42 == 42; };
-/// return *this;
-/// }
-/// };
+/// F& operator=(const F& o) {
+/// std::copy_if(o.begin(), o.end(), begin(), [](V v) { return v > 0; });
+/// return *this;
+/// }
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{returnStmt(forFunction(hasName("operator=")))}
-/// matches \match{return *this}
-/// but does not match \nomatch{return 42 == 42}.
+/// returnStmt(forCallable(functionDecl(hasName("operator="))))
+/// matches 'return *this'
+/// but does not match 'return v > 0'
///
-/// Given
+/// Given:
/// \code
-/// void foo {
+/// -(void) foo {
/// int x = 1;
/// dispatch_sync(queue, ^{ int y = 2; });
/// }
/// \endcode
-/// \compile_args{-ObjC}
-/// The matcher \matcher{declStmt(forCallable(objcMethodDecl()))}
-/// matches \match{int x = 1}
-/// but does not match \nomatch{int y = 2}.
-/// The matcher \matcher{declStmt(forCallable(blockDecl()))}
-/// matches \match{int y = 2}
-/// but does not match \nomatch{int x = 1}.
+/// declStmt(forCallable(objcMethodDecl()))
+/// matches 'int x = 1'
+/// but does not match 'int y = 2'.
+/// whereas declStmt(forCallable(blockDecl()))
+/// matches 'int y = 2'
+/// but does not match 'int x = 1'.
AST_MATCHER_P(Stmt, forCallable, internal::Matcher<Decl>, InnerMatcher) {
const auto &Parents = Finder->getASTContext().getParents(Node);
@@ -10746,93 +8405,73 @@ AST_MATCHER_P(Stmt, forCallable, internal::Matcher<Decl>, InnerMatcher) {
/// Matches a declaration that has external formal linkage.
///
-/// Given
+/// Example matches only z (matcher = varDecl(hasExternalFormalLinkage()))
/// \code
/// void f() {
-/// int a;
-/// static int b;
+/// int x;
+/// static int y;
/// }
-/// int c;
-/// static int d;
+/// int z;
/// \endcode
-/// The matcher \matcher{varDecl(hasExternalFormalLinkage())}
-/// matches \match{int c},
-/// but not \nomatch{int a}, \nomatch{static int b} or \nomatch{int d}.
///
-/// Given
+/// Example matches f() because it has external formal linkage despite being
+/// unique to the translation unit as though it has internal likage
+/// (matcher = functionDecl(hasExternalFormalLinkage()))
+///
/// \code
-/// namespace {
-/// void f() {}
-/// }
-/// void g() {}
-/// static void h() {}
+/// namespace {
+/// void f() {}
+/// }
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{functionDecl(hasExternalFormalLinkage())}
-/// matches \match{void g() {}}, but not \nomatch{void f() {}} or
-/// \nomatch{static void h() {}}.
AST_MATCHER(NamedDecl, hasExternalFormalLinkage) {
return Node.hasExternalFormalLinkage();
}
/// Matches a declaration that has default arguments.
///
-/// Given
+/// Example matches y (matcher = parmVarDecl(hasDefaultArgument()))
/// \code
-/// void x(int val) {}
-/// void y(int val = 0) {}
+/// void x(int val) {}
+/// void y(int val = 0) {}
/// \endcode
-/// \compile_args{-std=c++}
-///
-/// The matcher \matcher{parmVarDecl(hasDefaultArgument())}
-/// matches \match{int val = 0}.
///
/// Deprecated. Use hasInitializer() instead to be able to
/// match on the contents of the default argument. For example:
///
-/// Given
/// \code
-/// void x(int val = 7) {}
-/// void y(int val = 42) {}
+/// void x(int val = 7) {}
+/// void y(int val = 42) {}
/// \endcode
-/// \compile_args{-std=c++}
+/// parmVarDecl(hasInitializer(integerLiteral(equals(42))))
+/// matches the parameter of y
///
-/// The matcher
-/// \matcher{parmVarDecl(hasInitializer(integerLiteral(equals(42))))},
-/// matches \match{int val = 42}.
+/// A matcher such as
+/// parmVarDecl(hasInitializer(anything()))
+/// is equivalent to parmVarDecl(hasDefaultArgument()).
AST_MATCHER(ParmVarDecl, hasDefaultArgument) {
return Node.hasDefaultArg();
}
/// Matches array new expressions.
///
-/// Given
+/// Given:
/// \code
-/// struct MyClass { int x; };
/// MyClass *p1 = new MyClass[10];
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxNewExpr(isArray())}
-/// matches \match{new MyClass[10]}.
+/// cxxNewExpr(isArray())
+/// matches the expression 'new MyClass[10]'.
AST_MATCHER(CXXNewExpr, isArray) {
return Node.isArray();
}
/// Matches placement new expression arguments.
///
-/// Given
+/// Given:
/// \code
-/// void *operator new(decltype(sizeof(void*)), int, void*);
-/// struct MyClass { int x; };
-/// unsigned char Storage[sizeof(MyClass) * 10];
-/// MyClass *p1 = new (16, Storage) MyClass();
+/// MyClass *p1 = new (Storage, 16) MyClass();
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-///
-/// The matcher \matcher{cxxNewExpr(hasPlacementArg(0,
-/// integerLiteral(equals(16))))}
-/// matches \match{new (16, Storage) MyClass()}.
+/// cxxNewExpr(hasPlacementArg(1, integerLiteral(equals(16))))
+/// matches the expression 'new (Storage, 16) MyClass()'.
AST_MATCHER_P2(CXXNewExpr, hasPlacementArg, unsigned, Index,
internal::Matcher<Expr>, InnerMatcher) {
return Node.getNumPlacementArgs() > Index &&
@@ -10841,17 +8480,12 @@ AST_MATCHER_P2(CXXNewExpr, hasPlacementArg, unsigned, Index,
/// Matches any placement new expression arguments.
///
-/// Given
+/// Given:
/// \code
-/// void* operator new(decltype(sizeof(void*)), void*);
-/// struct MyClass { int x; };
-/// unsigned char Storage[sizeof(MyClass) * 10];
/// MyClass *p1 = new (Storage) MyClass();
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-///
-/// The matcher \matcher{cxxNewExpr(hasAnyPlacementArg(anything()))}
-/// matches \match{new (Storage) MyClass()}.
+/// cxxNewExpr(hasAnyPlacementArg(anything()))
+/// matches the expression 'new (Storage, 16) MyClass()'.
AST_MATCHER_P(CXXNewExpr, hasAnyPlacementArg, internal::Matcher<Expr>,
InnerMatcher) {
return llvm::any_of(Node.placement_arguments(), [&](const Expr *Arg) {
@@ -10861,18 +8495,12 @@ AST_MATCHER_P(CXXNewExpr, hasAnyPlacementArg, internal::Matcher<Expr>,
/// Matches array new expressions with a given array size.
///
-/// Given
+/// Given:
/// \code
-/// void* operator new(decltype(sizeof(void*)));
-/// struct MyClass { int x; };
/// MyClass *p1 = new MyClass[10];
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-///
-/// The matcher
-/// \matcher{cxxNewExpr(hasArraySize(
-/// ignoringImplicit(integerLiteral(equals(10)))))}
-/// matches \match{new MyClass[10]}.
+/// cxxNewExpr(hasArraySize(integerLiteral(equals(10))))
+/// matches the expression 'new MyClass[10]'.
AST_MATCHER_P(CXXNewExpr, hasArraySize, internal::Matcher<Expr>, InnerMatcher) {
return Node.isArray() && *Node.getArraySize() &&
InnerMatcher.matches(**Node.getArraySize(), Finder, Builder);
@@ -10880,42 +8508,33 @@ AST_MATCHER_P(CXXNewExpr, hasArraySize, internal::Matcher<Expr>, InnerMatcher) {
/// Matches a class declaration that is defined.
///
-/// Given
+/// Example matches x (matcher = cxxRecordDecl(hasDefinition()))
/// \code
/// class x {};
/// class y;
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{cxxRecordDecl(hasDefinition())}
-/// matches \match{class x {}}
AST_MATCHER(CXXRecordDecl, hasDefinition) {
return Node.hasDefinition();
}
/// Matches C++11 scoped enum declaration.
///
-/// Given
+/// Example matches Y (matcher = enumDecl(isScoped()))
/// \code
/// enum X {};
/// enum class Y {};
/// \endcode
-/// \compile_args{-std=c++}
-/// The matcher \matcher{enumDecl(isScoped())}
-/// matches \match{enum class Y {}}
AST_MATCHER(EnumDecl, isScoped) {
return Node.isScoped();
}
/// Matches a function declared with a trailing return type.
///
-/// Given
+/// Example matches Y (matcher = functionDecl(hasTrailingReturn()))
/// \code
/// int X() {}
/// auto Y() -> int {}
/// \endcode
-/// \compile_args{-std=c++11-or-later}
-/// The matcher \matcher{functionDecl(hasTrailingReturn())}
-/// matches \match{auto Y() -> int {}}.
AST_MATCHER(FunctionDecl, hasTrailingReturn) {
if (const auto *F = Node.getType()->getAs<FunctionProtoType>())
return F->hasTrailingReturn();
@@ -10934,6 +8553,7 @@ AST_MATCHER(FunctionDecl, hasTrailingReturn) {
/// appear in the C++17 AST.
///
/// Given
+///
/// \code
/// struct H {};
/// H G();
@@ -10941,11 +8561,9 @@ AST_MATCHER(FunctionDecl, hasTrailingReturn) {
/// H D = G();
/// }
/// \endcode
-/// \compile_args{-std=c++11-or-later}
///
-/// The matcher
-/// \matcher{varDecl(hasInitializer(ignoringElidableConstructorCall(callExpr())))}
-/// matches \match{H D = G()}.
+/// ``varDecl(hasInitializer(ignoringElidableConstructorCall(callExpr())))``
+/// matches ``H D = G()`` in C++11 through C++17 (and beyond).
AST_MATCHER_P(Expr, ignoringElidableConstructorCall, internal::Matcher<Expr>,
InnerMatcher) {
// E tracks the node that we are examining.
@@ -10976,21 +8594,15 @@ AST_MATCHER_P(Expr, ignoringElidableConstructorCall, internal::Matcher<Expr>,
/// Matches any ``#pragma omp`` executable directive.
///
/// Given
+///
/// \code
-/// void foo() {
-/// #pragma omp parallel
-/// {}
-/// #pragma omp parallel default(none)
-/// {
-/// #pragma omp taskyield
-/// }
-/// }
+/// #pragma omp parallel
+/// #pragma omp parallel default(none)
+/// #pragma omp taskyield
/// \endcode
-/// \compile_args{-fopenmp}
-/// The matcher \matcher{ompExecutableDirective()}
-/// matches \match{#pragma omp parallel},
-/// \match{#pragma omp parallel default(none)}
-/// and \match{#pragma omp taskyield}.
+///
+/// ``ompExecutableDirective()`` matches ``omp parallel``,
+/// ``omp parallel default(none)`` and ``omp taskyield``.
extern const internal::VariadicDynCastAllOfMatcher<Stmt, OMPExecutableDirective>
ompExecutableDirective;
@@ -10998,18 +8610,15 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, OMPExecutableDirective>
/// i.e., directives that can't have a structured block.
///
/// Given
+///
/// \code
-/// void foo() {
-/// #pragma omp parallel
-/// {
-/// #pragma omp taskyield
-/// }
-/// }
+/// #pragma omp parallel
+/// {}
+/// #pragma omp taskyield
/// \endcode
-/// \compile_args{-fopenmp}
///
-/// The matcher \matcher{ompExecutableDirective(isStandaloneDirective())}
-/// matches \match{#pragma omp taskyield}.
+/// ``ompExecutableDirective(isStandaloneDirective()))`` matches
+/// ``omp taskyield``.
AST_MATCHER(OMPExecutableDirective, isStandaloneDirective) {
return Node.isStandaloneDirective();
}
@@ -11020,20 +8629,15 @@ AST_MATCHER(OMPExecutableDirective, isStandaloneDirective) {
/// If it is, it will never match.
///
/// Given
+///
/// \code
-/// void foo() {
-/// #pragma omp parallel
-/// ;
-/// #pragma omp parallel
-/// {}
-/// }
+/// #pragma omp parallel
+/// ;
+/// #pragma omp parallel
+/// {}
/// \endcode
-/// \compile_args{-fopenmp}
///
-/// The matcher
-/// \matcher{ompExecutableDirective(hasStructuredBlock(nullStmt().bind("stmt")))}
-/// matches \match{#pragma omp parallel},
-/// with \matcher{type=sub$stmtt()} matching \match{sub=stmt${}}.
+/// ``ompExecutableDirective(hasStructuredBlock(nullStmt()))`` will match ``;``
AST_MATCHER_P(OMPExecutableDirective, hasStructuredBlock,
internal::Matcher<Stmt>, InnerMatcher) {
if (Node.isStandaloneDirective())
@@ -11044,18 +8648,14 @@ AST_MATCHER_P(OMPExecutableDirective, hasStructuredBlock,
/// Matches any clause in an OpenMP directive.
///
/// Given
+///
/// \code
-/// void foo() {
/// #pragma omp parallel
-/// ;
/// #pragma omp parallel default(none)
-/// ;
-/// }
/// \endcode
-/// \compile_args{-fopenmp}
///
-/// The matcher \matcher{ompExecutableDirective(hasAnyClause(anything()))}
-/// matches \match{#pragma omp parallel default(none)}.
+/// ``ompExecutableDirective(hasAnyClause(anything()))`` matches
+/// ``omp parallel default(none)``.
AST_MATCHER_P(OMPExecutableDirective, hasAnyClause,
internal::Matcher<OMPClause>, InnerMatcher) {
ArrayRef<OMPClause *> Clauses = Node.clauses();
@@ -11067,53 +8667,33 @@ AST_MATCHER_P(OMPExecutableDirective, hasAnyClause,
/// Matches OpenMP ``default`` clause.
///
/// Given
+///
/// \code
-/// void foo() {
-/// #pragma omp parallel default(none)
-/// ;
-/// #pragma omp parallel default(shared)
-/// ;
-/// #pragma omp parallel default(private)
-/// ;
-/// #pragma omp parallel default(firstprivate)
-/// ;
-/// #pragma omp parallel
-/// ;
-/// }
+/// #pragma omp parallel default(none)
+/// #pragma omp parallel default(shared)
+/// #pragma omp parallel default(private)
+/// #pragma omp parallel default(firstprivate)
+/// #pragma omp parallel
/// \endcode
-/// \compile_args{-fopenmp}
///
-/// The matcher
-/// \matcher{ompExecutableDirective(hasAnyClause(ompDefaultClause()))} matches
-/// \match{#pragma omp parallel default(none)},
-/// \match{#pragma omp parallel default(shared)},
-/// \match{#pragma omp parallel default(private)} and
-/// \match{#pragma omp parallel default(firstprivate)}.
+/// ``ompDefaultClause()`` matches ``default(none)``, ``default(shared)``,
+/// `` default(private)`` and ``default(firstprivate)``
extern const internal::VariadicDynCastAllOfMatcher<OMPClause, OMPDefaultClause>
ompDefaultClause;
/// Matches if the OpenMP ``default`` clause has ``none`` kind specified.
///
/// Given
+///
/// \code
-/// void foo() {
-/// #pragma omp parallel
-/// ;
-/// #pragma omp parallel default(none)
-/// ;
-/// #pragma omp parallel default(shared)
-/// ;
-/// #pragma omp parallel default(private)
-/// ;
-/// #pragma omp parallel default(firstprivate)
-/// ;
-/// }
+/// #pragma omp parallel
+/// #pragma omp parallel default(none)
+/// #pragma omp parallel default(shared)
+/// #pragma omp parallel default(private)
+/// #pragma omp parallel default(firstprivate)
/// \endcode
-/// \compile_args{-fopenmp}
///
-/// The matcher
-/// \matcher{ompExecutableDirective(hasAnyClause(ompDefaultClause(isNoneKind())))}
-/// matches only \match{#pragma omp parallel default(none)}.
+/// ``ompDefaultClause(isNoneKind())`` matches only ``default(none)``.
AST_MATCHER(OMPDefaultClause, isNoneKind) {
return Node.getDefaultKind() == llvm::omp::OMP_DEFAULT_none;
}
@@ -11121,25 +8701,16 @@ AST_MATCHER(OMPDefaultClause, isNoneKind) {
/// Matches if the OpenMP ``default`` clause has ``shared`` kind specified.
///
/// Given
+///
/// \code
-/// void foo() {
-/// #pragma omp parallel
-/// ;
-/// #pragma omp parallel default(none)
-/// ;
+/// #pragma omp parallel
+/// #pragma omp parallel default(none)
/// #pragma omp parallel default(shared)
-/// ;
/// #pragma omp parallel default(private)
-/// ;
/// #pragma omp parallel default(firstprivate)
-/// ;
-/// }
/// \endcode
-/// \compile_args{-fopenmp}
///
-/// The matcher
-/// \matcher{ompExecutableDirective(hasAnyClause(ompDefaultClause(isSharedKind())))}
-/// matches \match{#pragma omp parallel default(shared)}.
+/// ``ompDefaultClause(isSharedKind())`` matches only ``default(shared)``.
AST_MATCHER(OMPDefaultClause, isSharedKind) {
return Node.getDefaultKind() == llvm::omp::OMP_DEFAULT_shared;
}
@@ -11148,25 +8719,17 @@ AST_MATCHER(OMPDefaultClause, isSharedKind) {
/// specified.
///
/// Given
+///
/// \code
-/// void foo() {
-/// #pragma omp parallel
-/// ;
+/// #pragma omp parallel
/// #pragma omp parallel default(none)
-/// ;
/// #pragma omp parallel default(shared)
-/// ;
/// #pragma omp parallel default(private)
-/// ;
/// #pragma omp parallel default(firstprivate)
-/// ;
-/// }
/// \endcode
-/// \compile_args{-fopenmp}
///
-/// The matcher
-/// \matcher{ompExecutableDirective(hasAnyClause(ompDefaultClause(isPrivateKind())))}
-/// matches \match{#pragma omp parallel default(private)}.
+/// ``ompDefaultClause(isPrivateKind())`` matches only
+/// ``default(private)``.
AST_MATCHER(OMPDefaultClause, isPrivateKind) {
return Node.getDefaultKind() == llvm::omp::OMP_DEFAULT_private;
}
@@ -11175,25 +8738,17 @@ AST_MATCHER(OMPDefaultClause, isPrivateKind) {
/// specified.
///
/// Given
+///
/// \code
-/// void foo() {
-/// #pragma omp parallel
-/// ;
-/// #pragma omp parallel default(none)
-/// ;
-/// #pragma omp parallel default(shared)
-/// ;
-/// #pragma omp parallel default(private)
-/// ;
-/// #pragma omp parallel default(firstprivate)
-/// ;
-/// }
+/// #pragma omp parallel
+/// #pragma omp parallel default(none)
+/// #pragma omp parallel default(shared)
+/// #pragma omp parallel default(private)
+/// #pragma omp parallel default(firstprivate)
/// \endcode
-/// \compile_args{-fopenmp}
///
-/// The matcher
-/// \matcher{ompExecutableDirective(hasAnyClause(ompDefaultClause(isFirstPrivateKind())))}
-/// matches \match{#pragma omp parallel default(firstprivate)}.
+/// ``ompDefaultClause(isFirstPrivateKind())`` matches only
+/// ``default(firstprivate)``.
AST_MATCHER(OMPDefaultClause, isFirstPrivateKind) {
return Node.getDefaultKind() == llvm::omp::OMP_DEFAULT_firstprivate;
}
@@ -11202,23 +8757,15 @@ AST_MATCHER(OMPDefaultClause, isFirstPrivateKind) {
/// clause kind.
///
/// Given
+///
/// \code
-/// void foo() {
-/// #pragma omp parallel
-/// ;
-/// #pragma omp parallel for
-/// for (int i = 0; i < 10; ++i) {}
-/// #pragma omp for
-/// for (int i = 0; i < 10; ++i) {}
-/// }
+/// #pragma omp parallel
+/// #pragma omp parallel for
+/// #pragma omp for
/// \endcode
-/// \compile_args{-fopenmp}
///
-/// The matcher
-/// \matcher{ompExecutableDirective(isAllowedToContainClauseKind(
-/// OpenMPClauseKind::OMPC_default))}
-/// matches \match{#pragma omp parallel}
-/// and \match{#pragma omp parallel for}.
+/// `ompExecutableDirective(isAllowedToContainClause(OMPC_default))`` matches
+/// ``omp parallel`` and ``omp parallel for``.
///
/// If the matcher is use from clang-query, ``OpenMPClauseKind`` parameter
/// should be passed as a quoted string. e.g.,
diff --git a/clang/unittests/ASTMatchers/ASTMatchersTest.h b/clang/unittests/ASTMatchers/ASTMatchersTest.h
index 47bb7737316660..ad2f5f355621cd 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersTest.h
+++ b/clang/unittests/ASTMatchers/ASTMatchersTest.h
@@ -9,46 +9,12 @@
#ifndef LLVM_CLANG_UNITTESTS_ASTMATCHERS_ASTMATCHERSTEST_H
#define LLVM_CLANG_UNITTESTS_ASTMATCHERS_ASTMATCHERSTEST_H
-#include "clang/AST/APValue.h"
-#include "clang/AST/ASTTypeTraits.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclTemplate.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/NestedNameSpecifier.h"
-#include "clang/AST/Stmt.h"
-#include "clang/AST/Type.h"
-#include "clang/AST/TypeLoc.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/ASTMatchers/ASTMatchers.h"
-#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/DiagnosticIDs.h"
-#include "clang/Basic/LLVM.h"
-#include "clang/Basic/SourceLocation.h"
#include "clang/Frontend/ASTUnit.h"
-#include "clang/Serialization/PCHContainerOperations.h"
#include "clang/Testing/CommandLineArgs.h"
#include "clang/Testing/TestClangConfig.h"
-#include "clang/Tooling/ArgumentsAdjusters.h"
-#include "clang/Tooling/FixIt.h"
#include "clang/Tooling/Tooling.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/VirtualFileSystem.h"
-#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h"
-#include <cstddef>
-#include <iterator>
-#include <memory>
-#include <optional>
-#include <string>
-#include <type_traits>
-#include <utility>
-#include <vector>
namespace clang {
namespace ast_matchers {
@@ -327,8 +293,7 @@ template <typename T>
testing::AssertionResult matchAndVerifyResultConditionally(
const Twine &Code, const T &AMatcher,
std::unique_ptr<BoundNodesCallback> FindResultVerifier, bool ExpectResult,
- ArrayRef<std::string> Args = {}, StringRef Filename = "input.cc",
- const FileContentMappings &VirtualMappedFiles = {}) {
+ ArrayRef<std::string> Args = {}, StringRef Filename = "input.cc") {
bool VerifiedResult = false;
MatchFinder Finder;
VerifyMatch VerifyVerifiedResult(std::move(FindResultVerifier),
@@ -345,9 +310,7 @@ testing::AssertionResult matchAndVerifyResultConditionally(
// choices that we made above.
llvm::copy(Args, std::back_inserter(CompileArgs));
- if (!runToolOnCodeWithArgs(
- Factory->create(), Code, CompileArgs, Filename, "clang-tool",
- std::make_shared<PCHContainerOperations>(), VirtualMappedFiles)) {
+ if (!runToolOnCodeWithArgs(Factory->create(), Code, CompileArgs, Filename)) {
return testing::AssertionFailure() << "Parsing error in \"" << Code << "\"";
}
if (!VerifiedResult && ExpectResult) {
@@ -361,9 +324,7 @@ testing::AssertionResult matchAndVerifyResultConditionally(
VerifiedResult = false;
SmallString<256> Buffer;
std::unique_ptr<ASTUnit> AST(buildASTFromCodeWithArgs(
- Code.toStringRef(Buffer), CompileArgs, Filename, "clang-tool",
- std::make_shared<PCHContainerOperations>(),
- tooling::getClangStripDependencyFileAdjuster(), VirtualMappedFiles));
+ Code.toStringRef(Buffer), CompileArgs, Filename));
if (!AST.get())
return testing::AssertionFailure()
<< "Parsing error in \"" << Code << "\" while building AST";
@@ -472,357 +433,6 @@ template <typename T> class VerifyIdIsBoundTo : public BoundNodesCallback {
std::string Name;
};
-namespace detail {
-template <typename T>
-using hasDump_t = decltype(std::declval<const T &>().dump());
-template <typename T>
-constexpr bool hasDump = llvm::is_detected<hasDump_t, T>::value;
-
-template <typename T>
-using hasGetSourceRange_t =
- decltype(std::declval<const T &>().getSourceRange());
-template <typename T>
-constexpr bool hasGetSourceRange =
- llvm::is_detected<hasGetSourceRange_t, T>::value;
-
-template <typename T, std::enable_if_t<hasGetSourceRange<T>, bool> = true>
-std::optional<std::string> getText(const T *const Node,
- const ASTContext &Context) {
- return tooling::fixit::getText(*Node, Context).str();
-}
-inline std::optional<std::string> getText(const Attr *const Attribute,
- const ASTContext &) {
- return Attribute->getSpelling();
-}
-inline std::optional<std::string> getText(const void *const,
- const ASTContext &) {
- return std::nullopt;
-}
-
-template <typename T>
-auto getSourceRange(const T *const Node)
- -> std::optional<decltype(Node->getSourceRange())> {
- return Node->getSourceRange();
-}
-inline std::optional<SourceRange> getSourceRange(const void *const) {
- return std::nullopt;
-}
-
-template <typename T>
-auto getLocation(const T *const Node)
- -> std::optional<decltype(Node->getLocation())> {
- return Node->getLocation();
-}
-inline std::optional<SourceLocation> getLocation(const void *const) {
- return std::nullopt;
-}
-
-template <typename T>
-auto getBeginLoc(const T *const Node)
- -> std::optional<decltype(Node->getBeginLoc())> {
- return Node->getBeginLoc();
-}
-inline std::optional<SourceLocation> getBeginLoc(const void *const) {
- return std::nullopt;
-}
-
-inline std::optional<SourceLocation>
-getLocOfTagDeclFromType(const Type *const Node) {
- if (Node->isArrayType())
- if (const auto *const AType = Node->getPointeeOrArrayElementType()) {
- return getLocOfTagDeclFromType(AType);
- }
- if (const auto *const TDecl = Node->getAsTagDecl()) {
- return TDecl->getLocation();
- }
- return std::nullopt;
-}
-inline std::optional<SourceLocation>
-getLocOfTagDeclFromType(const void *const) {
- return std::nullopt;
-}
-
-template <typename T>
-auto getExprLoc(const T *const Node)
- -> std::optional<decltype(Node->getBeginLoc())> {
- return Node->getBeginLoc();
-}
-inline std::optional<SourceLocation> getExprLoc(const void *const) {
- return std::nullopt;
-}
-
-// Provides a string for test failures to show what was matched.
-template <typename T>
-static std::optional<std::string>
-getNodeDescription(const T *const Node, const ASTContext *const Context) {
- if constexpr (std::is_same_v<T, QualType>) {
- return Node->getAsString();
- }
- if constexpr (std::is_base_of_v<NamedDecl, T>) {
- return Node->getNameAsString();
- }
- if constexpr (std::is_base_of_v<Type, T>) {
- return QualType{Node, 0}.getAsString();
- }
-
- return detail::getText(Node, *Context);
-}
-
-template <typename T>
-bool shouldIgnoreNode(const T *const Node, const ASTContext &Context) {
- if (const auto Range = detail::getSourceRange(Node); Range.has_value()) {
- if (Range->isInvalid() ||
- !Context.getSourceManager().isInMainFile(Range->getBegin()))
- return true;
- } else if (const auto Loc = detail::getExprLoc(Node); Loc.has_value()) {
- if (Loc->isInvalid() || !Context.getSourceManager().isInMainFile(*Loc))
- return true;
- } else if (const auto Loc = detail::getLocation(Node); Loc.has_value()) {
- if (Loc->isInvalid() || !Context.getSourceManager().isInMainFile(*Loc))
- return true;
- } else if (const auto Loc = detail::getBeginLoc(Node); Loc.has_value()) {
- if (Loc->isInvalid() || !Context.getSourceManager().isInMainFile(*Loc))
- return true;
- } else if (const auto Loc = detail::getLocOfTagDeclFromType(Node);
- Loc.has_value()) {
- if (Loc->isInvalid() || !Context.getSourceManager().isInMainFile(*Loc))
- return true;
- }
- return false;
-}
-} // namespace detail
-
-enum class MatchKind {
- Code,
- Name,
- TypeStr,
-};
-
-inline llvm::StringRef toString(const MatchKind Kind) {
- switch (Kind) {
- case MatchKind::Code:
- return "Code";
- case MatchKind::Name:
- return "Name";
- case MatchKind::TypeStr:
- return "TypeStr";
- }
- llvm_unreachable("Unhandled MatchKind");
-}
-
-template <typename T> class VerifyBoundNodeMatch : public BoundNodesCallback {
-public:
- class Match {
- public:
- Match(const MatchKind Kind, std::string MatchString,
- const size_t MatchCount = 1)
- : Kind(Kind), MatchString(std::move(MatchString)),
- RemainingMatches(MatchCount) {}
-
- bool shouldRemoveMatched() {
- --RemainingMatches;
- return RemainingMatches == 0U;
- }
-
- template <typename U>
- static std::optional<std::string>
- getMatchText(const U *const Node, const ASTContext &Context,
- const MatchKind Kind, const bool EmitFailures = true) {
- if constexpr (std::is_same_v<U, NestedNameSpecifier>) {
- if (const IdentifierInfo *const Info = Node->getAsIdentifier())
- return Info->getName().str();
- if (const NamespaceDecl *const NS = Node->getAsNamespace())
- return getMatchText(NS, Context, Kind, EmitFailures);
- if (const NamespaceAliasDecl *const Alias = Node->getAsNamespaceAlias())
- return getMatchText(Alias, Context, Kind, EmitFailures);
- if (const CXXRecordDecl *const RDecl = Node->getAsRecordDecl())
- return getMatchText(RDecl, Context, Kind, EmitFailures);
- if (const Type *const RDecl = Node->getAsType())
- return getMatchText(RDecl, Context, Kind, EmitFailures);
- }
-
- switch (Kind) {
- case MatchKind::Code:
- return detail::getText(Node, Context);
- case MatchKind::Name:
- return getNameText(Node, EmitFailures);
- case MatchKind::TypeStr:
- return getTypeStrText(Node, EmitFailures);
- }
-
- return std::nullopt;
- }
-
- bool isMatch(const T *const Node, const ASTContext &Context) const {
- if (const auto OptMatchText = getMatchText(Node, Context, Kind))
- return *OptMatchText == MatchString;
-
- return false;
- }
-
- std::string getAsString() const {
- return llvm::formatv("MatchKind: {0}, MatchString: '{1}', "
- "RemainingMatches: {2}",
- toString(Kind), MatchString, RemainingMatches)
- .str();
- }
-
- MatchKind getMatchKind() const { return Kind; }
- llvm::StringRef getMatchString() const { return MatchString; }
-
- private:
- template <typename U>
- static std::optional<std::string>
- getNameText(const U *const Node, const bool EmitFailures = true) {
- if constexpr (std::is_base_of_v<Decl, U>) {
- if (const auto *const NDecl = llvm::dyn_cast<NamedDecl>(Node))
- return NDecl->getNameAsString();
- if (EmitFailures)
- ADD_FAILURE() << "'MatchKind::Name' requires 'U' to be a'NamedDecl'.";
- }
-
- if (EmitFailures)
- ADD_FAILURE() << "'MatchKind::Name' requires 'U' to be a "
- "'NamedDecl', but 'U' is not derived from 'Decl'.";
- return std::nullopt;
- }
-
- template <typename U>
- static std::optional<std::string>
- getTypeStrText(const U *const Node, const bool EmitFailures = true) {
- if constexpr (std::is_base_of_v<Type, U>)
- return QualType(Node, 0).getAsString();
- if constexpr (std::is_base_of_v<Decl, U>) {
- if (const auto *const TDecl = llvm::dyn_cast<TypeDecl>(Node))
- return getTypeStrText(TDecl->getTypeForDecl());
- if (const auto *const VDecl = llvm::dyn_cast<ValueDecl>(Node))
- return VDecl->getType().getAsString();
- }
- if (EmitFailures)
- ADD_FAILURE() << "Match kind is 'TypeStr', but node of type 'U' is "
- "not handled.";
- return std::nullopt;
- }
-
- MatchKind Kind;
- std::string MatchString;
- size_t RemainingMatches;
- };
-
- VerifyBoundNodeMatch(std::string Id, std::vector<Match> Matches)
- : Id(std::move(Id)), ExpectedMatches(std::move(Matches)),
- Matches(ExpectedMatches) {}
-
- bool run(const BoundNodes *const Nodes, ASTContext *const Context) override {
- const auto *const Node = Nodes->getNodeAs<T>(Id);
- if (Node == nullptr) {
- ADD_FAILURE() << "Expected Id '" << Id << "' to be bound to 'T'.";
- return true;
- }
-
- if constexpr (std::is_base_of_v<Decl, T>)
- if (const auto *const NDecl = llvm::dyn_cast<NamedDecl>(Node))
- if (const auto *Identifier = NDecl->getIdentifier();
- Identifier != nullptr && Identifier->getBuiltinID() > 0)
- return true;
-
- if (detail::shouldIgnoreNode(Node, *Context)) {
- return false;
- }
-
- const auto Iter = llvm::find_if(Matches, [Node, Context](const Match &M) {
- return M.isMatch(Node, *Context);
- });
- if (Iter == Matches.end()) {
- const auto NodeText =
- detail::getNodeDescription(Node, Context).value_or("<unknown>");
- const auto IsMultilineNodeText = NodeText.find('\n') != std::string::npos;
- ADD_FAILURE() << "No match of node '" << (IsMultilineNodeText ? "\n" : "")
- << NodeText << (IsMultilineNodeText ? "\n" : "")
- << "' was expected.\n"
- << "No match with remaining matches:"
- << getMatchComparisonText(Matches, Node, *Context)
- << "Match strings of Node for possible intended matches:"
- << getPossibleMatchStrings(Node, *Context)
- << "Already found matches:"
- << getMatchesAsString(FoundMatches) << "Expected matches:"
- << getMatchesAsString(ExpectedMatches);
- if constexpr (detail::hasDump<T>)
- Node->dump();
- return true;
- }
-
- if (Iter->shouldRemoveMatched()) {
- FoundMatches.push_back(*Iter);
- Matches.erase(Iter);
- }
-
- return true;
- }
-
- void onEndOfTranslationUnit() override {
- if (!ExpectedMatches.empty() && Matches.size() == ExpectedMatches.size())
- ADD_FAILURE() << "No matches were found.\n"
- << "Expected matches:"
- << getMatchesAsString(ExpectedMatches);
- else
- EXPECT_TRUE(Matches.empty())
- << "Not all expected matches were found.\n"
- << "Remaining matches:" << getMatchesAsString(Matches)
- << "Already found matches:" << getMatchesAsString(FoundMatches)
- << "Expected matches:" << getMatchesAsString(ExpectedMatches);
-
- Matches = ExpectedMatches;
- FoundMatches.clear();
-
- EXPECT_TRUE(FoundMatches.empty());
- }
-
-private:
- static std::string getMatchesAsString(const std::vector<Match> &Matches) {
- if (Matches.empty())
- return " none\n";
- std::string FormattedMatches{"\n"};
- for (const Match &M : Matches)
- FormattedMatches += "\t" + M.getAsString() + ",\n";
-
- return FormattedMatches;
- }
- static std::string getMatchComparisonText(const std::vector<Match> &Matches,
- const T *const Node,
- const ASTContext &Context) {
- if (Matches.empty())
- return " none\n";
- std::string MatchStrings{"\n"};
- for (const Match &M : Matches)
- MatchStrings += llvm::formatv(
- "\tMatchKind: {0}: '{1}' vs '{2}',\n", toString(M.getMatchKind()),
- Match::getMatchText(Node, Context, M.getMatchKind(), false)
- .value_or("<unknown>"),
- M.getMatchString());
-
- return MatchStrings;
- }
-
- static std::string getPossibleMatchStrings(const T *Node,
- const ASTContext &Context) {
- std::string MatchStrings{"\n"};
- for (const auto Kind :
- {MatchKind::Code, MatchKind::Name, MatchKind::TypeStr})
- MatchStrings +=
- llvm::formatv("\tMatchKind: {0}: '{1}',\n", toString(Kind),
- Match::getMatchText(Node, Context, Kind, false)
- .value_or("<unknown>"))
- .str();
- return MatchStrings;
- }
-
- const std::string Id;
- const std::vector<Match> ExpectedMatches;
- std::vector<Match> Matches;
- std::vector<Match> FoundMatches{};
-};
-
class ASTMatchersTest : public ::testing::Test,
public ::testing::WithParamInterface<TestClangConfig> {
protected:
@@ -843,40 +453,6 @@ class ASTMatchersTest : public ::testing::Test,
}
};
-class ASTMatchersDocTest
- : public ::testing::Test,
- public ::testing::WithParamInterface<TestClangConfig> {
-protected:
- template <typename T>
- testing::AssertionResult
- matches(const Twine &Code, const T &AMatcher,
- std::unique_ptr<BoundNodesCallback> FindResultVerifier,
- const ArrayRef<std::string> CompileArgs = {},
- const FileContentMappings &VirtualMappedFiles = {}) {
- const TestClangConfig &TestConfig = GetParam();
-
- auto Args = TestConfig.getCommandLineArgs();
- Args.insert(Args.end(), CompileArgs.begin(), CompileArgs.end());
- return clang::ast_matchers::matchAndVerifyResultConditionally(
- Code, AMatcher, std::move(FindResultVerifier), /*ExpectMatch=*/true,
- Args, getFilenameForTesting(TestConfig.Language), VirtualMappedFiles);
- }
-
- template <typename T>
- testing::AssertionResult
- notMatches(const Twine &Code, const T &AMatcher,
- std::unique_ptr<BoundNodesCallback> FindResultVerifier,
- const ArrayRef<std::string> CompileArgs = {},
- const FileContentMappings &VirtualMappedFiles = {}) {
- const TestClangConfig &TestConfig = GetParam();
-
- auto Args = TestConfig.getCommandLineArgs();
- Args.insert(Args.begin(), CompileArgs.begin(), CompileArgs.end());
- return clang::ast_matchers::matchAndVerifyResultConditionally(
- Code, AMatcher, std::move(FindResultVerifier), /*ExpectMatch=*/false,
- Args, getFilenameForTesting(TestConfig.Language), VirtualMappedFiles);
- }
-};
} // namespace ast_matchers
} // namespace clang
diff --git a/clang/unittests/ASTMatchers/CMakeLists.txt b/clang/unittests/ASTMatchers/CMakeLists.txt
index 3370f31cf6f28b..6a1e629d81b65b 100644
--- a/clang/unittests/ASTMatchers/CMakeLists.txt
+++ b/clang/unittests/ASTMatchers/CMakeLists.txt
@@ -4,26 +4,11 @@ set(LLVM_LINK_COMPONENTS
TargetParser
)
-add_custom_command(
- OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/ASTMatchersDocTests.cpp
- COMMAND
- ${CLANG_SOURCE_DIR}/utils/generate_ast_matcher_doc_tests.py ARGS
- --input-file
- ${CLANG_SOURCE_DIR}/include/clang/ASTMatchers/ASTMatchers.h
- --output-file
- ${CMAKE_CURRENT_BINARY_DIR}/ASTMatchersDocTests.cpp
- MAIN_DEPENDENCY
- ${CLANG_SOURCE_DIR}/include/clang/ASTMatchers/ASTMatchers.h
- DEPENDS
- ${CLANG_SOURCE_DIR}/utils/generate_ast_matcher_doc_tests.py
-)
-
add_clang_unittest(ASTMatchersTests
ASTMatchersInternalTest.cpp
ASTMatchersNodeTest.cpp
ASTMatchersNarrowingTest.cpp
ASTMatchersTraversalTest.cpp
- ${CMAKE_CURRENT_BINARY_DIR}/ASTMatchersDocTests.cpp
GtestMatchersTest.cpp
)
diff --git a/clang/utils/generate_ast_matcher_doc_tests.py b/clang/utils/generate_ast_matcher_doc_tests.py
deleted file mode 100755
index 2ee40d8a660684..00000000000000
--- a/clang/utils/generate_ast_matcher_doc_tests.py
+++ /dev/null
@@ -1,1097 +0,0 @@
-#!/usr/bin/env python3
-R"""
-TLDR:
-The order for a single code snippet example is:
-
- \header{a.h}
- \endheader <- zero or more header
-
- \code
- int a = 42;
- \endcode
- \compile_args{-std=c++,c23-or-later} <- optional, supports std ranges and
- whole languages
-
- \matcher{expr()} <- one or more matchers in succession
- \match{42} <- one ore more matches in succession
-
- \matcher{varDecl()} <- new matcher resets the context, the above
- \match will not count for this new
- matcher(-group)
- \match{int a = 42} <- only applies to the previous matcher (no the
- previous case)
-
-The above block can be repeated inside of a doxygen command for multiple
-code examples.
-
-Language Grammar:
- [] denotes an optional, and <> denotes user-input
-
- compile_args j:= \compile_args{[<compile_arg>;]<compile_arg>}
- matcher_tag_key ::= type
- match_tag_key ::= type || std || count
- matcher_tags ::= [matcher_tag_key=<value>;]matcher_tag_key=<value>
- match_tags ::= [match_tag_key=<value>;]match_tag_key=<value>
- matcher ::= \matcher{[matcher_tags$]<matcher>}
- matchers ::= [matcher] matcher
- match ::= \match{[match_tags$]<match>}
- matches ::= [match] match
- case ::= matchers matches
- cases ::= [case] case
- header-block ::= \header{<name>} <code> \endheader
- code-block ::= \code <code> \endcode
- testcase ::= code-block [compile_args] cases
-
-The 'std' tag and '\compile_args' support specifying a specific
-language version, a whole language and all of it's versions, and thresholds
-(implies ranges). Multiple arguments are passed with a ',' seperator.
-For a language and version to execute a tested matcher, it has to match
-the specified '\compile_args' for the code, and the 'std' tag for the matcher.
-Predicates for the 'std' compiler flag are used with disjunction between
-languages (e.g. 'c || c++') and conjunction for all predicates specific
-to each language (e.g. 'c++11-or-later && c++23-or-earlier').
-
-Examples:
- - c all available versions of C
- - c++11 only C++11
- - c++11-or-later C++11 or later
- - c++11-or-earlier C++11 or earlier
- - c++11-or-later,c++23-or-earlier,c all of C and C++ between 11 and
- 23 (inclusive)
- - c++11-23,c same as above
-
-Tags:
-
- Type:
- Match types are used to select where the string that is used to check if
- a node matches comes from.
- Available: code, name, typestr, typeofstr.
- The default is 'code'.
-
- Matcher types are used to mark matchers as submatchers with 'sub' or as
- deactivated using 'none'. Testing submatchers is not implemented.
-
- Count:
- Specifying a 'count=n' on a match will result in a test that requires that
- the specified match will be matched n times. Default is 1.
-
- Std:
- A match allows specifying if it matches only in specific language versions.
- This may be needed when the AST differs between language versions.
-"""
-
-import re
-from argparse import ArgumentParser, Namespace
-from collections import defaultdict
-from enum import Enum
-from functools import reduce
-from pathlib import Path
-from sys import exit
-
-statistics = defaultdict(int)
-
-expected_failure_statistics = {
- "missing_tests": 10,
- "skipped_objc": 42,
- "none_type_matchers": 6,
-}
-
-found_issue = False
-
-
-def parse_arguments() -> Namespace:
- parser = ArgumentParser(
- description="extract test cases from the documentation comments of AST"
- " matchers",
- )
-
- parser.add_argument(
- "--output-file",
- help="The path to the ASTMatchersDocTest.cpp file where the tests are"
- " written to.",
- type=Path,
- )
-
- parser.add_argument(
- "--input-file",
- help="The path to the ASTMatchers.h file",
- type=Path,
- )
-
- return parser.parse_args()
-
-
-def matcher_to_node_type(matcher: str) -> str:
- """Converts the written top-level matcher to the node type that the matcher
- will bind.
- Contains special cases because not all matcher names can be simply converted
- to a type by spelling it with uppercase characters in the beginning.
-
- Args:
- matcher: The matcher string
-
- Returns:
- The type of the node that a match will bind to
- """
- if matcher.startswith("traverse"):
- comma_loc = matcher.find(",")
- return matcher_to_node_type(matcher[comma_loc + 1 :].strip())
- if matcher.startswith("cxxBoolLiteral"):
- return "CXXBoolLiteralExpr"
- if matcher.startswith("binaryOperation"):
- return "Expr"
- if matcher.startswith("invocation"):
- return "Expr"
- if matcher.startswith("alignOfExpr"):
- return "Expr"
- if matcher.startswith("sizeOfExpr"):
- return "Expr"
- if matcher.startswith("floatLiteral"):
- return "FloatingLiteral"
- if matcher.startswith("gnuNullExpr"):
- return "GNUNullExpr"
- if matcher.startswith("cxx"):
- return "CXX" + matcher[3 : matcher.find("(")]
- if matcher.startswith("omp"):
- return "OMP" + matcher[3 : matcher.find("(")]
- if matcher.startswith("cuda"):
- return "CUDA" + matcher[4 : matcher.find("(")]
- if matcher.startswith("objc"):
- return "ObjC" + matcher[4 : matcher.find("(")]
- return matcher[0:1].upper() + matcher[1 : matcher.find("(")]
-
-
-def get_clang_config_constraint_expr(std: str) -> str:
- """Converts a single argument to 'std' into the corresponding check to be
- done in the tests.
-
- Args:
- std: A single argument to 'std' (e.g. 'c++11-or-later')
-
- Returns:
- An expression that checks is the test config enables what the 'std'
- argument specifies.
- """
- if std == "":
- return ""
-
- or_later_str = "-or-later"
- or_earlier_str = "-or-earlier"
- match = re.match(r"c(\d\d)-?(\d\d)?", std)
- if match:
- if len(match.groups()) == 3:
- return f"Conf.isCOrLater({match.group(1)}) && Conf.isOrEarlier({match.group(2)})"
- if std.endswith(or_later_str):
- return f"Conf.isCOrLater({match.group(1)})"
- if std.endswith(or_earlier_str):
- return f"Conf.isCOrEarlier({match.group(1)})"
- return f"Conf.Language == Lang_C{match.group(1)}"
-
- match = re.match(r"c\+\+(\d\d)-?(\d\d)?", std)
- if match:
- if len(match.groups()) == 3:
- return f"Conf.isCXXOrLater({match.group(1)}) && Conf.isCXXOrEarlier({match.group(2)})"
- if std.endswith(or_later_str):
- return f"Conf.isCXXOrLater({match.group(1)})"
- if std.endswith(or_earlier_str):
- return f"Conf.isCXXOrEarlier({match.group(1)})"
- return f"Conf.Language == Lang_CXX{match.group(1)}"
-
- if std == "c":
- return "Conf.isC()"
-
- if std == "c++":
- return "Conf.isCXX()"
-
- if std.startswith("-ObjC"):
- return ""
-
- return ""
-
-
-class TestLanguage:
- """Wraps multiple args to 'std' for emitting the config check inside the
- tests.
-
- Attributes:
- raw: The arg to 'std' as written
- c: The config check expression for C
- cxx: The config check expression for C++
- objc: The config check expression for ObjC
- """
-
- def __init__(self, std: str) -> None:
- self.raw = std
- self.c = ""
- self.cxx = ""
- self.objc = ""
- if std.startswith("-ObjC"):
- self.objc = std
- return
-
- for standard_spec in std.split(","):
- expr = get_clang_config_constraint_expr(standard_spec)
- if standard_spec.startswith("c++"):
- if self.cxx != "":
- self.cxx += " && "
- self.cxx += expr
- elif standard_spec.startswith("c"):
- if self.c != "":
- self.c += " && "
- self.c += expr
-
- def has_value(self):
- return self.c != "" or self.cxx != "" or self.objc != ""
-
- def get_config_check_expr(self):
- if self.c != "" and self.cxx != "":
- return f"({self.c}) || ({self.cxx})"
- if self.c != "":
- return self.c
- if self.cxx != "":
- return self.cxx
- if self.objc != "":
- return self.objc
- return ""
-
-
-class Tags:
- """Wrapper to parse and store the tags that can be passed to '\\match' and
- '\\matcher'.
-
- Attributes:
- map: The parsed tags by key ('str' -> 'str' map)
- opt_test_language: The 'std' tag is handled by TestLanguage
- """
-
- def __init__(self, tag_string: str) -> None:
- self.map = defaultdict(
- lambda: "",
- [split_first(tag, "=") for tag in tag_string.split(";")],
- )
-
- self.opt_test_language = None
- if "std" in self.map:
- self.opt_test_language = TestLanguage(self.map["std"])
- self.map.pop("std")
-
-
-class Matcher:
- def __init__(self, matcher: str, tags: Tags) -> None:
- self.matcher = matcher
- self.tags = tags
-
- def is_sub_matcher(self) -> bool:
- return self.tags.map["type"] == "sub"
-
- def __format__(self, format_spec: str) -> str:
- return self.matcher.__format__(format_spec)
-
- def __str__(self) -> str:
- return f"{self.matcher}"
-
- def __repr__(self) -> str:
- return f"{self.matcher}"
-
-
-class Match:
- def __init__(self, match_str: str, tags: Tags) -> None:
- self.match_str = match_str.replace("\n", " ")
- self.tags = tags
-
- def is_sub_match(self) -> bool:
- return self.tags.map["sub"] != ""
-
- def __format__(self, format_spec: str) -> str:
- return self.match_str.__format__(format_spec)
-
- def __str__(self) -> str:
- return f"{self.match_str}"
-
- def __repr__(self) -> str:
- return f"{self.match_str}"
-
- def get_as_cpp_raw_string(self) -> str:
- return f'R"cpp({self.match_str})cpp"'
-
-
-def get_lang_spec_and_remove_from_list(args: list) -> str:
- for arg in args:
- if arg == "-ObjC":
- args.remove(arg)
- return arg
- if arg.startswith("-std="):
- args.remove(arg)
- return arg[5:]
- return ""
-
-
-class CompileArgs:
- """Represents the '\\compile_args' command and its arguments.
-
- Attributes:
- lang_spec: The specified test language
- args: All other arguments
- """
-
- def __init__(self, args: list) -> None:
- self.lang_spec = TestLanguage(get_lang_spec_and_remove_from_list(args))
- self.args = args
-
- if any(("cuda" in arg for arg in self.args)) and not any(
- "-x" in arg for arg in self.args
- ):
- self.args.append("-xcuda")
- self.args.append("-nocudainc")
- self.args.append("-nocudalib")
-
- def is_cuda(self) -> bool:
- return any("cuda" in cmd for cmd in self.args)
-
- def is_objc(self) -> bool:
- return self.lang_spec.objc != ""
-
-
-def get_any_valid_std_specified(lang_spec: str) -> str:
- """Get any argument to '-std' that satisfies the language specification
- in 'lang_spec'
-
- Args:
- lang_spec: An argument to 'std'
-
- Returns:
- Any valid argument to the '-std' compiler flag that satisfies
- 'lang_spec'
- """
- if lang_spec == "":
- return "c++11"
-
- first_comma = lang_spec.find(",")
- if first_comma != -1:
- lang_spec = lang_spec[:first_comma]
-
- first_minus = lang_spec.find("-")
- if first_minus != -1:
- lang_spec = lang_spec[:first_minus]
-
- elif lang_spec == "c":
- lang_spec = "c11"
- elif lang_spec == "c++":
- lang_spec = "c++11"
-
- return lang_spec
-
-
-def get_with_lang_spec(args: CompileArgs) -> list:
- """Construct compiler arguments from a CompileArgs instance
-
- Args:
- args: The arguments to '\\compile_args'
-
- Returns:
- A list of compiler arguments that satisfy what is specified in 'args'
- """
- if args.lang_spec.objc.startswith("-ObjC"):
- return [*args.args, args.lang_spec.objc]
-
- if args.lang_spec.has_value():
- return [*args.args, "-std=" + get_any_valid_std_specified(args.lang_spec.raw)]
-
- return args.args
-
-
-cuda_header: str = """
- typedef unsigned long long size_t;
- #define __constant__ __attribute__((constant))
- #define __device__ __attribute__((device))
- #define __global__ __attribute__((global))
- #define __host__ __attribute__((host))
- #define __shared__ __attribute__((shared))
- struct dim3 {
- unsigned x, y, z;
- __host__ __device__ dim3(unsigned x, unsigned y = 1, unsigned z = 1)
- : x(x), y(y), z(z) {}
- };
- typedef struct cudaStream *cudaStream_t;
- int cudaConfigureCall(dim3 gridSize, dim3 blockSize,
- size_t sharedSize = 0,
- cudaStream_t stream = 0);
- extern "C" unsigned __cudaPushCallConfiguration(
- dim3 gridDim, dim3 blockDim, size_t sharedMem = 0, void *stream =
- 0);
-"""
-
-
-class MatchType(Enum):
- """Available types of a match, specified by using the lowercase version in
- doxygen: '\\match{type=typestr}'.
- Specifies what string from the matched node should be used to check for a
- match.
-
- Attributes:
- Invalid: Specified an invalid match type
- Code: Check if a matched node matches by using it's text
- (SourceRange -> Lexer)
- Name: Use the name of the matched node to check if it matches
- TypeStr: Use the string representation of the matched type to check if
- it matches
- """
-
- Invalid = 0
- Code = 1
- Name = 2
- TypeStr = 3
-
-
-def get_match_type(match: Match) -> MatchType:
- match_type = match.tags.map["type"]
- if match_type == "name":
- return MatchType.Name
- if match_type == "" or match_type == "code":
- return MatchType.Code
- if match_type == "typestr":
- return MatchType.TypeStr
- print(f"match {match} has an invalid match type: {match_type}")
- statistics["match_type_invalid"] += 1
- return MatchType.Invalid
-
-
-def get_match_count(match: Match) -> str:
- count = match.tags.map["count"]
- if count == "":
- return "1"
- return count
-
-
-def construct_match(match: Match) -> str:
- result = ""
- if match.tags.opt_test_language:
- result += f"\tif ({match.tags.opt_test_language.get_config_check_expr()})\n\t"
-
- result += f"\tMatches.emplace_back(MatchKind::{get_match_type(match).name}, {match.get_as_cpp_raw_string()}, {get_match_count(match)});"
- return result
-
-
-class TestCase:
- """Represents a single code example and its tests. Tests are added during
- parsing and finally emitted as C++ test code.
-
- Attributes:
- input_file: The file path where the matcher was specified
- line: The line that the test case starts at
- cases: The collected cases for this example code
- code: The example code
- headers: Headers, if any
- compile_args: Compile arguments, if any
- """
-
- def __init__(self, input_file: Path, line: int):
- self.input_file = input_file
- self.line = line
- self.cases: list[tuple[list[Matcher], list[Match]]] = []
- self.code: str = ""
- self.headers: list[tuple[str, str]] = []
- self.compile_args = None
-
- def get_last_case(self) -> tuple:
- return self.cases[-1]
-
- def add_case(self):
- self.cases.append(([], []))
-
- def add_matcher(self, matcher: Matcher):
- self.get_last_case()[0].append(matcher)
-
- def add_match(self, match: Match):
- self.get_last_case()[1].append(match)
-
- def has_non_lang_spec_compile_args(self) -> bool:
- return self.compile_args is not None and len(self.compile_args.args) != 0
-
- def has_headers(self) -> bool:
- return len(self.headers) != 0
-
- def get_compile_commands(self) -> str:
- if self.compile_args is None:
- return "{}"
- return "{ " + ",".join([f'"{arg}"' for arg in self.compile_args.args]) + " }"
-
- def diag(self, message: str):
- print(f"{self.input_file}:{self.line + 1}: {message}")
-
- def has_match_with_std_constraint(self) -> bool:
- return any(
- (
- any(match.tags.opt_test_language for match in case[1])
- for case in self.cases
- ),
- )
-
- def get_formated_headers(self) -> str:
- return "\n\t".join(
- f'std::pair{{"{header[0]}", \n\tR"cpp({header[1]})cpp"}},'
- for header in self.headers
- )
-
- def build_test_case(self):
- self.code = self.code.strip("\n")
- has_cuda = self.compile_args and self.compile_args.is_cuda()
- if has_cuda:
- self.headers.append(("cuda.h", cuda_header))
-
- res = ""
- if has_cuda:
- res += "#if LLVM_HAS_NVPTX_TARGET\n"
-
- res += f"""TEST_P(ASTMatchersDocTest, docs_{self.line + 1}) {{
- const StringRef Code = R"cpp(\n"""
- if has_cuda:
- res += '\t#include "cuda.h"\n'
- res += f'{self.code})cpp";\n'
-
- if self.has_headers():
- res += f"\tconst FileContentMappings VirtualMappedFiles = {{{self.get_formated_headers()}}};"
-
- if self.compile_args and self.compile_args.lang_spec.objc != "":
- statistics["skipped_objc"] += 1
- return ""
-
- statistics["code_snippets"] += 1
-
- statistics["matches"] += reduce(
- lambda a, b: a + b,
- (len(v[1]) for v in self.cases),
- )
-
- statistics["matchers"] += reduce(
- lambda a, b: a + b,
- (len(v[0]) for v in self.cases),
- )
-
- if self.compile_args and self.compile_args.lang_spec.has_value():
- res += f"""
- const TestClangConfig& Conf = GetParam();
- const bool ConfigEnablesCheckingCode = {self.compile_args.lang_spec.get_config_check_expr()};
- if (!ConfigEnablesCheckingCode) return;\n"""
-
- elif self.has_match_with_std_constraint():
- res += "\n\tconst TestClangConfig& Conf = GetParam();\n"
-
- # Don't want to emit a test without any actual tested matchers.
- # Would result in warnings about unused variables (Code) during the
- # build.
- case_has_test = False
-
- for matchers, matches in self.cases:
- if len(matchers) == 0:
- self.diag("test cases have no matchers")
- continue
-
- for matcher in matchers:
- if matcher.matcher.startswith("objc"):
- statistics["skipped_objc"] += 1
- continue
- # FIXME: add support for testing submatchers
- if matcher.tags.map["type"] == "sub":
- continue
- if matcher.tags.map["type"] == "none":
- statistics["none_type_matchers"] += 1
- continue
- matcher_type = matcher_to_node_type(matcher.matcher)
-
- statistics["tested_matchers"] += 1
- case_has_test = True
-
- verifier_type = f"VerifyBoundNodeMatch<{matcher_type}>"
-
- code_adding_matches = "\n".join(
- construct_match(match)
- for match in matches
- if match.tags.map["sub"] == ""
- )
-
- match_function = (
- "matches" if len(code_adding_matches) != 0 else "notMatches"
- )
-
- res += f"""
- {{
- SCOPED_TRACE("Test failure from docs_{self.line + 1} originates here.");
- using Verifier = {verifier_type};
-
- std::vector<Verifier::Match> Matches;
-{code_adding_matches}
-
- EXPECT_TRUE({match_function}(
- Code,
- {matcher.matcher}.bind("match"),
- std::make_unique<Verifier>("match", Matches)"""
-
- if self.has_headers():
- res += f",\n\t\t{self.get_compile_commands()}"
- res += ",\n\t\tVirtualMappedFiles"
- elif self.has_non_lang_spec_compile_args():
- res += f",\n\t\t{self.get_compile_commands()}"
-
- res += "));\n\t}\n"
-
- if not case_has_test:
- return ""
-
- res += "}"
- if has_cuda:
- res += "\n#endif\n"
- return res
-
-
-class ParsingContext(Enum):
- NoneCtx = 0
- Code = 1
- Header = 2
- CompileArgs = 3
- Matcher = 4
- Match = 5
- NoMatch = 6
-
-
-def split_first(data: str, delim: str) -> tuple:
- pos = data.find(delim)
- if pos == -1:
- return (data, "")
-
- return (data[0:pos], data[pos + 1 :])
-
-
-def find_matching_closing_rbrace(
- data: str,
- start_pos: int,
- braces_to_be_matched: int,
-) -> int:
- next_lbrace = data.find("{", start_pos)
- next_rbrace = data.find("}", start_pos)
- if next_lbrace != -1:
- if next_lbrace < next_rbrace:
- return find_matching_closing_rbrace(
- data,
- next_lbrace + 1,
- braces_to_be_matched + 1,
- )
- if braces_to_be_matched == 0:
- return next_rbrace
- return find_matching_closing_rbrace(
- data,
- next_rbrace + 1,
- braces_to_be_matched - 1,
- )
-
- if braces_to_be_matched > 0:
- return find_matching_closing_rbrace(
- data,
- next_rbrace + 1,
- braces_to_be_matched - 1,
- )
-
- return next_rbrace
-
-
-class CommentedMatcher:
- """Represents a matcher and it's corresponding doxygen comment.
-
- Attributes:
- comment: The doxygen comment
- matcher: The actual matcher code/implementation
- """
-
- def __init__(
- self,
- comment: list,
- matcher: list,
- ):
- self.comment = comment
- self.matcher = matcher
-
-
-class BlockParser:
- """The parser that parses the test cases from a doxygen block.
-
- Attributes:
- input_file: The file where the matchers are located
- cases: All TestCases
- current_line: The line that the parser is currently on
- data: The lines in the comment
- """
-
- def __init__(self, data: CommentedMatcher, input_file: Path):
- self.input_file = input_file
- self.cases = list()
- self.current_line = data.comment[0][0]
- self.data = "\n".join([line[1] for line in data.comment])
- self.diagnostics = list()
-
- def advance(self) -> ParsingContext:
- """Find the next doxygen command to be parsed and return the
- ParsingContext it represents.
-
- Returns:
- The ParsingContext of the location the parser arived at.
- """
- begin_tags = {
- "\\code": ParsingContext.Code,
- "\\header{": ParsingContext.Header,
- "\\compile_args{": ParsingContext.CompileArgs,
- "\\matcher{": ParsingContext.Matcher,
- "\\match{": ParsingContext.Match,
- "\\nomatch{": ParsingContext.NoMatch,
- }
-
- matches = list()
-
- for tag, ctx in begin_tags.items():
- match = self.data.find(tag)
- if match == -1:
- continue
- matches.append((match, ctx, tag))
-
- if len(matches) == 0:
- return ParsingContext.NoneCtx
-
- matches.sort()
-
- loc, ctx, tag = matches[0]
- loc = loc + len(tag) - 1
- self.consume_until(loc)
- return ctx
-
- def add_case(self, line: int):
- self.cases.append(TestCase(self.input_file, line))
-
- def delete_last_test(self):
- self.cases.pop()
-
- def get_last_case(self) -> TestCase:
- return self.cases[-1]
-
- def add_matcher(self, matcher: Matcher):
- if matcher.is_sub_matcher():
- return
- self.get_last_case().add_matcher(matcher)
-
- def add_match(self, match: Match):
- if match.is_sub_match():
- return
- self.get_last_case().add_match(match)
-
- def consume_until(self, pos: int):
- self.current_line += self.data.count("\n", 0, pos)
- self.data = self.data[pos + 1 :]
-
- def visit_code_block(self):
- code_end = "\\endcode"
- endcode_loc = self.data.find(code_end)
- end = endcode_loc + len(code_end)
-
- self.get_last_case().code = self.data[:endcode_loc].replace("\n", "\n\t")
-
- self.consume_until(end)
-
- def visit_header(self):
- header_end = "\\endheader"
- endheader_loc = self.data.find(header_end)
- end = endheader_loc + len(header_end)
-
- vrbrace_loc = find_matching_closing_rbrace(self.data, 0, 0)
- header_name = self.data[0:vrbrace_loc]
-
- self.get_last_case().headers.append(
- (
- header_name,
- self.data[vrbrace_loc + 1 : endheader_loc].replace("\n", "\n\t"),
- ),
- )
-
- self.consume_until(end)
-
- def visit_compile_args(self):
- end = find_matching_closing_rbrace(self.data, 0, 0)
-
- args = self.data[:end]
- self.consume_until(end)
-
- self.get_last_case().compile_args = CompileArgs(
- [split_arg for arg in args.split(";") for split_arg in arg.split(" ")],
- )
-
- def build_matcher(self):
- end = find_matching_closing_rbrace(self.data, 0, 0)
- tag_separator = self.data.find("$")
- tags = Tags("")
- if tag_separator != -1 and tag_separator < end:
- tags = Tags(self.data[:tag_separator])
- self.consume_until(tag_separator)
-
- # find the '}' again, self.data shifted
- end = find_matching_closing_rbrace(self.data, 0, 0)
-
- matcher_str = self.data[:end]
- if matcher_str.count("(") != matcher_str.count(")"):
- self.diag(
- f"The matcher {matcher_str} has an unbalanced number of parentheses"
- )
- self.consume_until(end)
- return None
-
- matcher = Matcher(self.data[:end], tags)
- self.consume_until(end)
- return matcher
-
- def visit_match(self):
- end = find_matching_closing_rbrace(self.data, 0, 0)
- tag_separator = self.data.find("$")
- tags = Tags("")
- if tag_separator != -1 and tag_separator < end:
- tags = Tags(self.data[:tag_separator])
- self.consume_until(tag_separator)
-
- # find the '}' again, self.data shifted
- end = find_matching_closing_rbrace(self.data, 0, 0)
- self.add_match(Match(self.data[:end], tags))
- self.consume_until(end)
-
- def diag(self, msg: str):
- # Save diagnostics instead of emitting them to remove the noise of diagnosed issues,
- # when the issues are all expected.
- self.diagnostics.append(f"{self.input_file}:{self.current_line + 1}: {msg}")
-
- def run(self):
- ctx = self.advance()
-
- if ctx == ParsingContext.NoneCtx:
- self.diag("matcher is missing an example")
- statistics["missing_tests"] += 1
- return
-
- while ctx != ParsingContext.NoneCtx:
- self.add_case(self.current_line)
- while ctx == ParsingContext.Header:
- self.visit_header()
- ctx = self.advance()
-
- if ctx != ParsingContext.Code:
- self.diag(f"expected {ParsingContext.Code}, not {ctx}")
- statistics["missing_tests"] += 1
- self.delete_last_test()
- return
-
- self.visit_code_block()
- ctx = self.advance()
-
- if ctx == ParsingContext.CompileArgs:
- self.visit_compile_args()
- compile_args = self.get_last_case().compile_args
- ctx = self.advance()
- if compile_args and compile_args.is_objc():
- self.delete_last_test()
- statistics["skipped_objc"] += 1
-
- while ctx != ParsingContext.Code and ctx != ParsingContext.NoneCtx:
- ctx = self.advance()
-
- continue
-
- if ctx != ParsingContext.Matcher:
- if ctx == ParsingContext.NoneCtx:
- self.diag(
- "this code example is missing an example matcher and matches",
- )
- else:
- self.diag(
- f"expected {ParsingContext.Matcher} after {ParsingContext.Code}, not {ctx}",
- )
-
- statistics["missing_tests"] += 1
- self.delete_last_test()
- return
-
- while ctx == ParsingContext.Matcher:
- matcher = self.build_matcher()
- if matcher and not matcher.is_sub_matcher():
- self.get_last_case().add_case()
-
- if matcher:
- self.add_matcher(matcher)
-
- ctx = self.advance()
- while ctx == ParsingContext.Matcher:
- matcher = self.build_matcher()
- if matcher:
- self.add_matcher(matcher)
- ctx = self.advance()
-
- if ctx != ParsingContext.Match and ctx != ParsingContext.NoMatch:
- if ctx == ParsingContext.NoneCtx:
- self.diag(
- "this matcher does not specify what it should or shouldn't match",
- )
- else:
- self.diag(
- f"expected {ParsingContext.Match} or {ParsingContext.NoMatch} after {ParsingContext.Matcher}, not {ctx}",
- )
-
- statistics["matcher_groups_without_matches"] += 1
- break
-
- while ctx == ParsingContext.Match or ctx == ParsingContext.NoMatch:
- if ctx == ParsingContext.Match:
- self.visit_match()
- ctx = self.advance()
-
-
-def parse_block(data: CommentedMatcher, input_file: Path) -> BlockParser:
- parser = BlockParser(data, input_file)
- parser.run()
- return parser
-
-
-def parse(data: list, input_file: Path) -> tuple:
- result: tuple = ([], [])
-
- for parsed_block in [parse_block(block, input_file) for block in data]:
- result[0].extend(parsed_block.cases)
- result[1].extend(parsed_block.diagnostics)
-
- return result
-
-
-def group_doc_comment_and_followed_code(
- enumerated_lines: list,
-) -> list:
- result: list = []
-
- start_new_group_on_comment = True
- for line_nr, line in enumerate(enumerated_lines, start=1):
- if line.startswith("///"):
- if start_new_group_on_comment:
- result.append(CommentedMatcher([], []))
- start_new_group_on_comment = False
- if len(result) != 0:
- result[-1].comment.append((line_nr, line[4:].rstrip()))
- else:
- start_new_group_on_comment = True
- if len(result) != 0:
- result[-1].matcher.append((line_nr, line))
-
- return result
-
-
-test_file_begin = """
-// unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp - AST matcher unit tests//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "ASTMatchersTest.h"
-#include "clang/ASTMatchers/ASTMatchers.h"
-#include "clang/Testing/TestClangConfig.h"
-#include "gtest/gtest.h"
-#include <string>
-
-namespace clang {
-namespace ast_matchers {
-"""
-
-test_file_end = """
-static std::vector<TestClangConfig> allTestClangConfigs() {
- std::vector<TestClangConfig> all_configs;
- for (TestLanguage lang : {
-#define TESTLANGUAGE(lang, version, std_flag, index) Lang_##lang##version,
-#include "clang/Testing/TestLanguage.def"
- }) {
- TestClangConfig config;
- config.Language = lang;
-
- // Use an unknown-unknown triple so we don't instantiate the full system
- // toolchain. On Linux, instantiating the toolchain involves stat'ing
- // large portions of /usr/lib, and this slows down not only this test, but
- // all other tests, via contention in the kernel.
- //
- // FIXME: This is a hack to work around the fact that there's no way to do
- // the equivalent of runToolOnCodeWithArgs without instantiating a full
- // Driver. We should consider having a function, at least for tests, that
- // invokes cc1.
- config.Target = "i386-unknown-unknown";
- all_configs.push_back(config);
-
- // Windows target is interesting to test because it enables
- // `-fdelayed-template-parsing`.
- config.Target = "x86_64-pc-win32-msvc";
- all_configs.push_back(config);
- }
- return all_configs;
-}
-
-INSTANTIATE_TEST_SUITE_P(
- ASTMatchersTests, ASTMatchersDocTest,
- testing::ValuesIn(allTestClangConfigs()),
- [](const testing::TestParamInfo<TestClangConfig> &Info) {
- return Info.param.toShortString();
- });
-} // namespace ast_matchers
-} // namespace clang
-"""
-
-
-def main():
- args = parse_arguments()
-
- assert args.input_file.exists()
-
- comment_blocks = group_doc_comment_and_followed_code(
- args.input_file.read_text().split("\n"),
- )
-
- statistics["doxygen_blocks"] = len(comment_blocks)
- results = parse(comment_blocks, args.input_file)
-
- res: str = (
- "\n\n".join(
- filter(
- lambda case: len(case) != 0,
- [r.build_test_case() for r in results[0]],
- ),
- )
- + "\n"
- )
-
- args.output_file.write_text(test_file_begin + res + test_file_end)
-
- global found_issue
- for key, value in expected_failure_statistics.items():
- if value != statistics[key]:
- print(
- "Mismatch between expected and actual failure statistic: "
- f"{key}: expected: {value}, actual: {statistics[key]}. "
- "Please fix the issue or adjust the expected_failure_statistics"
- " value if appropriate."
- )
- found_issue = True
-
- if found_issue:
- for diag in results[1]:
- print(diag)
-
- print("Statistics:")
- for key, value in statistics.items():
- print(f"\t{key: <30}: {value: >5}")
-
- exit(1)
-
-
-# FIXME: add support in the html gen script to differentiate between overloads examples
-# FIXME: should verify that all polymorphic ast nodes have a test
-
-
-if __name__ == "__main__":
- main()
More information about the cfe-commits
mailing list