[clang-tidy] Fix trailing semicolon and lost comment in readability-use-std-min-max (#208782)

Fix two bugs in readability-use-std-min-max when the if body has no
braces.

For brace-less if bodies, If->getEndLoc() points to the expression end
rather than the trailing semicolon, truncating replacements and losing
comments. We find the semicolon via findNextToken and extend the range
consistent with compound statement logic.

Before:
  if (n < -1) n = -1 ;          ->  n = std::max(n, -1); ;
  if (n > 1) n = 1/*comment*/;  ->  n = std::min(n, 1);;

After:
  if (n < -1) n = -1 ;          ->  n = std::max(n, -1);
  if (n > 1) n = 1/*comment*/;  ->  n = std::min(n, 1); /*comment*/

Fixes #208708.

AI Usage: This patch is AI-assisted, reviewed and verified by me.
This commit is contained in:
hehuan 2026-08-01 19:09:50 +08:00 committed by GitHub
parent 63f9de888e
commit 60f965b1f6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 23 additions and 1 deletions

View file

@ -167,7 +167,7 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
const auto *BinaryOp = Result.Nodes.getNodeAs<BinaryOperator>("binaryOp"); const auto *BinaryOp = Result.Nodes.getNodeAs<BinaryOperator>("binaryOp");
const BinaryOperatorKind BinaryOpcode = BinaryOp->getOpcode(); const BinaryOperatorKind BinaryOpcode = BinaryOp->getOpcode();
const SourceLocation IfLocation = If->getIfLoc(); const SourceLocation IfLocation = If->getIfLoc();
const SourceLocation ThenLocation = If->getEndLoc(); SourceLocation ThenLocation = If->getEndLoc();
auto ReplaceAndDiagnose = [&](const StringRef FunctionName) { auto ReplaceAndDiagnose = [&](const StringRef FunctionName) {
const SourceManager &Source = *Result.SourceManager; const SourceManager &Source = *Result.SourceManager;
@ -218,6 +218,12 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
if (Semi != StringRef::npos && PostInner.take_front(Semi).trim().empty()) if (Semi != StringRef::npos && PostInner.take_front(Semi).trim().empty())
PostInner = PostInner.drop_front(Semi + 1); PostInner = PostInner.drop_front(Semi + 1);
AppendNormalized(PostInner); AppendNormalized(PostInner);
} else if (const auto SemiTok =
Lexer::findNextToken(ThenLocation, Source, LO);
SemiTok && SemiTok->is(tok::semi)) {
AppendNormalized(
GetSourceText(ThenLocation, SemiTok->getLocation()).rtrim());
ThenLocation = SemiTok->getLocation();
} }
diag(IfLocation, "use `%0` instead of `%1`") diag(IfLocation, "use `%0` instead of `%1`")

View file

@ -121,6 +121,10 @@ Changes in existing checks
exclusively for overload resolution. Added the :option:`IgnoredTypes` exclusively for overload resolution. Added the :option:`IgnoredTypes`
option to allow customizing the set of ignored types. option to allow customizing the set of ignored types.
- Improved :doc:`readability-use-std-min-max
<clang-tidy/checks/readability/use-std-min-max>` check by fixing spurious
trailing semicolons and lost comments when the ``if`` body has no braces.
Removed checks Removed checks
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^

View file

@ -253,6 +253,18 @@ void testVectorSizeType() {
value = v.size(); value = v.size();
} }
namespace gh208708 {
void f(int &n) {
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<`
// CHECK-FIXES: n = std::max(n, -1);
if (n < -1) n = -1 ;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `>`
// CHECK-FIXES: n = std::min(n, 1); /*use clamp when c++17 or later is enabled*/
if (n > 1) n = 1/*use clamp when c++17 or later is enabled*/;
}
} // namespace gh208708
namespace gh121676 { namespace gh121676 {
void useLeft() { void useLeft() {