diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/docs/LibASTMatchersReference.html | 131 | ||||
-rw-r--r-- | clang/include/clang/ASTMatchers/ASTMatchers.h | 29 | ||||
-rw-r--r-- | clang/lib/ASTMatchers/Dynamic/Registry.cpp | 1 | ||||
-rw-r--r-- | clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp | 29 |
4 files changed, 173 insertions, 17 deletions
diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index 97c75277c27..338399976f4 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -3009,6 +3009,23 @@ expr(isValueDependent()) matches return Size </pre></td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>></td><td class="name" onclick="toggle('nullPointerConstant0')"><a name="nullPointerConstant0Anchor">nullPointerConstant</a></td><td></td></tr> +<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: + void *v1 = NULL; + void *v2 = nullptr; + void *v3 = __null; // GNU extension + char *cp = (char *)0; + int *ip = 0; + int i = 0; +expr(nullPointerConstant()) + matches the initializer for v1, v2, v3, cp, and ip. Does not match the + initializer for i. +</pre></td></tr> + + <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FieldDecl.html">FieldDecl</a>></td><td class="name" onclick="toggle('hasBitWidth0')"><a name="hasBitWidth0Anchor">hasBitWidth</a></td><td>unsigned Width</td></tr> <tr><td colspan="4" class="doc" id="hasBitWidth0"><pre>Matches non-static data members that are bit-fields of the specified bit width. @@ -3761,6 +3778,18 @@ but not 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: + +void x(int val = 7) {} +void y(int val = 42) {} +parmVarDecl(hasInitializer(integerLiteral(equals(42)))) + matches the parameter of y + +A matcher such as + parmVarDecl(hasInitializer(anything())) +is equivalent to parmVarDecl(hasDefaultArgument()). </pre></td></tr> @@ -4479,23 +4508,6 @@ functionDecl(isInstantiated()) </pre></td></tr> -<tr><td>Matcher<internal::Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>>></td><td class="name" onclick="toggle('nullPointerConstant0')"><a name="nullPointerConstant0Anchor">nullPointerConstant</a></td><td></td></tr> -<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: - void *v1 = NULL; - void *v2 = nullptr; - void *v3 = __null; // GNU extension - char *cp = (char *)0; - int *ip = 0; - int i = 0; -expr(nullPointerConstant()) - matches the initializer for v1, v2, v3, cp, and ip. Does not match the - initializer for i. -</pre></td></tr> - - <tr><td>Matcher<internal::Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>>></td><td class="name" onclick="toggle('hasAnyName0')"><a name="hasAnyName0Anchor">hasAnyName</a></td><td>StringRef, ..., StringRef</td></tr> <tr><td colspan="4" class="doc" id="hasAnyName0"><pre>Matches NamedDecl nodes that have any of the specified names. @@ -5082,6 +5094,29 @@ with compoundStmt() </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: + void foo() { + if (int i = foobar(); i > 0) {} + switch (int i = foobar(); i) {} + for (auto& a = get_range(); auto& x : a) {} + } + void bar() { + if (foobar() > 0) {} + switch (foobar()) {} + for (auto& x : get_range()) {} + } +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. @@ -6206,6 +6241,29 @@ Examples matches the if statement </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: + void foo() { + if (int i = foobar(); i > 0) {} + switch (int i = foobar(); i) {} + for (auto& a = get_range(); auto& x : a) {} + } + void bar() { + if (foobar() > 0) {} + switch (foobar()) {} + for (auto& x : get_range()) {} + } +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. @@ -6943,6 +7001,29 @@ Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(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: + void foo() { + if (int i = foobar(); i > 0) {} + switch (int i = foobar(); i) {} + for (auto& a = get_range(); auto& x : a) {} + } + void bar() { + if (foobar() > 0) {} + switch (foobar()) {} + for (auto& x : get_range()) {} + } +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>const 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. @@ -7170,6 +7251,22 @@ Usable as: Any Matcher </pre></td></tr> +<tr><td>Matcher<T></td><td class="name" onclick="toggle('traverse0')"><a name="traverse0Anchor">traverse</a></td><td>ast_type_traits::TraversalKind TK, const Matcher<T> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="traverse0"><pre>Causes all nested matchers to be matched with the specified traversal kind. + +Given + void foo() + { + int i = 3.0; + } +The matcher + traverse(ast_type_traits::TK_IgnoreImplicitCastsAndParentheses, + varDecl(hasInitializer(floatLiteral().bind("init"))) + ) +matches the variable declaration with "init" bound to the "3.0". +</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('hasType2')"><a name="hasType2Anchor">hasType</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="hasType2"><pre>Matches if the expression's or declaration's type matches a type matcher. diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index 2a5f0cf6fa9..7db5f7a5de8 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -4343,6 +4343,35 @@ AST_POLYMORPHIC_MATCHER(isConstexpr, return Node.isConstexpr(); } +/// Matches selection statements with initializer. +/// +/// Given: +/// \code +/// void foo() { +/// if (int i = foobar(); i > 0) {} +/// switch (int i = foobar(); i) {} +/// for (auto& a = get_range(); auto& x : a) {} +/// } +/// void bar() { +/// if (foobar() > 0) {} +/// switch (foobar()) {} +/// for (auto& x : get_range()) {} +/// } +/// \endcode +/// 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), + internal::Matcher<Stmt>, InnerMatcher) { + const Stmt *Init = Node.getInit(); + return Init != nullptr && InnerMatcher.matches(*Init, Finder, Builder); +} + /// Matches the condition expression of an if statement, for loop, /// switch statement or conditional operator. /// diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp index 8c11e069cb0..89722489fe2 100644 --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -279,6 +279,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasIndex); REGISTER_MATCHER(hasInit); REGISTER_MATCHER(hasInitializer); + REGISTER_MATCHER(hasInitStatement); REGISTER_MATCHER(hasKeywordSelector); REGISTER_MATCHER(hasLHS); REGISTER_MATCHER(hasLocalQualifiers); diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp index 342897fd56a..e7f9232e968 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -1071,6 +1071,35 @@ TEST(isConstexpr, MatchesConstexprDeclarations) { LanguageMode::Cxx17OrLater)); } +TEST(hasInitStatement, MatchesSelectionInitializers) { + EXPECT_TRUE(matches("void baz() { if (int i = 1; i > 0) {} }", + ifStmt(hasInitStatement(anything())), + LanguageMode::Cxx17OrLater)); + EXPECT_TRUE(notMatches("void baz() { if (int i = 1) {} }", + ifStmt(hasInitStatement(anything())))); + EXPECT_TRUE(notMatches("void baz() { if (1 > 0) {} }", + ifStmt(hasInitStatement(anything())))); + EXPECT_TRUE(matches( + "void baz(int i) { switch (int j = i; j) { default: break; } }", + switchStmt(hasInitStatement(anything())), LanguageMode::Cxx17OrLater)); + EXPECT_TRUE(notMatches("void baz(int i) { switch (i) { default: break; } }", + switchStmt(hasInitStatement(anything())))); +} + +TEST(hasInitStatement, MatchesRangeForInitializers) { + EXPECT_TRUE(matches("void baz() {" + "int items[] = {};" + "for (auto &arr = items; auto &item : arr) {}" + "}", + cxxForRangeStmt(hasInitStatement(anything())), + LanguageMode::Cxx2aOrLater)); + EXPECT_TRUE(notMatches("void baz() {" + "int items[] = {};" + "for (auto &item : items) {}" + "}", + cxxForRangeStmt(hasInitStatement(anything())))); +} + TEST(TemplateArgumentCountIs, Matches) { EXPECT_TRUE( matches("template<typename T> struct C {}; C<int> c;", |