[clang] Reland: [clang][test] add testing for the AST matcher reference (PR #112168)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 14 01:35:10 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Julian Schmidt (5chmidti)
<details>
<summary>Changes</summary>
## Problem Statement
Previously, the examples in the AST matcher reference, which gets generated by the Doxygen comments in `ASTMatchers.h`, were untested and best effort.
Some of the matchers had no or wrong examples of how to use the matcher.
## Solution
This patch introduces a simple DSL around Doxygen commands to enable testing the AST matcher documentation in a way that should be relatively easy to use.
In `ASTMatchers.h`, most matchers are documented with a Doxygen comment. Most of these also have a code example that aims to show what the matcher will match, given a matcher somewhere in the documentation text. The way that the documentation is tested, is by using Doxygen's alias feature to declare custom aliases. These aliases forward to `<tt>text</tt>` (which is what Doxygen's `\c` does, but for multiple words). Using the Doxygen aliases is the obvious choice, because there are (now) four consumers:
- people reading the header/using signature help
- the Doxygen generated documentation
- the generated HTML AST matcher reference
- (new) the generated matcher tests
This patch rewrites/extends the documentation such that all matchers have a documented example.
The new `generate_ast_matcher_doc_tests.py` script will warn on any undocumented matchers (but not on matchers without a Doxygen comment) and provides diagnostics and statistics about the matchers.
The current statistics emitted by the parser are:
```text
Statistics:
doxygen_blocks : 519
missing_tests : 10
skipped_objc : 42
code_snippets : 503
matches : 820
matchers : 580
tested_matchers : 574
none_type_matchers : 6
```
The tests are generated during building, and the script will only print something if it found an issue with the specified tests (e.g., missing tests).
## Description
DSL for generating the tests from documentation.
TLDR:
```
\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
\match{42} <- one or more matches in succession
\matcher{varDecl()} <- new matcher resets the context, the above
\match will not count for this new
matcher(-group)
\match{int a = 42} <- only applies to the previous matcher (not to the
previous case)
```
The above block can be repeated inside a Doxygen command for multiple code examples for a single matcher.
The test generation script will only look for these annotations and ignore anything else like `\c` or the sentences where these annotations are embedded into: `The matcher \matcher{expr()} matches the number \match{42}.`.
### Language Grammar
[] denotes an optional, and <> denotes user-input
```
compile_args j:= \compile_args{[<compile_arg>;]<compile_arg>}
matcher_tag_key ::= type
match_tag_key ::= type || std || count || sub
matcher_tags ::= [matcher_tag_key=<value>;]matcher_tag_key=<value>
match_tags ::= [match_tag_key=<value>;]match_tag_key=<value>
matcher ::= \matcher{[matcher_tags$]<matcher>}
matchers ::= [matcher] matcher
match ::= \match{[match_tags$]<match>}
matches ::= [match] match
case ::= matchers matches
cases ::= [case] case
header-block ::= \header{<name>} <code> \endheader
code-block ::= \code <code> \endcode
testcase ::= code-block [compile_args] cases
```
### Language Standard Versions
The 'std' tag and '\compile_args' support specifying a specific language version, a whole language and all of its versions, and thresholds (implies ranges). Multiple arguments are passed with a ',' separator. For a language and version to execute a tested matcher, it has to match the specified '\compile_args' for the code, and the 'std' tag for the matcher. Predicates for the 'std' compiler flag are used with disjunction between languages (e.g. 'c || c++') and conjunction for all predicates specific to each language (e.g. 'c++11-or-later && c++23-or-earlier').
Examples:
- `c` all available versions of C
- `c++11` only C++11
- `c++11-or-later` C++11 or later
- `c++11-or-earlier` C++11 or earlier
- `c++11-or-later,c++23-or-earlier,c` all of C and C++ between 11 and
23 (inclusive)
- `c++11-23,c` same as above
### Tags
#### `type`:
**Match types** are used to select where the string that is used to check if a node matches comes from.
Available: `code`, `name`, `typestr`, `typeofstr`. The default is `code`.
- `code`: Forwards to `tooling::fixit::getText(...)` and should be the preferred way to show what matches.
- `name`: Casts the match to a `NamedDecl` and returns the result of `getNameAsString`. Useful when the matched AST node is not easy to spell out (`code` type), e.g., namespaces or classes with many members.
- `typestr`: Returns the result of `QualType::getAsString` for the type derived from `Type` (otherwise, if it is derived from `Decl`, recurses with `Node->getTypeForDecl()`)
**Matcher types** are used to mark matchers as sub-matcher with 'sub' or as deactivated using 'none'. Testing sub-matcher is not implemented.
#### `count`:
Specifying a 'count=n' on a match will result in a test that requires that the specified match will be matched n times. Default is 1.
#### `std`:
A match allows specifying if it matches only in specific language versions. This may be needed when the AST differs between language versions.
#### `sub`:
The `sub` tag on a `\match` will indicate that the match is for a node of a bound sub-matcher.
E.g., `\matcher{expr(expr().bind("inner"))}` has a sub-matcher that binds to `inner`, which is the value for the `sub` tag of the expected match for the sub-matcher `\match{sub=inner$...}`. Currently, sub-matchers are not tested in any way.
### What if ...?
#### ... I want to add a matcher?
Add a Doxygen comment to the matcher with a code example, corresponding matchers and matches, that shows what the matcher is supposed to do. Specify the compile arguments/supported languages if required, and run `ninja check-clang-unit` to test the documentation.
#### ... the example I wrote is wrong?
The test-failure output of the generated test file will provide information about
- where the generated test file is located
- which line in `ASTMatcher.h` the example is from
- which matches were: found, not-(yet)-found, expected
- in case of an unexpected match: what the node looks like using the different `type`s
- the language version and if the test ran with a windows `-target` flag (also in failure summary)
#### ... I don't adhere to the required order of the syntax?
The script will diagnose any found issues, such as `matcher is missing an example` with a `file:line:` prefix,
which should provide enough information about the issue.
#### ... the script diagnoses a false-positive issue with a Doxygen comment?
It hopefully shouldn't, but if you, e.g., added some non-matcher code and documented it with Doxygen, then the script will consider that as a matcher documentation. As a result, the script will print that it detected a mismatch between the actual and the expected number of failures. If the diagnostic truly is a false-positive, change the `expected_failure_statistics` at the top of the `generate_ast_matcher_doc_tests.py` file.
Fixes #<!-- -->57607
Fixes #<!-- -->63748
---
Patch is 906.88 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/112168.diff
8 Files Affected:
- (modified) clang/docs/LibASTMatchersReference.html (+5679-2272)
- (modified) clang/docs/ReleaseNotes.rst (+3)
- (modified) clang/docs/doxygen.cfg.in (+8-1)
- (modified) clang/docs/tools/dump_ast_matchers.py (+63-5)
- (modified) clang/include/clang/ASTMatchers/ASTMatchers.h (+4117-1664)
- (modified) clang/unittests/ASTMatchers/ASTMatchersTest.h (+427-3)
- (modified) clang/unittests/ASTMatchers/CMakeLists.txt (+15)
- (added) clang/utils/generate_ast_matcher_doc_tests.py (+1097)
``````````diff
diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html
index a16b9c44ef0eab..baf39befd796a5 100644
--- a/clang/docs/LibASTMatchersReference.html
+++ b/clang/docs/LibASTMatchersReference.html
@@ -586,28 +586,36 @@ <h2 id="decl-matchers">Node Matchers</h2>
#pragma omp declare simd
int min();
-attr()
- matches "nodiscard", "nonnull", "noinline", and the whole "#pragma" line.
+
+The matcher attr()
+matches nodiscard, nonnull, noinline, and
+declare simd.
</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.
-Examples matches public virtual B.
+Given
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.
-Examples matches i(42).
+Given
class C {
C() : i(42) {}
int i;
};
+
+The matcher cxxCtorInitializer()
+matches i(42).
</pre></td></tr>
@@ -619,17 +627,22 @@ <h2 id="decl-matchers">Node Matchers</h2>
public:
int a;
};
-accessSpecDecl()
- matches 'public:'
+
+The matcher 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()
- auto [foo, bar] = std::make_pair{42, 42};
+Given
+ struct pair { int x; int y; };
+ pair make(int, int);
+ auto [foo, bar] = make(42, 42);
+
+The matcher bindingDecl()
+matches foo and bar.
</pre></td></tr>
@@ -642,14 +655,18 @@ <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.
-Example matches Z
+Given
template<class T> class Z {};
+
+The matcher classTemplateDecl()
+matches Z.
</pre></td></tr>
@@ -660,13 +677,14 @@ <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> {};
-classTemplatePartialSpecializationDecl()
- matches the specialization A<T,T*,I> but not 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>.
</pre></td></tr>
@@ -677,87 +695,128 @@ <h2 id="decl-matchers">Node Matchers</h2>
template<typename T> class A {};
template<> class A<double> {};
A<int> a;
-classTemplateSpecializationDecl()
- matches the specializations A<int> and A<double>
+
+The matcher classTemplateSpecializationDecl()
+matches class A<int>
+and class 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.
-Example matches integral
- template<typename T>
- concept integral = std::is_integral_v<T>;
+Given
+ template<typename T> concept my_concept = true;
+
+
+The matcher conceptDecl()
+matches template<typename T>
+concept my_concept = true.
</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.
-Example matches Foo::Foo() and Foo::Foo(int)
+Given
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.
-Example matches the operator.
+Given
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.
-Example matches the deduction guide.
+Given
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.
-Example matches Foo::~Foo()
+Given
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.
-Example matches y
+Given
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.
-Example matches X, Z
+Given
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.
-Examples matches X, C, and the friend declaration inside C;
+Given
void X();
class C {
- friend X;
+ friend void X();
};
+
+The matcher decl()
+matches void X(), C
+and friend void X().
</pre></td></tr>
@@ -767,40 +826,49 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
class X { int y; };
-declaratorDecl()
- matches int y.
+
+The matcher 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.
-Examples matches the declaration node with foo and bar, but not
-number.
-(matcher = declStmt(has(decompositionDecl())))
-
+Given
+ struct pair { int x; int y; };
+ pair make(int, int);
int number = 42;
- auto [foo, bar] = std::make_pair{42, 42};
+ auto [foo, bar] = make(42, 42);
+
+The matcher decompositionDecl()
+matches auto [foo, bar] = make(42, 42),
+but does not match number.
</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.
-Example matches A, B, C
+Given
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.
-Example matches X
+Given
enum X {
A, B, C
};
+
+The matcher enumDecl()
+matches the enum X.
</pre></td></tr>
@@ -808,9 +876,14 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="fieldDecl0"><pre>Matches field declarations.
Given
- class X { int m; };
-fieldDecl()
- matches 'm'.
+ int a;
+ struct Foo {
+ int x;
+ };
+ void bar(int val);
+
+The matcher fieldDecl()
+matches int x.
</pre></td></tr>
@@ -819,16 +892,20 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
class X { friend void foo(); };
-friendDecl()
- matches 'friend void foo()'.
+
+The matcher 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.
-Example matches f
+Given
void f();
+
+The matcher functionDecl()
+matches void f().
</pre></td></tr>
@@ -837,6 +914,10 @@ <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>
@@ -845,8 +926,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
struct X { struct { int a; }; };
-indirectFieldDecl()
- matches 'a'.
+The matcher indirectFieldDecl()
+matches a.
</pre></td></tr>
@@ -854,10 +935,13 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="labelDecl0"><pre>Matches a declaration of label.
Given
- goto FOO;
- FOO: bar();
-labelDecl()
- matches 'FOO:'
+ void bar();
+ void foo() {
+ goto FOO;
+ FOO: bar();
+ }
+The matcher labelDecl()
+matches FOO: bar().
</pre></td></tr>
@@ -866,8 +950,9 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
extern "C" {}
-linkageSpecDecl()
- matches "extern "C" {}"
+
+The matcher linkageSpecDecl()
+matches extern "C" {}.
</pre></td></tr>
@@ -875,12 +960,18 @@ <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>
@@ -890,8 +981,10 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
namespace test {}
namespace alias = ::test;
-namespaceAliasDecl()
- matches "namespace alias" but not "namespace test"
+
+The matcher namespaceAliasDecl()
+matches alias,
+but does not match test.
</pre></td></tr>
@@ -901,8 +994,9 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
namespace {}
namespace test {}
-namespaceDecl()
- matches "namespace {}" and "namespace test {}"
+
+The matcher namespaceDecl()
+matches namespace {} and namespace test {}.
</pre></td></tr>
@@ -911,8 +1005,10 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
template <typename T, int N> struct C {};
-nonTypeTemplateParmDecl()
- matches 'N', but not 'T'.
+
+The matcher nonTypeTemplateParmDecl()
+matches int N,
+but does not match typename T.
</pre></td></tr>
@@ -922,6 +1018,7 @@ <h2 id="decl-matchers">Node Matchers</h2>
Example matches Foo (Additions)
@interface Foo (Additions)
@end
+
</pre></td></tr>
@@ -931,6 +1028,7 @@ <h2 id="decl-matchers">Node Matchers</h2>
Example matches Foo (Additions)
@implementation Foo (Additions)
@end
+
</pre></td></tr>
@@ -940,6 +1038,7 @@ <h2 id="decl-matchers">Node Matchers</h2>
Example matches Foo
@implementation Foo
@end
+
</pre></td></tr>
@@ -949,6 +1048,7 @@ <h2 id="decl-matchers">Node Matchers</h2>
Example matches Foo
@interface Foo
@end
+
</pre></td></tr>
@@ -960,6 +1060,7 @@ <h2 id="decl-matchers">Node Matchers</h2>
BOOL _enabled;
}
@end
+
</pre></td></tr>
@@ -974,6 +1075,7 @@ <h2 id="decl-matchers">Node Matchers</h2>
@implementation Foo
- (void)method {}
@end
+
</pre></td></tr>
@@ -984,6 +1086,7 @@ <h2 id="decl-matchers">Node Matchers</h2>
@interface Foo
@property BOOL enabled;
@end
+
</pre></td></tr>
@@ -993,6 +1096,7 @@ <h2 id="decl-matchers">Node Matchers</h2>
Example matches FooDelegate
@protocol FooDelegate
@end
+
</pre></td></tr>
@@ -1001,48 +1105,58 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
void f(int x);
-parmVarDecl()
- matches int x.
+The matcher 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.
-Example matches X, Z, U, and S
+Given
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.
-Example:
- staticAssertDecl()
-matches
- static_assert(sizeof(S) == sizeof(int))
-in
+Given
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.
-Example matches X, Z, U, S, E
+Given
class X;
template<class T> class Z {};
struct S {};
union U {};
- enum E {
- A, B, C
- };
+ 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 }.
</pre></td></tr>
@@ -1051,8 +1165,10 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
template <template <typename> class Z, int N> struct C {};
-templateTypeParmDecl()
- matches 'Z', but not 'N'.
+
+The matcher templateTemplateParmDecl()
+matches template <typename> class Z,
+but does not match int N.
</pre></td></tr>
@@ -1061,8 +1177,10 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
template <typename T, int N> struct C {};
-templateTypeParmDecl()
- matches 'T', but not 'N'.
+
+The matcher templateTypeParmDecl()
+matches typename T,
+but does not int N.
</pre></td></tr>
@@ -1072,10 +1190,12 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
int X;
namespace NS {
- int Y;
+ int Y;
} // namespace NS
-decl(hasDeclContext(translationUnitDecl()))
- matches "int X", but not "int Y".
+
+The matcher namedDecl(hasDeclContext(translationUnitDecl()))
+matches X and NS,
+but does not match Y.
</pre></td></tr>
@@ -1085,17 +1205,22 @@ <h2 id="decl-matchers">Node Matchers</h2>
Given
typedef int X;
using Y = int;
-typeAliasDecl()
- matches "using Y = int", but not "typedef int X"
+
+The matcher typeAliasDecl()
+matches using Y = int,
+but does not match 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><t...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/112168
More information about the cfe-commits
mailing list