From 71263dc615cd6ece304e4326485336691c2ddc26 Mon Sep 17 00:00:00 2001 From: Baranov Victor Date: Sun, 29 Mar 2026 09:11:28 +0300 Subject: [PATCH] [clang-tidy] Fix bugprone-inc-dec-in-conditions FP with lambda condition (#189145) Fixes https://github.com/llvm/llvm-project/issues/163913. --- .../bugprone/IncDecInConditionsCheck.cpp | 5 ++- clang-tools-extra/docs/ReleaseNotes.rst | 5 +++ .../bugprone/inc-dec-in-conditions.cpp | 44 +++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.cpp index 9f723d52f60e..bdb91b1ed0f4 100644 --- a/clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.cpp @@ -39,6 +39,9 @@ void IncDecInConditionsCheck::registerMatchers(MatchFinder *Finder) { expr(anyOf(hasAncestor(expr(matchers::hasUnevaluatedContext())), hasAncestor(typeLoc()))); + auto IsInLambda = + hasAncestor(lambdaExpr(hasAncestor(expr(equalsBoundNode("parent"))))); + Finder->addMatcher( expr( OperatorMatcher, unless(hasAncestor(OperatorMatcher)), @@ -50,7 +53,7 @@ void IncDecInConditionsCheck::registerMatchers(MatchFinder *Finder) { cxxOperatorCallExpr( isPrePostOperator(), hasUnaryOperand(expr().bind("operand")))), - unless(IsInUnevaluatedContext), + unless(IsInUnevaluatedContext), unless(IsInLambda), hasAncestor( expr(equalsBoundNode("parent"), hasDescendant( diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 637edaece2a9..eb735e6e62ee 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -219,6 +219,11 @@ Changes in existing checks loss in overloads with transparent standard functors (e.g. ``std::plus<>``) for ``std::accumulate``, ``std::reduce``, and ``std::inner_product``. +- Improved :doc:`bugprone-inc-dec-in-conditions + ` check by fixing a false + positive when increment/decrement operators appear inside lambda bodies that + are part of a condition expression. + - Improved :doc:`bugprone-macro-parentheses ` check by printing the macro definition in the warning message if the macro is defined on command line. diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/inc-dec-in-conditions.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/inc-dec-in-conditions.cpp index 91de013138f0..82a36f1dc3e0 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/inc-dec-in-conditions.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/inc-dec-in-conditions.cpp @@ -78,3 +78,47 @@ namespace PR85838 { if (static_cast(bar) < foo) {} } } + +namespace GH163913 { + void lambdaWithIncrement(int size) { + if ([](int n) { + ++n; + return n; + }(size) < 42) {} + } + + void lambdaWithDecrement(int size) { + if ([](int n) { + --n; + return n; + }(size) < 42) {} + } + + template + auto eval(Func&& fn) -> decltype(fn()) { + return fn(); + } + + void lambdaWithForLoop(int size) { + if (eval([&] { + int result = 0; + for (int i = 0; i < size; i++) { + result += i; + } + return result; + }) < 42) {} + } + + void outsideLambda(int size) { + if ([](int n) { + --n; + return n; + }(size) < ++size) {} + // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: incrementing and referencing a variable in a complex condition + if (++size > [](int n) { + --n; + return n; + }(size)) {} + // CHECK-MESSAGES: :[[@LINE-4]]:9: warning: incrementing and referencing a variable in a complex condition + } +}