mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-14 03:45:33 +00:00
[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:
parent
cfed2bf588
commit
e93a73fb7a
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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(
|
||||
|
@ -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) {
|
||||
|
@ -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("==")),
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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(),
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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())),
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user