forked from OSchip/llvm-project
Revert "[ASTMatchers] extract public matchers from const-analysis into own patch"
This reverts commit 4c48ea68e4
.
The powerpc buildbots had an internal compiler error after this patch.
This requires some inspection.
This commit is contained in:
parent
4c48ea68e4
commit
23a799adf0
|
@ -635,30 +635,6 @@ Example matches a
|
|||
</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('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())))
|
||||
|
||||
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_1DecompositionDecl.html">DecompositionDecl</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())))
|
||||
|
||||
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_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.
|
||||
</pre></td></tr>
|
||||
|
@ -4993,60 +4969,6 @@ and parmVarDecl(...)
|
|||
</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('forEachArgumentWithParamType1')"><a name="forEachArgumentWithParamType1Anchor">forEachArgumentWithParamType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> ArgMatcher, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>> ParamMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="forEachArgumentWithParamType1"><pre>Matches all arguments and their respective types for a CallExpr or
|
||||
CXXConstructExpr. It is very similar to forEachArgumentWithParam but
|
||||
it works on calls through function pointers as well.
|
||||
|
||||
The difference is, that function pointers do not provide access to a
|
||||
ParmVarDecl, but only the QualType for each argument.
|
||||
|
||||
Given
|
||||
void f(int i);
|
||||
int y;
|
||||
f(y);
|
||||
void (*f_ptr)(int) = f;
|
||||
f_ptr(y);
|
||||
callExpr(
|
||||
forEachArgumentWithParamType(
|
||||
declRefExpr(to(varDecl(hasName("y")))),
|
||||
qualType(isInteger()).bind("type)
|
||||
))
|
||||
matches f(y) and f_ptr(y)
|
||||
with declRefExpr(...)
|
||||
matching int y
|
||||
and qualType(...)
|
||||
matching int
|
||||
</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('forEachArgumentWithParamType1')"><a name="forEachArgumentWithParamType1Anchor">forEachArgumentWithParamType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> ArgMatcher, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>> ParamMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="forEachArgumentWithParamType1"><pre>Matches all arguments and their respective types for a CallExpr or
|
||||
CXXConstructExpr. It is very similar to forEachArgumentWithParam but
|
||||
it works on calls through function pointers as well.
|
||||
|
||||
The difference is, that function pointers do not provide access to a
|
||||
ParmVarDecl, but only the QualType for each argument.
|
||||
|
||||
Given
|
||||
void f(int i);
|
||||
int y;
|
||||
f(y);
|
||||
void (*f_ptr)(int) = f;
|
||||
f_ptr(y);
|
||||
callExpr(
|
||||
forEachArgumentWithParamType(
|
||||
declRefExpr(to(varDecl(hasName("y")))),
|
||||
qualType(isInteger()).bind("type)
|
||||
))
|
||||
matches f(y) and f_ptr(y)
|
||||
with declRefExpr(...)
|
||||
matching int y
|
||||
and qualType(...)
|
||||
matching int
|
||||
</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('hasAnyArgument1')"><a name="hasAnyArgument1Anchor">hasAnyArgument</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="hasAnyArgument1"><pre>Matches any argument of a call expression or a constructor call
|
||||
expression, or an ObjC-message-send expression.
|
||||
|
@ -5525,60 +5447,6 @@ and parmVarDecl(...)
|
|||
</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('forEachArgumentWithParamType0')"><a name="forEachArgumentWithParamType0Anchor">forEachArgumentWithParamType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> ArgMatcher, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>> ParamMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="forEachArgumentWithParamType0"><pre>Matches all arguments and their respective types for a CallExpr or
|
||||
CXXConstructExpr. It is very similar to forEachArgumentWithParam but
|
||||
it works on calls through function pointers as well.
|
||||
|
||||
The difference is, that function pointers do not provide access to a
|
||||
ParmVarDecl, but only the QualType for each argument.
|
||||
|
||||
Given
|
||||
void f(int i);
|
||||
int y;
|
||||
f(y);
|
||||
void (*f_ptr)(int) = f;
|
||||
f_ptr(y);
|
||||
callExpr(
|
||||
forEachArgumentWithParamType(
|
||||
declRefExpr(to(varDecl(hasName("y")))),
|
||||
qualType(isInteger()).bind("type)
|
||||
))
|
||||
matches f(y) and f_ptr(y)
|
||||
with declRefExpr(...)
|
||||
matching int y
|
||||
and qualType(...)
|
||||
matching int
|
||||
</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('forEachArgumentWithParamType0')"><a name="forEachArgumentWithParamType0Anchor">forEachArgumentWithParamType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> ArgMatcher, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>> ParamMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="forEachArgumentWithParamType0"><pre>Matches all arguments and their respective types for a CallExpr or
|
||||
CXXConstructExpr. It is very similar to forEachArgumentWithParam but
|
||||
it works on calls through function pointers as well.
|
||||
|
||||
The difference is, that function pointers do not provide access to a
|
||||
ParmVarDecl, but only the QualType for each argument.
|
||||
|
||||
Given
|
||||
void f(int i);
|
||||
int y;
|
||||
f(y);
|
||||
void (*f_ptr)(int) = f;
|
||||
f_ptr(y);
|
||||
callExpr(
|
||||
forEachArgumentWithParamType(
|
||||
declRefExpr(to(varDecl(hasName("y")))),
|
||||
qualType(isInteger()).bind("type)
|
||||
))
|
||||
matches f(y) and f_ptr(y)
|
||||
with declRefExpr(...)
|
||||
matching int y
|
||||
and qualType(...)
|
||||
matching int
|
||||
</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('hasAnyArgument0')"><a name="hasAnyArgument0Anchor">hasAnyArgument</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="hasAnyArgument0"><pre>Matches any argument of a call expression or a constructor call
|
||||
expression, or an ObjC-message-send expression.
|
||||
|
|
|
@ -310,18 +310,6 @@ AST_POLYMORPHIC_MATCHER_P(isExpansionInFileMatching,
|
|||
/// \endcode
|
||||
extern const internal::VariadicAllOfMatcher<Decl> decl;
|
||||
|
||||
/// Matches decomposition-declarations.
|
||||
///
|
||||
/// Examples matches the declaration node with \c foo and \c bar, but not
|
||||
/// \c number.
|
||||
/// (matcher = declStmt(has(decompositionDecl())))
|
||||
///
|
||||
/// \code
|
||||
/// int number = 42;
|
||||
/// auto [foo, bar] = std::make_pair{42, 42};
|
||||
/// \endcode
|
||||
extern const internal::VariadicAllOfMatcher<DecompositionDecl> decompositionDecl;
|
||||
|
||||
/// Matches a declaration of a linkage specification.
|
||||
///
|
||||
/// Given
|
||||
|
@ -4206,104 +4194,6 @@ AST_POLYMORPHIC_MATCHER_P2(forEachArgumentWithParam,
|
|||
return Matched;
|
||||
}
|
||||
|
||||
/// Matches all arguments and their respective types for a \c CallExpr or
|
||||
/// \c CXXConstructExpr. It is very similar to \c forEachArgumentWithParam but
|
||||
/// it works on calls through function pointers as well.
|
||||
///
|
||||
/// The difference is, that function pointers do not provide access to a
|
||||
/// \c ParmVarDecl, but only the \c QualType for each argument.
|
||||
///
|
||||
/// Given
|
||||
/// \code
|
||||
/// void f(int i);
|
||||
/// int y;
|
||||
/// f(y);
|
||||
/// void (*f_ptr)(int) = f;
|
||||
/// f_ptr(y);
|
||||
/// \endcode
|
||||
/// callExpr(
|
||||
/// forEachArgumentWithParamType(
|
||||
/// declRefExpr(to(varDecl(hasName("y")))),
|
||||
/// qualType(isInteger()).bind("type)
|
||||
/// ))
|
||||
/// matches f(y) and f_ptr(y)
|
||||
/// with declRefExpr(...)
|
||||
/// matching int y
|
||||
/// and qualType(...)
|
||||
/// matching int
|
||||
AST_POLYMORPHIC_MATCHER_P2(forEachArgumentWithParamType,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(CallExpr,
|
||||
CXXConstructExpr),
|
||||
internal::Matcher<Expr>, ArgMatcher,
|
||||
internal::Matcher<QualType>, ParamMatcher) {
|
||||
BoundNodesTreeBuilder Result;
|
||||
// The first argument of an overloaded member operator is the implicit object
|
||||
// argument of the method which should not be matched against a parameter, so
|
||||
// we skip over it here.
|
||||
BoundNodesTreeBuilder Matches;
|
||||
unsigned ArgIndex = cxxOperatorCallExpr(callee(cxxMethodDecl()))
|
||||
.matches(Node, Finder, &Matches)
|
||||
? 1
|
||||
: 0;
|
||||
|
||||
const FunctionProtoType *FProto = nullptr;
|
||||
|
||||
if (const auto *Call = dyn_cast<CallExpr>(&Node)) {
|
||||
if (const auto *Value =
|
||||
dyn_cast_or_null<ValueDecl>(Call->getCalleeDecl())) {
|
||||
QualType QT = Value->getType().getCanonicalType();
|
||||
|
||||
// This does not necessarily lead to a `FunctionProtoType`,
|
||||
// e.g. K&R functions do not have a function prototype.
|
||||
if (QT->isFunctionPointerType())
|
||||
FProto = QT->getPointeeType()->getAs<FunctionProtoType>();
|
||||
|
||||
if (QT->isMemberFunctionPointerType()) {
|
||||
const auto *MP = QT->getAs<MemberPointerType>();
|
||||
assert(MP &&
|
||||
"Must be member-pointer if its a memberfunctionpointer");
|
||||
FProto = MP->getPointeeType()->getAs<FunctionProtoType>();
|
||||
assert(FProto &&
|
||||
"The call must have happened through a member function "
|
||||
"pointer");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ParamIndex = 0;
|
||||
bool Matched = false;
|
||||
|
||||
for (; ArgIndex < Node.getNumArgs(); ++ArgIndex, ++ParamIndex) {
|
||||
BoundNodesTreeBuilder ArgMatches(*Builder);
|
||||
if (ArgMatcher.matches(*(Node.getArg(ArgIndex)->IgnoreParenCasts()),
|
||||
Finder, &ArgMatches)) {
|
||||
BoundNodesTreeBuilder ParamMatches(ArgMatches);
|
||||
|
||||
// This test is cheaper compared to the big matcher in the next if.
|
||||
// Therefore, please keep this order.
|
||||
if (FProto) {
|
||||
QualType ParamType = FProto->getParamType(ParamIndex);
|
||||
if (ParamMatcher.matches(ParamType, Finder, &ParamMatches)) {
|
||||
Result.addMatch(ParamMatches);
|
||||
Matched = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (expr(anyOf(cxxConstructExpr(hasDeclaration(cxxConstructorDecl(
|
||||
hasParameter(ParamIndex, hasType(ParamMatcher))))),
|
||||
callExpr(callee(functionDecl(
|
||||
hasParameter(ParamIndex, hasType(ParamMatcher)))))))
|
||||
.matches(Node, Finder, &ParamMatches)) {
|
||||
Result.addMatch(ParamMatches);
|
||||
Matched = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
*Builder = std::move(Result);
|
||||
return Matched;
|
||||
}
|
||||
|
||||
/// Matches any parameter of a function or an ObjC method declaration or a
|
||||
/// block.
|
||||
///
|
||||
|
|
|
@ -196,7 +196,6 @@ RegistryMaps::RegistryMaps() {
|
|||
REGISTER_MATCHER(cxxUnresolvedConstructExpr);
|
||||
REGISTER_MATCHER(decayedType);
|
||||
REGISTER_MATCHER(decl);
|
||||
REGISTER_MATCHER(decompositionDecl);
|
||||
REGISTER_MATCHER(declCountIs);
|
||||
REGISTER_MATCHER(declRefExpr);
|
||||
REGISTER_MATCHER(declStmt);
|
||||
|
@ -221,7 +220,6 @@ RegistryMaps::RegistryMaps() {
|
|||
REGISTER_MATCHER(floatLiteral);
|
||||
REGISTER_MATCHER(forEach);
|
||||
REGISTER_MATCHER(forEachArgumentWithParam);
|
||||
REGISTER_MATCHER(forEachArgumentWithParamType);
|
||||
REGISTER_MATCHER(forEachConstructorInitializer);
|
||||
REGISTER_MATCHER(forEachDescendant);
|
||||
REGISTER_MATCHER(forEachOverridden);
|
||||
|
|
|
@ -735,172 +735,6 @@ TEST(ForEachArgumentWithParam, HandlesBoundNodesForNonMatches) {
|
|||
std::make_unique<VerifyIdIsBoundTo<VarDecl>>("v", 4)));
|
||||
}
|
||||
|
||||
TEST(ForEachArgumentWithParamType, ReportsNoFalsePositives) {
|
||||
StatementMatcher ArgumentY =
|
||||
declRefExpr(to(varDecl(hasName("y")))).bind("arg");
|
||||
TypeMatcher IntType = qualType(isInteger()).bind("type");
|
||||
StatementMatcher CallExpr =
|
||||
callExpr(forEachArgumentWithParamType(ArgumentY, IntType));
|
||||
|
||||
// IntParam does not match.
|
||||
EXPECT_TRUE(notMatches("void f(int* i) { int* y; f(y); }", CallExpr));
|
||||
// ArgumentY does not match.
|
||||
EXPECT_TRUE(notMatches("void f(int i) { int x; f(x); }", CallExpr));
|
||||
}
|
||||
|
||||
TEST(ForEachArgumentWithParamType, MatchesCXXMemberCallExpr) {
|
||||
StatementMatcher ArgumentY =
|
||||
declRefExpr(to(varDecl(hasName("y")))).bind("arg");
|
||||
TypeMatcher IntType = qualType(isInteger()).bind("type");
|
||||
StatementMatcher CallExpr =
|
||||
callExpr(forEachArgumentWithParamType(ArgumentY, IntType));
|
||||
EXPECT_TRUE(matchAndVerifyResultTrue(
|
||||
"struct S {"
|
||||
" const S& operator[](int i) { return *this; }"
|
||||
"};"
|
||||
"void f(S S1) {"
|
||||
" int y = 1;"
|
||||
" S1[y];"
|
||||
"}",
|
||||
CallExpr, std::make_unique<VerifyIdIsBoundTo<QualType>>("type", 1)));
|
||||
|
||||
StatementMatcher CallExpr2 =
|
||||
callExpr(forEachArgumentWithParamType(ArgumentY, IntType));
|
||||
EXPECT_TRUE(matchAndVerifyResultTrue(
|
||||
"struct S {"
|
||||
" static void g(int i);"
|
||||
"};"
|
||||
"void f() {"
|
||||
" int y = 1;"
|
||||
" S::g(y);"
|
||||
"}",
|
||||
CallExpr2, std::make_unique<VerifyIdIsBoundTo<QualType>>("type", 1)));
|
||||
}
|
||||
|
||||
TEST(ForEachArgumentWithParamType, MatchesCallExpr) {
|
||||
StatementMatcher ArgumentY =
|
||||
declRefExpr(to(varDecl(hasName("y")))).bind("arg");
|
||||
TypeMatcher IntType = qualType(isInteger()).bind("type");
|
||||
StatementMatcher CallExpr =
|
||||
callExpr(forEachArgumentWithParamType(ArgumentY, IntType));
|
||||
|
||||
EXPECT_TRUE(
|
||||
matchAndVerifyResultTrue("void f(int i) { int y; f(y); }", CallExpr,
|
||||
std::make_unique<VerifyIdIsBoundTo<QualType>>(
|
||||
"type")));
|
||||
EXPECT_TRUE(
|
||||
matchAndVerifyResultTrue("void f(int i) { int y; f(y); }", CallExpr,
|
||||
std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>(
|
||||
"arg")));
|
||||
|
||||
EXPECT_TRUE(matchAndVerifyResultTrue(
|
||||
"void f(int i, int j) { int y; f(y, y); }", CallExpr,
|
||||
std::make_unique<VerifyIdIsBoundTo<QualType>>("type", 2)));
|
||||
EXPECT_TRUE(matchAndVerifyResultTrue(
|
||||
"void f(int i, int j) { int y; f(y, y); }", CallExpr,
|
||||
std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg", 2)));
|
||||
}
|
||||
|
||||
TEST(ForEachArgumentWithParamType, MatchesConstructExpr) {
|
||||
StatementMatcher ArgumentY =
|
||||
declRefExpr(to(varDecl(hasName("y")))).bind("arg");
|
||||
TypeMatcher IntType = qualType(isInteger()).bind("type");
|
||||
StatementMatcher ConstructExpr =
|
||||
cxxConstructExpr(forEachArgumentWithParamType(ArgumentY, IntType));
|
||||
|
||||
EXPECT_TRUE(matchAndVerifyResultTrue(
|
||||
"struct C {"
|
||||
" C(int i) {}"
|
||||
"};"
|
||||
"int y = 0;"
|
||||
"C Obj(y);",
|
||||
ConstructExpr,
|
||||
std::make_unique<VerifyIdIsBoundTo<QualType>>("type")));
|
||||
EXPECT_TRUE(matchAndVerifyResultTrue(
|
||||
"struct C {"
|
||||
" C(int i) {}"
|
||||
"};"
|
||||
"int y = 0;"
|
||||
"C Obj(y);",
|
||||
ConstructExpr,
|
||||
std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg")));
|
||||
}
|
||||
|
||||
TEST(ForEachArgumentWithParamType, HandlesKandRFunctions) {
|
||||
StatementMatcher ArgumentY =
|
||||
declRefExpr(to(varDecl(hasName("y")))).bind("arg");
|
||||
TypeMatcher IntType = qualType(isInteger()).bind("type");
|
||||
StatementMatcher CallExpr =
|
||||
callExpr(forEachArgumentWithParamType(ArgumentY, IntType));
|
||||
|
||||
EXPECT_TRUE(matchesC("void f();\n"
|
||||
"void call_it(void) { int x, y; f(x, y); }\n"
|
||||
"void f(a, b) int a, b; {}\n"
|
||||
"void call_it2(void) { int x, y; f(x, y); }",
|
||||
CallExpr));
|
||||
}
|
||||
|
||||
TEST(ForEachArgumentWithParamType, HandlesBoundNodesForNonMatches) {
|
||||
EXPECT_TRUE(matchAndVerifyResultTrue(
|
||||
"void g(int i, int j) {"
|
||||
" int a;"
|
||||
" int b;"
|
||||
" int c;"
|
||||
" g(a, 0);"
|
||||
" g(a, b);"
|
||||
" g(0, b);"
|
||||
"}",
|
||||
functionDecl(
|
||||
forEachDescendant(varDecl().bind("v")),
|
||||
forEachDescendant(callExpr(forEachArgumentWithParamType(
|
||||
declRefExpr(to(decl(equalsBoundNode("v")))), qualType())))),
|
||||
std::make_unique<VerifyIdIsBoundTo<VarDecl>>("v", 4)));
|
||||
}
|
||||
|
||||
TEST(ForEachArgumentWithParamType, MatchesFunctionPtrCalls) {
|
||||
StatementMatcher ArgumentY =
|
||||
declRefExpr(to(varDecl(hasName("y")))).bind("arg");
|
||||
TypeMatcher IntType = qualType(builtinType()).bind("type");
|
||||
StatementMatcher CallExpr =
|
||||
callExpr(forEachArgumentWithParamType(ArgumentY, IntType));
|
||||
|
||||
EXPECT_TRUE(
|
||||
matchAndVerifyResultTrue("void f(int i) {"
|
||||
"void (*f_ptr)(int) = f; int y; f_ptr(y); }",
|
||||
CallExpr,
|
||||
std::make_unique<VerifyIdIsBoundTo<QualType>>("type")));
|
||||
EXPECT_TRUE(
|
||||
matchAndVerifyResultTrue("void f(int i) {"
|
||||
"void (*f_ptr)(int) = f; int y; f_ptr(y); }",
|
||||
CallExpr,
|
||||
std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg")));
|
||||
}
|
||||
|
||||
TEST(ForEachArgumentWithParamType, MatchesMemberFunctionPtrCalls) {
|
||||
StatementMatcher ArgumentY =
|
||||
declRefExpr(to(varDecl(hasName("y")))).bind("arg");
|
||||
TypeMatcher IntType = qualType(builtinType()).bind("type");
|
||||
StatementMatcher CallExpr =
|
||||
callExpr(forEachArgumentWithParamType(ArgumentY, IntType));
|
||||
|
||||
StringRef S = "struct A {\n"
|
||||
" int f(int i) { return i + 1; }\n"
|
||||
" int (A::*x)(int);\n"
|
||||
"};\n"
|
||||
"void f() {\n"
|
||||
" int y = 42;\n"
|
||||
" A a;\n"
|
||||
" a.x = &A::f;\n"
|
||||
" (a.*(a.x))(y);\n"
|
||||
"}";
|
||||
EXPECT_TRUE(
|
||||
matchAndVerifyResultTrue(S, CallExpr,
|
||||
std::make_unique<VerifyIdIsBoundTo<QualType>>("type")));
|
||||
EXPECT_TRUE(
|
||||
matchAndVerifyResultTrue(S, CallExpr,
|
||||
std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg")));
|
||||
}
|
||||
|
||||
TEST(QualType, hasCanonicalType) {
|
||||
EXPECT_TRUE(notMatches("typedef int &int_ref;"
|
||||
"int a;"
|
||||
|
|
Loading…
Reference in New Issue