[ASTMatchers] Added ignoringParenImpCasts to has matchers

has matcher changed behaviour, and now it matches "as is" and
doesn't skip implicit and paren casts

http://reviews.llvm.org/D20801

llvm-svn: 271289
This commit is contained in:
Piotr Padlewski 2016-05-31 15:26:56 +00:00
parent cfed2bf588
commit e93a73fb7a
22 changed files with 137 additions and 116 deletions

View File

@ -23,10 +23,10 @@ void ThrownExceptionTypeCheck::registerMatchers(MatchFinder *Finder) {
return;
Finder->addMatcher(
cxxThrowExpr(
has(cxxConstructExpr(hasDeclaration(cxxConstructorDecl(
isCopyConstructor(), unless(isNoThrow()))))
.bind("expr"))),
cxxThrowExpr(has(ignoringParenImpCasts(
cxxConstructExpr(hasDeclaration(cxxConstructorDecl(
isCopyConstructor(), unless(isNoThrow()))))
.bind("expr")))),
this);
}

View File

@ -47,15 +47,18 @@ void BoolPointerImplicitConversionCheck::check(
auto DeclRef = ignoringParenImpCasts(declRefExpr(to(equalsNode(D))));
if (!match(findAll(
unaryOperator(hasOperatorName("*"), hasUnaryOperand(DeclRef))),
*If, *Result.Context).empty() ||
*If, *Result.Context)
.empty() ||
!match(findAll(arraySubscriptExpr(hasBase(DeclRef))), *If,
*Result.Context).empty() ||
*Result.Context)
.empty() ||
// FIXME: We should still warn if the paremater is implicitly converted to
// bool.
!match(findAll(callExpr(hasAnyArgument(ignoringParenImpCasts(DeclRef)))),
*If, *Result.Context)
.empty() ||
!match(findAll(cxxDeleteExpr(has(expr(DeclRef)))), *If, *Result.Context)
!match(findAll(cxxDeleteExpr(has(ignoringParenImpCasts(expr(DeclRef))))),
*If, *Result.Context)
.empty())
return;

View File

@ -103,15 +103,17 @@ void DanglingHandleCheck::registerMatchersForVariables(MatchFinder *Finder) {
Finder->addMatcher(
varDecl(hasType(cxxRecordDecl(IsAHandle)),
hasInitializer(
exprWithCleanups(has(ConvertedHandle)).bind("bad_stmt"))),
exprWithCleanups(has(ignoringParenImpCasts(ConvertedHandle)))
.bind("bad_stmt"))),
this);
// Find 'Handle foo = ReturnsAValue();'
Finder->addMatcher(
varDecl(hasType(cxxRecordDecl(IsAHandle)), unless(parmVarDecl()),
hasInitializer(
exprWithCleanups(has(handleFrom(IsAHandle, ConvertedHandle)))
.bind("bad_stmt"))),
varDecl(
hasType(cxxRecordDecl(IsAHandle)), unless(parmVarDecl()),
hasInitializer(exprWithCleanups(has(ignoringParenImpCasts(handleFrom(
IsAHandle, ConvertedHandle))))
.bind("bad_stmt"))),
this);
// Find 'foo = ReturnsAValue(); // foo is Handle'
Finder->addMatcher(
@ -133,7 +135,7 @@ void DanglingHandleCheck::registerMatchersForReturn(MatchFinder *Finder) {
// 1. Value to Handle conversion.
// 2. Handle copy construction.
// We have to match both.
has(handleFrom(
has(ignoringParenImpCasts(handleFrom(
IsAHandle,
handleFrom(IsAHandle, declRefExpr(to(varDecl(
// Is function scope ...
@ -141,7 +143,7 @@ void DanglingHandleCheck::registerMatchersForReturn(MatchFinder *Finder) {
// ... and it is a local array or Value.
anyOf(hasType(arrayType()),
hasType(recordDecl(
unless(IsAHandle)))))))))),
unless(IsAHandle))))))))))),
// Temporary fix for false positives inside lambdas.
unless(hasAncestor(lambdaExpr())))
.bind("bad_stmt"),
@ -149,8 +151,9 @@ void DanglingHandleCheck::registerMatchersForReturn(MatchFinder *Finder) {
// Return a temporary.
Finder->addMatcher(
returnStmt(has(exprWithCleanups(has(handleFrom(
IsAHandle, handleFromTemporaryValue(IsAHandle))))))
returnStmt(
has(ignoringParenImpCasts(exprWithCleanups(has(ignoringParenImpCasts(
handleFrom(IsAHandle, handleFromTemporaryValue(IsAHandle))))))))
.bind("bad_stmt"),
this);
}

View File

@ -25,19 +25,20 @@ void InaccurateEraseCheck::registerMatchers(MatchFinder *Finder) {
return;
const auto CheckForEndCall = hasArgument(
1, anyOf(cxxConstructExpr(
has(cxxMemberCallExpr(callee(cxxMethodDecl(hasName("end"))))
.bind("InaccEndCall"))),
1, anyOf(cxxConstructExpr(has(ignoringParenImpCasts(
cxxMemberCallExpr(callee(cxxMethodDecl(hasName("end"))))
.bind("InaccEndCall")))),
anything()));
Finder->addMatcher(
cxxMemberCallExpr(
on(hasType(namedDecl(matchesName("^::std::")))),
callee(cxxMethodDecl(hasName("erase"))), argumentCountIs(1),
hasArgument(0, has(callExpr(callee(functionDecl(matchesName(
hasArgument(0, has(ignoringParenImpCasts(
callExpr(callee(functionDecl(matchesName(
"^::std::(remove(_if)?|unique)$"))),
CheckForEndCall)
.bind("InaccAlgCall"))),
.bind("InaccAlgCall")))),
unless(isInTemplateInstantiation()))
.bind("InaccErase"),
this);

View File

@ -42,7 +42,8 @@ void IncorrectRoundings::registerMatchers(MatchFinder *MatchFinder) {
// Match a floating literal of 0.5 or a floating literal of 0.5 implicitly.
// cast to floating type.
auto FloatOrCastHalf =
anyOf(FloatHalf, implicitCastExpr(FloatType, has(FloatHalf)));
anyOf(FloatHalf,
implicitCastExpr(FloatType, has(ignoringParenImpCasts(FloatHalf))));
// Match if either the LHS or RHS is a floating literal of 0.5 or a floating
// literal of 0.5 and the other is of type double or vice versa.

View File

@ -45,18 +45,19 @@ void InefficientAlgorithmCheck::registerMatchers(MatchFinder *Finder) {
callExpr(
callee(functionDecl(Algorithms)),
hasArgument(
0, cxxConstructExpr(has(cxxMemberCallExpr(
0, cxxConstructExpr(has(ignoringParenImpCasts(cxxMemberCallExpr(
callee(cxxMethodDecl(hasName("begin"))),
on(declRefExpr(
hasDeclaration(decl().bind("IneffContObj")),
anyOf(hasType(ContainerMatcher.bind("IneffCont")),
hasType(pointsTo(
ContainerMatcher.bind("IneffContPtr")))))
.bind("IneffContExpr")))))),
hasArgument(1, cxxConstructExpr(has(cxxMemberCallExpr(
callee(cxxMethodDecl(hasName("end"))),
on(declRefExpr(hasDeclaration(
equalsBoundNode("IneffContObj")))))))),
.bind("IneffContExpr"))))))),
hasArgument(
1, cxxConstructExpr(has(ignoringParenImpCasts(cxxMemberCallExpr(
callee(cxxMethodDecl(hasName("end"))),
on(declRefExpr(
hasDeclaration(equalsBoundNode("IneffContObj"))))))))),
hasArgument(2, expr().bind("AlgParam")),
unless(isInTemplateInstantiation()))
.bind("IneffAlg");

View File

@ -37,10 +37,11 @@ void MisplacedWideningCastCheck::registerMatchers(MatchFinder *Finder) {
hasType(isInteger()))
.bind("Calc");
const auto ExplicitCast =
explicitCastExpr(hasDestinationType(isInteger()), has(Calc));
const auto ExplicitCast = explicitCastExpr(hasDestinationType(isInteger()),
has(ignoringParenImpCasts(Calc)));
const auto ImplicitCast =
implicitCastExpr(hasImplicitDestinationType(isInteger()), has(Calc));
implicitCastExpr(hasImplicitDestinationType(isInteger()),
has(ignoringParenImpCasts(Calc)));
const auto Cast = expr(anyOf(ExplicitCast, ImplicitCast)).bind("Cast");
Finder->addMatcher(varDecl(hasInitializer(Cast)), this);

View File

@ -20,12 +20,12 @@ namespace misc {
void SizeofContainerCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
expr(unless(isInTemplateInstantiation()),
expr(sizeOfExpr(has(
expr(sizeOfExpr(has(ignoringParenImpCasts(
expr(hasType(hasCanonicalType(hasDeclaration(cxxRecordDecl(
matchesName("^(::std::|::string)"),
unless(matchesName("^::std::(bitset|array)$")),
hasMethod(cxxMethodDecl(hasName("size"), isPublic(),
isConst()))))))))))
isConst())))))))))))
.bind("sizeof"),
// Ignore ARRAYSIZE(<array of containers>) pattern.
unless(hasAncestor(binaryOperator(

View File

@ -81,21 +81,23 @@ void SizeofExpressionCheck::registerMatchers(MatchFinder *Finder) {
const auto SizeOfExpr =
expr(anyOf(sizeOfExpr(has(type())), sizeOfExpr(has(expr()))));
const auto SizeOfZero = expr(
sizeOfExpr(has(expr(ignoringParenImpCasts(integerLiteral(equals(0)))))));
sizeOfExpr(has(ignoringParenImpCasts(expr(integerLiteral(equals(0)))))));
// Detect expression like: sizeof(ARRAYLEN);
// Note: The expression 'sizeof(sizeof(0))' is a portable trick used to know
// the sizeof size_t.
if (WarnOnSizeOfConstant) {
Finder->addMatcher(expr(sizeOfExpr(has(ConstantExpr)), unless(SizeOfZero))
.bind("sizeof-constant"),
this);
Finder->addMatcher(
expr(sizeOfExpr(has(ignoringParenImpCasts(ConstantExpr))),
unless(SizeOfZero))
.bind("sizeof-constant"),
this);
}
// Detect expression like: sizeof(this);
if (WarnOnSizeOfThis) {
Finder->addMatcher(
expr(sizeOfExpr(has(expr(ignoringParenImpCasts(cxxThisExpr())))))
expr(sizeOfExpr(has(ignoringParenImpCasts(expr(cxxThisExpr())))))
.bind("sizeof-this"),
this);
}
@ -105,12 +107,12 @@ void SizeofExpressionCheck::registerMatchers(MatchFinder *Finder) {
const auto ConstStrLiteralDecl =
varDecl(isDefinition(), hasType(qualType(hasCanonicalType(CharPtrType))),
hasInitializer(ignoringParenImpCasts(stringLiteral())));
Finder->addMatcher(
expr(sizeOfExpr(has(expr(hasType(qualType(hasCanonicalType(CharPtrType))),
ignoringParenImpCasts(declRefExpr(
hasDeclaration(ConstStrLiteralDecl)))))))
.bind("sizeof-charp"),
this);
Finder->addMatcher(expr(sizeOfExpr(has(ignoringParenImpCasts(expr(
hasType(qualType(hasCanonicalType(CharPtrType))),
ignoringParenImpCasts(declRefExpr(
hasDeclaration(ConstStrLiteralDecl))))))))
.bind("sizeof-charp"),
this);
// Detect sizeof(ptr) where ptr points to an aggregate (i.e. sizeof(&S)).
const auto ArrayExpr = expr(ignoringParenImpCasts(
@ -188,10 +190,11 @@ void SizeofExpressionCheck::registerMatchers(MatchFinder *Finder) {
// Detect strange double-sizeof expression like: sizeof(sizeof(...));
// Note: The expression 'sizeof(sizeof(0))' is accepted.
Finder->addMatcher(expr(sizeOfExpr(has(expr(hasSizeOfDescendant(
8, expr(SizeOfExpr, unless(SizeOfZero)))))))
.bind("sizeof-sizeof-expr"),
this);
Finder->addMatcher(
expr(sizeOfExpr(has(ignoringParenImpCasts(expr(
hasSizeOfDescendant(8, expr(SizeOfExpr, unless(SizeOfZero))))))))
.bind("sizeof-sizeof-expr"),
this);
}
void SizeofExpressionCheck::check(const MatchFinder::MatchResult &Result) {

View File

@ -33,12 +33,13 @@ void StaticAssertCheck::registerMatchers(MatchFinder *Finder) {
if (!(getLangOpts().CPlusPlus11 || getLangOpts().C11))
return;
auto IsAlwaysFalse = expr(ignoringParenImpCasts(
auto IsAlwaysFalse =
expr(anyOf(cxxBoolLiteral(equals(false)), integerLiteral(equals(0)),
cxxNullPtrLiteralExpr(), gnuNullExpr()))
.bind("isAlwaysFalse")));
.bind("isAlwaysFalse");
auto IsAlwaysFalseWithCast = ignoringParenImpCasts(anyOf(
IsAlwaysFalse, cStyleCastExpr(has(IsAlwaysFalse)).bind("castExpr")));
IsAlwaysFalse, cStyleCastExpr(has(ignoringParenImpCasts(IsAlwaysFalse)))
.bind("castExpr")));
auto AssertExprRoot = anyOf(
binaryOperator(
anyOf(hasOperatorName("&&"), hasOperatorName("==")),

View File

@ -88,7 +88,7 @@ void SuspiciousMissingCommaCheck::registerMatchers(MatchFinder *Finder) {
const auto StringsInitializerList =
initListExpr(hasType(constantArrayType()),
has(expr(ignoringImpCasts(ConcatenatedStringLiteral))));
has(ignoringParenImpCasts(expr(ConcatenatedStringLiteral))));
Finder->addMatcher(StringsInitializerList.bind("list"), this);
}

View File

@ -156,8 +156,9 @@ void SuspiciousStringCompareCheck::registerMatchers(MatchFinder *Finder) {
// Detect comparison to invalid constant: 'strcmp() == -1'.
const auto InvalidLiteral = ignoringParenImpCasts(
anyOf(integerLiteral(unless(equals(0))),
unaryOperator(hasOperatorName("-"),
has(integerLiteral(unless(equals(0))))),
unaryOperator(
hasOperatorName("-"),
has(ignoringParenImpCasts(integerLiteral(unless(equals(0)))))),
characterLiteral(), cxxBoolLiteral()));
Finder->addMatcher(binaryOperator(matchers::isComparisonOperator(),

View File

@ -56,8 +56,8 @@ void UnconventionalAssignOperatorCheck::registerMatchers(ast_matchers::MatchFind
cxxMethodDecl(IsSelfAssign, anyOf(isConst(), isVirtual())).bind("cv"),
this);
const auto IsBadReturnStatement = returnStmt(unless(has(
unaryOperator(hasOperatorName("*"), hasUnaryOperand(cxxThisExpr())))));
const auto IsBadReturnStatement = returnStmt(unless(has(ignoringParenImpCasts(
unaryOperator(hasOperatorName("*"), hasUnaryOperand(cxxThisExpr()))))));
const auto IsGoodAssign = cxxMethodDecl(IsAssign, HasGoodReturnType);
Finder->addMatcher(returnStmt(IsBadReturnStatement, forFunction(IsGoodAssign))

View File

@ -30,13 +30,13 @@ void UniqueptrResetReleaseCheck::registerMatchers(MatchFinder *Finder) {
cxxMethodDecl(hasName("reset"),
ofClass(cxxRecordDecl(hasName("::std::unique_ptr"),
decl().bind("left_class"))))),
has(cxxMemberCallExpr(
has(ignoringParenImpCasts(cxxMemberCallExpr(
on(expr().bind("right")),
callee(memberExpr().bind("release_member")),
callee(cxxMethodDecl(
hasName("release"),
ofClass(cxxRecordDecl(hasName("::std::unique_ptr"),
decl().bind("right_class"))))))))
decl().bind("right_class")))))))))
.bind("reset_call"),
this);
}

View File

@ -33,13 +33,16 @@ void UnusedRAIICheck::registerMatchers(MatchFinder *Finder) {
// Look for temporaries that are constructed in-place and immediately
// destroyed. Look for temporaries created by a functional cast but not for
// those returned from a call.
auto BindTemp = cxxBindTemporaryExpr(unless(has(callExpr()))).bind("temp");
auto BindTemp =
cxxBindTemporaryExpr(unless(has(ignoringParenImpCasts(callExpr()))))
.bind("temp");
Finder->addMatcher(
exprWithCleanups(
unless(isInTemplateInstantiation()),
hasParent(compoundStmt().bind("compound")),
hasType(cxxRecordDecl(hasNonTrivialDestructor())),
anyOf(has(BindTemp), has(cxxFunctionalCastExpr(has(BindTemp)))))
exprWithCleanups(unless(isInTemplateInstantiation()),
hasParent(compoundStmt().bind("compound")),
hasType(cxxRecordDecl(hasNonTrivialDestructor())),
anyOf(has(ignoringParenImpCasts(BindTemp)),
has(ignoringParenImpCasts(cxxFunctionalCastExpr(
has(ignoringParenImpCasts(BindTemp)))))))
.bind("expr"),
this);
}

View File

@ -30,14 +30,14 @@ void MakeSmartPtrCheck::registerMatchers(ast_matchers::MatchFinder *Finder) {
return;
Finder->addMatcher(
cxxBindTemporaryExpr(
has(cxxConstructExpr(
hasType(getSmartPointerTypeMatcher()), argumentCountIs(1),
hasArgument(
0, cxxNewExpr(hasType(pointsTo(qualType(hasCanonicalType(
equalsBoundNode(PointerType))))))
.bind(NewExpression)))
.bind(ConstructorCall))),
cxxBindTemporaryExpr(has(ignoringParenImpCasts(
cxxConstructExpr(
hasType(getSmartPointerTypeMatcher()), argumentCountIs(1),
hasArgument(0,
cxxNewExpr(hasType(pointsTo(qualType(hasCanonicalType(
equalsBoundNode(PointerType))))))
.bind(NewExpression)))
.bind(ConstructorCall)))),
this);
}

View File

@ -141,14 +141,14 @@ void PassByValueCheck::registerMatchers(MatchFinder *Finder) {
// ParenListExpr is generated instead of a CXXConstructExpr,
// filtering out templates automatically for us.
withInitializer(cxxConstructExpr(
has(declRefExpr(to(
has(ignoringParenImpCasts(declRefExpr(to(
parmVarDecl(
hasType(qualType(
// Match only const-ref or a non-const value
// parameters. Rvalues and const-values
// shouldn't be modified.
anyOf(constRefType(), nonConstValueType()))))
.bind("Param")))),
.bind("Param"))))),
hasDeclaration(cxxConstructorDecl(
isCopyConstructor(), unless(isDeleted()),
hasDeclContext(

View File

@ -26,24 +26,26 @@ void ShrinkToFitCheck::registerMatchers(MatchFinder *Finder) {
memberExpr(member(valueDecl().bind("ContainerDecl")));
const auto ShrinkableAsDecl =
declRefExpr(hasDeclaration(valueDecl().bind("ContainerDecl")));
const auto CopyCtorCall = cxxConstructExpr(
hasArgument(0, anyOf(ShrinkableAsMember, ShrinkableAsDecl,
unaryOperator(has(ShrinkableAsMember)),
unaryOperator(has(ShrinkableAsDecl)))));
const auto SwapParam = expr(anyOf(
memberExpr(member(equalsBoundNode("ContainerDecl"))),
declRefExpr(hasDeclaration(equalsBoundNode("ContainerDecl"))),
unaryOperator(has(memberExpr(member(equalsBoundNode("ContainerDecl"))))),
unaryOperator(
has(declRefExpr(hasDeclaration(equalsBoundNode("ContainerDecl")))))));
const auto CopyCtorCall = cxxConstructExpr(hasArgument(
0, anyOf(ShrinkableAsMember, ShrinkableAsDecl,
unaryOperator(has(ignoringParenImpCasts(ShrinkableAsMember))),
unaryOperator(has(ignoringParenImpCasts(ShrinkableAsDecl))))));
const auto SwapParam =
expr(anyOf(memberExpr(member(equalsBoundNode("ContainerDecl"))),
declRefExpr(hasDeclaration(equalsBoundNode("ContainerDecl"))),
unaryOperator(has(ignoringParenImpCasts(
memberExpr(member(equalsBoundNode("ContainerDecl")))))),
unaryOperator(has(ignoringParenImpCasts(declRefExpr(
hasDeclaration(equalsBoundNode("ContainerDecl"))))))));
Finder->addMatcher(
cxxMemberCallExpr(on(hasType(namedDecl(
hasAnyName("std::basic_string", "std::deque", "std::vector")))),
callee(cxxMethodDecl(hasName("swap"))),
has(memberExpr(hasDescendant(CopyCtorCall))),
hasArgument(0, SwapParam.bind("ContainerToShrink")),
unless(isInTemplateInstantiation()))
cxxMemberCallExpr(
on(hasType(namedDecl(
hasAnyName("std::basic_string", "std::deque", "std::vector")))),
callee(cxxMethodDecl(hasName("swap"))),
has(ignoringParenImpCasts(memberExpr(hasDescendant(CopyCtorCall)))),
hasArgument(0, SwapParam.bind("ContainerToShrink")),
unless(isInTemplateInstantiation()))
.bind("CopyAndSwapTrick"),
this);
}

View File

@ -24,7 +24,7 @@ void UseBoolLiteralsCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
implicitCastExpr(
has(integerLiteral().bind("literal")),
has(ignoringParenImpCasts(integerLiteral().bind("literal"))),
hasImplicitDestinationType(qualType(booleanType())),
unless(isInTemplateInstantiation()),
anyOf(hasParent(explicitCastExpr().bind("cast")), anything())),

View File

@ -160,8 +160,8 @@ static bool isCopyAssignmentAndCanBeDefaulted(ASTContext *Context,
// statement:
// return *this;
if (Compound->body_empty() ||
match(returnStmt(has(unaryOperator(hasOperatorName("*"),
hasUnaryOperand(cxxThisExpr())))),
match(returnStmt(has(ignoringParenImpCasts(unaryOperator(
hasOperatorName("*"), hasUnaryOperand(cxxThisExpr()))))),
*Compound->body_back(), *Context)
.empty())
return false;
@ -175,21 +175,21 @@ static bool isCopyAssignmentAndCanBeDefaulted(ASTContext *Context,
// ((Base*)this)->operator=((Base)Other);
//
// So we are looking for a member call that fulfills:
if (match(
compoundStmt(has(cxxMemberCallExpr(allOf(
// - The object is an implicit cast of 'this' to a pointer to
// a base class.
onImplicitObjectArgument(
implicitCastExpr(hasImplicitDestinationType(
pointsTo(type(equalsNode(Base)))),
hasSourceExpression(cxxThisExpr()))),
// - The called method is the operator=.
callee(cxxMethodDecl(isCopyAssignmentOperator())),
// - The argument is (an implicit cast to a Base of) the
// argument taken by "Operator".
argumentCountIs(1),
hasArgument(0, declRefExpr(to(varDecl(equalsNode(Param))))))))),
*Compound, *Context)
if (match(compoundStmt(has(ignoringParenImpCasts(cxxMemberCallExpr(allOf(
// - The object is an implicit cast of 'this' to a pointer to
// a base class.
onImplicitObjectArgument(
implicitCastExpr(hasImplicitDestinationType(
pointsTo(type(equalsNode(Base)))),
hasSourceExpression(cxxThisExpr()))),
// - The called method is the operator=.
callee(cxxMethodDecl(isCopyAssignmentOperator())),
// - The argument is (an implicit cast to a Base of) the
// argument taken by "Operator".
argumentCountIs(1),
hasArgument(0,
declRefExpr(to(varDecl(equalsNode(Param)))))))))),
*Compound, *Context)
.empty())
return false;
}
@ -204,11 +204,11 @@ static bool isCopyAssignmentAndCanBeDefaulted(ASTContext *Context,
member(fieldDecl(equalsNode(Field))));
auto RHS = accessToFieldInVar(Field, Param);
if (match(
compoundStmt(has(stmt(anyOf(
compoundStmt(has(ignoringParenImpCasts(stmt(anyOf(
binaryOperator(hasOperatorName("="), hasLHS(LHS), hasRHS(RHS)),
cxxOperatorCallExpr(hasOverloadedOperatorName("="),
argumentCountIs(2), hasArgument(0, LHS),
hasArgument(1, RHS)))))),
hasArgument(1, RHS))))))),
*Compound, *Context)
.empty())
return false;

View File

@ -461,7 +461,8 @@ void SimplifyBooleanExprCheck::matchCompoundIfReturnsBool(MatchFinder *Finder,
compoundStmt(allOf(hasAnySubstatement(ifStmt(hasThen(returnsBool(Value)),
unless(hasElse(stmt())))),
hasAnySubstatement(
returnStmt(has(cxxBoolLiteral(equals(!Value))))
returnStmt(has(ignoringParenImpCasts(
cxxBoolLiteral(equals(!Value)))))
.bind(CompoundReturnId))))
.bind(Id),
this);

View File

@ -28,11 +28,11 @@ void UniqueptrDeleteReleaseCheck::registerMatchers(MatchFinder *Finder) {
hasName("std::default_delete")))))));
Finder->addMatcher(
cxxDeleteExpr(
has(cxxMemberCallExpr(on(expr(hasType(UniquePtrWithDefaultDelete),
unless(hasType(IsSusbstituted)))
.bind("uptr")),
callee(cxxMethodDecl(hasName("release"))))))
cxxDeleteExpr(has(ignoringParenImpCasts(cxxMemberCallExpr(
on(expr(hasType(UniquePtrWithDefaultDelete),
unless(hasType(IsSusbstituted)))
.bind("uptr")),
callee(cxxMethodDecl(hasName("release")))))))
.bind("delete"),
this);
}