summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeorge Karpenkov <ekarpenkov@apple.com>2018-03-29 00:51:11 +0000
committerGeorge Karpenkov <ekarpenkov@apple.com>2018-03-29 00:51:11 +0000
commit9741fa736187b2a767137076e776aae421929cee (patch)
tree16a1cb5ddcc0a117a79974d646fa37fe0e133f46
parent4654818441b2653140055e9f2726cdb30c20eecd (diff)
[ASTMatchers] Extend hasParameter and hasAnyParameter matches to handle Objective-C methods
Differential Revision: https://reviews.llvm.org/D44707 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@328746 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--docs/LibASTMatchersReference.html60
-rw-r--r--include/clang/ASTMatchers/ASTMatchers.h43
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h2
-rw-r--r--unittests/ASTMatchers/ASTMatchersTraversalTest.cpp4
-rw-r--r--unittests/ASTMatchers/Dynamic/ParserTest.cpp15
5 files changed, 104 insertions, 20 deletions
diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html
index 9c55e8214d..8e63c13888 100644
--- a/docs/LibASTMatchersReference.html
+++ b/docs/LibASTMatchersReference.html
@@ -5298,7 +5298,7 @@ matches 'int x = 0' in
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasAnyParameter0')"><a name="hasAnyParameter0Anchor">hasAnyParameter</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="hasAnyParameter0"><pre>Matches any parameter of a function declaration.
+<tr><td colspan="4" class="doc" id="hasAnyParameter0"><pre>Matches any parameter of a function or ObjC method declaration.
Does not match the 'this' parameter of a method.
@@ -5308,6 +5308,13 @@ 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
+matching y.
</pre></td></tr>
@@ -5347,7 +5354,8 @@ with compoundStmt()
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasParameter0')"><a name="hasParameter0Anchor">hasParameter</a></td><td>unsigned N, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="hasParameter0"><pre>Matches the n'th parameter of a function declaration.
+<tr><td colspan="4" class="doc" id="hasParameter0"><pre>Matches the n'th parameter of a function or an ObjC method
+declaration.
Given
class X { void f(int x) {} };
@@ -5355,6 +5363,13 @@ cxxMethodDecl(hasParameter(0, hasType(varDecl())))
matches f(int x) {}
with hasParameter(...)
matching int x
+
+For ObjectiveC, given
+ @interface I - (void) f:(int) y; @end
+
+the matcher objcMethodDecl(hasParameter(0, hasName("y")))
+matches the declaration of method f with hasParameter
+matching y.
</pre></td></tr>
@@ -5713,6 +5728,47 @@ matches the [webView ...] message invocation.
</pre></td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>&gt;</td><td class="name" onclick="toggle('hasAnyParameter1')"><a name="hasAnyParameter1Anchor">hasAnyParameter</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasAnyParameter1"><pre>Matches any parameter of a function or ObjC method declaration.
+
+Does not match the 'this' parameter of a method.
+
+Given
+ class X { void f(int x, int y, int z) {} };
+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
+matching y.
+</pre></td></tr>
+
+
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>&gt;</td><td class="name" onclick="toggle('hasParameter1')"><a name="hasParameter1Anchor">hasParameter</a></td><td>unsigned N, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasParameter1"><pre>Matches the n'th parameter of a function or an ObjC method
+declaration.
+
+Given
+ class X { void f(int x) {} };
+cxxMethodDecl(hasParameter(0, hasType(varDecl())))
+ matches f(int x) {}
+with hasParameter(...)
+ matching int x
+
+For ObjectiveC, given
+ @interface I - (void) f:(int) y; @end
+
+the matcher objcMethodDecl(hasParameter(0, hasName("y")))
+matches the declaration of method f with hasParameter
+matching y.
+</pre></td></tr>
+
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1OpaqueValueExpr.html">OpaqueValueExpr</a>&gt;</td><td class="name" onclick="toggle('hasSourceExpression1')"><a name="hasSourceExpression1Anchor">hasSourceExpression</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<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.
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index 65f1524223..b3366dd487 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -3466,7 +3466,8 @@ AST_MATCHER(CXXConstructExpr, requiresZeroInitialization) {
return Node.requiresZeroInitialization();
}
-/// \brief Matches the n'th parameter of a function declaration.
+/// \brief Matches the n'th parameter of a function or an ObjC method
+/// declaration.
///
/// Given
/// \code
@@ -3476,12 +3477,22 @@ AST_MATCHER(CXXConstructExpr, requiresZeroInitialization) {
/// matches f(int x) {}
/// with hasParameter(...)
/// matching int x
-AST_MATCHER_P2(FunctionDecl, hasParameter,
- unsigned, N, internal::Matcher<ParmVarDecl>,
- InnerMatcher) {
- return (N < Node.getNumParams() &&
- InnerMatcher.matches(
- *Node.getParamDecl(N), Finder, Builder));
+///
+/// For ObjectiveC, given
+/// \code
+/// @interface I - (void) f:(int) y; @end
+/// \endcode
+//
+/// the matcher objcMethodDecl(hasParameter(0, hasName("y")))
+/// matches the declaration of method f with hasParameter
+/// matching y.
+AST_POLYMORPHIC_MATCHER_P2(hasParameter,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
+ ObjCMethodDecl),
+ unsigned, N, internal::Matcher<ParmVarDecl>,
+ InnerMatcher) {
+ return (N < Node.parameters().size()
+ && InnerMatcher.matches(*Node.parameters()[N], Finder, Builder));
}
/// \brief Matches all arguments and their respective ParmVarDecl.
@@ -3538,7 +3549,7 @@ AST_POLYMORPHIC_MATCHER_P2(forEachArgumentWithParam,
return Matched;
}
-/// \brief Matches any parameter of a function declaration.
+/// \brief Matches any parameter of a function or ObjC method declaration.
///
/// Does not match the 'this' parameter of a method.
///
@@ -3550,8 +3561,20 @@ AST_POLYMORPHIC_MATCHER_P2(forEachArgumentWithParam,
/// matches f(int x, int y, int z) {}
/// with hasAnyParameter(...)
/// matching int y
-AST_MATCHER_P(FunctionDecl, hasAnyParameter,
- internal::Matcher<ParmVarDecl>, InnerMatcher) {
+///
+/// For ObjectiveC, given
+/// \code
+/// @interface I - (void) f:(int) y; @end
+/// \endcode
+//
+/// the matcher objcMethodDecl(hasAnyParameter(hasName("y")))
+/// matches the declaration of method f with hasParameter
+/// matching y.
+AST_POLYMORPHIC_MATCHER_P(hasAnyParameter,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
+ ObjCMethodDecl),
+ internal::Matcher<ParmVarDecl>,
+ InnerMatcher) {
return matchesFirstInPointerRange(InnerMatcher, Node.param_begin(),
Node.param_end(), Finder, Builder);
}
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
index 3169791464..7df8f373b3 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
@@ -87,7 +87,7 @@ public:
static std::unique_ptr<WorkList> makeUnexploredFirstPriorityQueue();
};
-} // end GR namespace
+} // end ento namespace
} // end clang namespace
diff --git a/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
index a5381842f4..c9c70a5f25 100644
--- a/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -539,6 +539,8 @@ TEST(HasParameter, CallsInnerMatcher) {
cxxMethodDecl(hasParameter(0, varDecl()))));
EXPECT_TRUE(notMatches("class X { void x(int) {} };",
cxxMethodDecl(hasParameter(0, hasName("x")))));
+ EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) x; @end",
+ objcMethodDecl(hasParameter(0, hasName("x")))));
}
TEST(HasParameter, DoesNotMatchIfIndexOutOfBounds) {
@@ -568,6 +570,8 @@ TEST(HasAnyParameter, MatchesIndependentlyOfPosition) {
EXPECT_TRUE(matches(
"class Y {}; class X { void x(Y y, X x) {} };",
cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
+ EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) x; @end",
+ objcMethodDecl(hasAnyParameter(hasName("x")))));
}
TEST(Returns, MatchesReturnTypes) {
diff --git a/unittests/ASTMatchers/Dynamic/ParserTest.cpp b/unittests/ASTMatchers/Dynamic/ParserTest.cpp
index 0c4c7dfd78..7224db0942 100644
--- a/unittests/ASTMatchers/Dynamic/ParserTest.cpp
+++ b/unittests/ASTMatchers/Dynamic/ParserTest.cpp
@@ -186,8 +186,8 @@ using ast_matchers::internal::Matcher;
Parser::NamedValueMap getTestNamedValues() {
Parser::NamedValueMap Values;
Values["nameX"] = llvm::StringRef("x");
- Values["hasParamA"] =
- VariantMatcher::SingleMatcher(hasParameter(0, hasName("a")));
+ Values["hasParamA"] = VariantMatcher::SingleMatcher(
+ functionDecl(hasParameter(0, hasName("a"))));
return Values;
}
@@ -329,16 +329,17 @@ TEST(ParserTest, CompletionNamedValues) {
EXPECT_LT(0u, Comps.size());
// Can complete names and registry together.
- Code = "cxxMethodDecl(hasP";
+ Code = "functionDecl(hasP";
Comps = Parser::completeExpression(Code, Code.size(), nullptr, &NamedValues);
ASSERT_EQ(3u, Comps.size());
- EXPECT_EQ("aramA", Comps[0].TypedText);
- EXPECT_EQ("Matcher<FunctionDecl> hasParamA", Comps[0].MatcherDecl);
- EXPECT_EQ("arameter(", Comps[1].TypedText);
+ EXPECT_EQ("arameter(", Comps[0].TypedText);
EXPECT_EQ(
"Matcher<FunctionDecl> hasParameter(unsigned, Matcher<ParmVarDecl>)",
- Comps[1].MatcherDecl);
+ Comps[0].MatcherDecl);
+
+ EXPECT_EQ("aramA", Comps[1].TypedText);
+ EXPECT_EQ("Matcher<Decl> hasParamA", Comps[1].MatcherDecl);
EXPECT_EQ("arent(", Comps[2].TypedText);
EXPECT_EQ(