Extend hasType narrowing matcher for TypedefDecls, add functionProtoType matcher for FunctionProtoType nodes, extend parameterCountIs to FunctionProtoType nodes.
Patch by Richard Thomson llvm-svn: 259210
This commit is contained in:
parent
565f7866ac
commit
fb9d0e354d
|
@ -1308,6 +1308,18 @@ c and d.
|
|||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td><td class="name" onclick="toggle('functionProtoType0')"><a name="functionProtoType0Anchor">functionProtoType</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionProtoType.html">FunctionProtoType</a>>...</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="functionProtoType0"><pre>Matches FunctionProtoType nodes.
|
||||
|
||||
Given
|
||||
int (*f)(int);
|
||||
void g();
|
||||
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>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td><td class="name" onclick="toggle('functionType0')"><a name="functionType0Anchor">functionType</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionType.html">FunctionType</a>>...</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="functionType0"><pre>Matches FunctionType nodes.
|
||||
|
||||
|
@ -2335,13 +2347,40 @@ compiled in C mode.
|
|||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>></td><td class="name" onclick="toggle('parameterCountIs0')"><a name="parameterCountIs0Anchor">parameterCountIs</a></td><td>unsigned N</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="parameterCountIs0"><pre>Matches FunctionDecls that have a specific parameter count.
|
||||
<tr><td colspan="4" class="doc" id="parameterCountIs0"><pre>Matches FunctionDecls and FunctionProtoTypes that have a
|
||||
specific parameter count.
|
||||
|
||||
Given
|
||||
void f(int i) {}
|
||||
void g(int i, int j) {}
|
||||
void h(int i, int j);
|
||||
void j(int i);
|
||||
void k(int x, int y, int z, ...);
|
||||
functionDecl(parameterCountIs(2))
|
||||
matches g(int i, int j) {}
|
||||
matches void g(int i, int j) {}
|
||||
functionProtoType(parameterCountIs(2))
|
||||
matches void h(int i, int j)
|
||||
functionProtoType(parameterCountIs(3))
|
||||
matches void k(int x, int y, int z, ...);
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionProtoType.html">FunctionProtoType</a>></td><td class="name" onclick="toggle('parameterCountIs1')"><a name="parameterCountIs1Anchor">parameterCountIs</a></td><td>unsigned N</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="parameterCountIs1"><pre>Matches FunctionDecls and FunctionProtoTypes that have a
|
||||
specific parameter count.
|
||||
|
||||
Given
|
||||
void f(int i) {}
|
||||
void g(int i, int j) {}
|
||||
void h(int i, int j);
|
||||
void j(int i);
|
||||
void k(int x, int y, int z, ...);
|
||||
functionDecl(parameterCountIs(2))
|
||||
matches void g(int i, int j) {}
|
||||
functionProtoType(parameterCountIs(2))
|
||||
matches void h(int i, int j)
|
||||
functionProtoType(parameterCountIs(3))
|
||||
matches void k(int x, int y, int z, ...);
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
|
@ -3995,8 +4034,8 @@ actual casts "explicit" casts.)
|
|||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>></td><td class="name" onclick="toggle('hasType2')"><a name="hasType2Anchor">hasType</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasType2"><pre>Overloaded to match the declaration of the expression's or value
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>></td><td class="name" onclick="toggle('hasType3')"><a name="hasType3Anchor">hasType</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasType3"><pre>Overloaded to match the declaration of the expression's or value
|
||||
declaration's type.
|
||||
|
||||
In case of a value declaration (for example a variable declaration),
|
||||
|
@ -4020,8 +4059,10 @@ matcher.
|
|||
|
||||
Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
|
||||
and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
|
||||
and U (matcher = typedefDecl(hasType(asString("int")))
|
||||
class X {};
|
||||
void y(X &x) { x; X z; }
|
||||
typedef int U;
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
|
@ -4796,6 +4837,19 @@ Usable as: Any Matcher
|
|||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefDecl.html">TypedefDecl</a>></td><td class="name" onclick="toggle('hasType1')"><a name="hasType1Anchor">hasType</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>> InnerMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasType1"><pre>Matches if the expression's or declaration's type matches a type
|
||||
matcher.
|
||||
|
||||
Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
|
||||
and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
|
||||
and U (matcher = typedefDecl(hasType(asString("int")))
|
||||
class X {};
|
||||
void y(X &x) { x; X z; }
|
||||
typedef int U;
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://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="http://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.
|
||||
|
@ -4881,8 +4935,8 @@ usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(functionDecl())))
|
|||
matches using X::b but not using X::a </pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>></td><td class="name" onclick="toggle('hasType3')"><a name="hasType3Anchor">hasType</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasType3"><pre>Overloaded to match the declaration of the expression's or value
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>></td><td class="name" onclick="toggle('hasType4')"><a name="hasType4Anchor">hasType</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasType4"><pre>Overloaded to match the declaration of the expression's or value
|
||||
declaration's type.
|
||||
|
||||
In case of a value declaration (for example a variable declaration),
|
||||
|
@ -4900,14 +4954,16 @@ Usable as: Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.
|
|||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>></td><td class="name" onclick="toggle('hasType1')"><a name="hasType1Anchor">hasType</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>> InnerMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasType1"><pre>Matches if the expression's or declaration's type matches a type
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>></td><td class="name" onclick="toggle('hasType2')"><a name="hasType2Anchor">hasType</a></td><td>Matcher<<a href="http://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.
|
||||
|
||||
Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
|
||||
and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
|
||||
and U (matcher = typedefDecl(hasType(asString("int")))
|
||||
class X {};
|
||||
void y(X &x) { x; X z; }
|
||||
typedef int U;
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
|
|
|
@ -2298,14 +2298,17 @@ AST_MATCHER_P_OVERLOAD(CallExpr, callee, internal::Matcher<Decl>, InnerMatcher,
|
|||
///
|
||||
/// Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
|
||||
/// and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
|
||||
/// and U (matcher = typedefDecl(hasType(asString("int")))
|
||||
/// \code
|
||||
/// class X {};
|
||||
/// void y(X &x) { x; X z; }
|
||||
/// typedef int U;
|
||||
/// \endcode
|
||||
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
|
||||
hasType, AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, ValueDecl),
|
||||
hasType, AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, TypedefDecl, ValueDecl),
|
||||
internal::Matcher<QualType>, InnerMatcher, 0) {
|
||||
return InnerMatcher.matches(Node.getType(), Finder, Builder);
|
||||
return InnerMatcher.matches(internal::getUnderlyingType<NodeType>(Node),
|
||||
Finder, Builder);
|
||||
}
|
||||
|
||||
/// \brief Overloaded to match the declaration of the expression's or value
|
||||
|
@ -2951,16 +2954,27 @@ AST_MATCHER_P(FunctionDecl, hasAnyParameter,
|
|||
Node.param_end(), Finder, Builder);
|
||||
}
|
||||
|
||||
/// \brief Matches \c FunctionDecls that have a specific parameter count.
|
||||
/// \brief Matches \c FunctionDecls and \c FunctionProtoTypes that have a
|
||||
/// specific parameter count.
|
||||
///
|
||||
/// Given
|
||||
/// \code
|
||||
/// void f(int i) {}
|
||||
/// void g(int i, int j) {}
|
||||
/// void h(int i, int j);
|
||||
/// void j(int i);
|
||||
/// void k(int x, int y, int z, ...);
|
||||
/// \endcode
|
||||
/// functionDecl(parameterCountIs(2))
|
||||
/// matches g(int i, int j) {}
|
||||
AST_MATCHER_P(FunctionDecl, parameterCountIs, unsigned, N) {
|
||||
/// matches void g(int i, int j) {}
|
||||
/// functionProtoType(parameterCountIs(2))
|
||||
/// matches void h(int i, int j)
|
||||
/// functionProtoType(parameterCountIs(3))
|
||||
/// matches void k(int x, int y, int z, ...);
|
||||
AST_POLYMORPHIC_MATCHER_P(parameterCountIs,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
|
||||
FunctionProtoType),
|
||||
unsigned, N) {
|
||||
return Node.getNumParams() == N;
|
||||
}
|
||||
|
||||
|
@ -4099,6 +4113,18 @@ AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType,
|
|||
/// matches "int (*f)(int)" and the type of "g".
|
||||
AST_TYPE_MATCHER(FunctionType, functionType);
|
||||
|
||||
/// \brief Matches \c FunctionProtoType nodes.
|
||||
///
|
||||
/// Given
|
||||
/// \code
|
||||
/// int (*f)(int);
|
||||
/// void g();
|
||||
/// \endcode
|
||||
/// 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.
|
||||
AST_TYPE_MATCHER(FunctionProtoType, functionProtoType);
|
||||
|
||||
/// \brief Matches \c ParenType nodes.
|
||||
///
|
||||
/// Given
|
||||
|
|
|
@ -60,6 +60,17 @@ class BoundNodes;
|
|||
|
||||
namespace internal {
|
||||
|
||||
/// \brief Unifies obtaining the underlying type of a regular node through
|
||||
/// `getType` and a TypedefNameDecl node through `getUnderlyingType`.
|
||||
template <typename NodeType>
|
||||
inline QualType getUnderlyingType(const NodeType &Node) {
|
||||
return Node.getType();
|
||||
}
|
||||
|
||||
template <> inline QualType getUnderlyingType(const TypedefDecl &Node) {
|
||||
return Node.getUnderlyingType();
|
||||
}
|
||||
|
||||
/// \brief Internal version of BoundNodes. Holds all the bound nodes.
|
||||
class BoundNodesMap {
|
||||
public:
|
||||
|
|
|
@ -182,6 +182,7 @@ RegistryMaps::RegistryMaps() {
|
|||
REGISTER_MATCHER(forStmt);
|
||||
REGISTER_MATCHER(friendDecl);
|
||||
REGISTER_MATCHER(functionDecl);
|
||||
REGISTER_MATCHER(functionProtoType);
|
||||
REGISTER_MATCHER(functionTemplateDecl);
|
||||
REGISTER_MATCHER(functionType);
|
||||
REGISTER_MATCHER(gotoStmt);
|
||||
|
|
|
@ -1091,6 +1091,16 @@ TEST(HasType, TakesDeclMatcherAndMatchesValueDecl) {
|
|||
notMatches("class X {}; void y() { X *x; }", varDecl(hasType(ClassX))));
|
||||
}
|
||||
|
||||
TEST(HasType, MatchesTypedefDecl) {
|
||||
EXPECT_TRUE(matches("typedef int X;", typedefDecl(hasType(asString("int")))));
|
||||
EXPECT_TRUE(matches("typedef const int T;",
|
||||
typedefDecl(hasType(asString("const int")))));
|
||||
EXPECT_TRUE(notMatches("typedef const int T;",
|
||||
typedefDecl(hasType(asString("int")))));
|
||||
EXPECT_TRUE(matches("typedef int foo; typedef foo bar;",
|
||||
typedefDecl(hasType(asString("foo")), hasName("bar"))));
|
||||
}
|
||||
|
||||
TEST(HasTypeLoc, MatchesDeclaratorDecls) {
|
||||
EXPECT_TRUE(matches("int x;",
|
||||
varDecl(hasName("x"), hasTypeLoc(loc(asString("int"))))));
|
||||
|
@ -1563,6 +1573,9 @@ TEST(Function, MatchesFunctionDeclarations) {
|
|||
functionDecl(isVariadic())));
|
||||
EXPECT_TRUE(notMatches("void f();", functionDecl(isVariadic())));
|
||||
EXPECT_TRUE(notMatchesC("void f();", functionDecl(isVariadic())));
|
||||
EXPECT_TRUE(matches("void f(...);", functionDecl(parameterCountIs(0))));
|
||||
EXPECT_TRUE(matchesC("void f();", functionDecl(parameterCountIs(0))));
|
||||
EXPECT_TRUE(matches("void f(int, ...);", functionDecl(parameterCountIs(1))));
|
||||
}
|
||||
|
||||
TEST(FunctionTemplate, MatchesFunctionTemplateDeclarations) {
|
||||
|
@ -1719,6 +1732,7 @@ TEST(Matcher, ParameterCount) {
|
|||
EXPECT_TRUE(matches("class X { void f(int i) {} };", Function1Arg));
|
||||
EXPECT_TRUE(notMatches("void f() {}", Function1Arg));
|
||||
EXPECT_TRUE(notMatches("void f(int i, int j, int k) {}", Function1Arg));
|
||||
EXPECT_TRUE(matches("void f(int i, ...) {};", Function1Arg));
|
||||
}
|
||||
|
||||
TEST(Matcher, References) {
|
||||
|
@ -4447,6 +4461,15 @@ TEST(TypeMatching, MatchesFunctionTypes) {
|
|||
EXPECT_TRUE(matches("void f(int i) {}", functionType()));
|
||||
}
|
||||
|
||||
TEST(TypeMatching, MatchesFunctionProtoTypes) {
|
||||
EXPECT_TRUE(matches("int (*f)(int);", functionProtoType()));
|
||||
EXPECT_TRUE(matches("void f(int i);", functionProtoType()));
|
||||
EXPECT_TRUE(matches("void f();", functionProtoType(parameterCountIs(0))));
|
||||
EXPECT_TRUE(notMatchesC("void f();", functionProtoType()));
|
||||
EXPECT_TRUE(
|
||||
matchesC("void f(void);", functionProtoType(parameterCountIs(0))));
|
||||
}
|
||||
|
||||
TEST(TypeMatching, MatchesParenType) {
|
||||
EXPECT_TRUE(
|
||||
matches("int (*array)[4];", varDecl(hasType(pointsTo(parenType())))));
|
||||
|
@ -5148,7 +5171,8 @@ TEST(IsInlineMatcher, IsInline) {
|
|||
namespaceDecl(isInline(), hasName("m"))));
|
||||
}
|
||||
|
||||
// FIXME: Figure out how to specify paths so the following tests pass on Windows.
|
||||
// FIXME: Figure out how to specify paths so the following tests pass on
|
||||
// Windows.
|
||||
#ifndef LLVM_ON_WIN32
|
||||
|
||||
TEST(Matcher, IsExpansionInMainFileMatcher) {
|
||||
|
|
Loading…
Reference in New Issue