diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone-infinite-loop.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone-infinite-loop.cpp --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone-infinite-loop.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone-infinite-loop.cpp @@ -70,11 +70,25 @@ i++; } + while ((Limit)--) { + // Not an error since 'Limit' is updated. + i++; + } + + while ((Limit) -= 1) { + // Not an error since 'Limit' is updated. + } + while (int k = Limit) { // Not an error since 'Limit' is updated. Limit--; } + while (int k = Limit) { + // Not an error since 'Limit' is updated + (Limit)--; + } + while (int k = Limit--) { // Not an error since 'Limit' is updated. i++; @@ -86,6 +100,15 @@ for (i = 0; i < Limit; Limit--) { } + + for (i = 0; i < Limit; (Limit) = Limit - 1) { + } + + for (i = 0; i < Limit; (Limit) -= 1) { + } + + for (i = 0; i < Limit; --(Limit)) { + } } void simple_not_infinite2() { diff --git a/clang/lib/Analysis/ExprMutationAnalyzer.cpp b/clang/lib/Analysis/ExprMutationAnalyzer.cpp --- a/clang/lib/Analysis/ExprMutationAnalyzer.cpp +++ b/clang/lib/Analysis/ExprMutationAnalyzer.cpp @@ -201,14 +201,15 @@ const Stmt *ExprMutationAnalyzer::findDirectMutation(const Expr *Exp) { // LHS of any assignment operators. - const auto AsAssignmentLhs = - binaryOperator(isAssignmentOperator(), - hasLHS(maybeEvalCommaExpr(equalsNode(Exp)))); + const auto AsAssignmentLhs = binaryOperator( + isAssignmentOperator(), + hasLHS(maybeEvalCommaExpr(ignoringParenImpCasts(equalsNode(Exp))))); // Operand of increment/decrement operators. const auto AsIncDecOperand = unaryOperator(anyOf(hasOperatorName("++"), hasOperatorName("--")), - hasUnaryOperand(maybeEvalCommaExpr(equalsNode(Exp)))); + hasUnaryOperand(maybeEvalCommaExpr( + ignoringParenImpCasts(equalsNode(Exp))))); // Invoking non-const member function. // A member function is assumed to be non-const when it is unresolved. diff --git a/clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp b/clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp --- a/clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp +++ b/clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp @@ -112,11 +112,21 @@ class AssignmentTest : public ::testing::TestWithParam {}; TEST_P(AssignmentTest, AssignmentModifies) { - const std::string ModExpr = "x " + GetParam() + " 10"; - const auto AST = buildASTFromCode("void f() { int x; " + ModExpr + "; }"); - const auto Results = - match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); - EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre(ModExpr)); + { + const std::string ModExpr = "x " + GetParam() + " 10"; + const auto AST = buildASTFromCode("void f() { int x; " + ModExpr + "; }"); + const auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre(ModExpr)); + } + + { + const std::string ModExpr = "(x) " + GetParam() + " 10"; + const auto AST = buildASTFromCode("void f() { int x; " + ModExpr + "; }"); + const auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre(ModExpr)); + } } INSTANTIATE_TEST_CASE_P(AllAssignmentOperators, AssignmentTest, @@ -134,7 +144,8 @@ } INSTANTIATE_TEST_CASE_P(AllIncDecOperators, IncDecTest, - Values("++x", "--x", "x++", "x--"), ); + Values("++x", "--x", "x++", "x--", "++(x)", "--(x)", + "(x)++", "(x)--"), ); TEST(ExprMutationAnalyzerTest, NonConstMemberFunc) { const auto AST = buildASTFromCode(