[llvm-branch-commits] [clang] 2f82f95 - Revert "Reland: [clang][test] add testing for the AST matcher reference (#112…"
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Nov 15 22:34:06 PST 2024
Author: Julian Schmidt
Date: 2024-11-16T07:33:59+01:00
New Revision: 2f82f958126dbe55e580db8c65e087c054564ed6
URL: https://github.com/llvm/llvm-project/commit/2f82f958126dbe55e580db8c65e087c054564ed6
DIFF: https://github.com/llvm/llvm-project/commit/2f82f958126dbe55e580db8c65e087c054564ed6.diff
LOG: Revert "Reland: [clang][test] add testing for the AST matcher reference (#112…"
This reverts commit 53e92e48d0c03a2475e8517dd4c28968d84fc217.
Added:
Modified:
clang/docs/LibASTMatchersReference.html
clang/docs/ReleaseNotes.rst
clang/docs/doxygen.cfg.in
clang/docs/tools/dump_ast_matchers.py
clang/include/clang/ASTMatchers/ASTMatchers.h
clang/unittests/ASTMatchers/ASTMatchersTest.h
clang/unittests/ASTMatchers/CMakeLists.txt
Removed:
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
diff erent 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
diff erent parts of the statement are expanded from
diff erent
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
diff erent parts of the statement are expanded from
diff erent
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
diff erent parts of the statement are expanded from
diff erent
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
diff ers 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
-//
diff erent `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
diff erent parts of the statement are expanded from
diff erent
/// 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
diff erent 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
diff erent
-/// 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()) == (ptr
diff _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
diff erent 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
diff ers 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
diff erentiate between overloads examples
-# FIXME: should verify that all polymorphic ast nodes have a test
-
-
-if __name__ == "__main__":
- main()
More information about the llvm-branch-commits
mailing list