-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[clang-tidy][NFC] Clean up and slightly optimize modernize-use-integer-sign-comparison
#163492
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…er-sign-comparison`
@llvm/pr-subscribers-clang-tools-extra @llvm/pr-subscribers-clang-tidy Author: Victor Chernyakin (localspook) ChangesFull diff: https://github.com/llvm/llvm-project/pull/163492.diff 1 Files Affected:
diff --git a/clang-tools-extra/clang-tidy/modernize/UseIntegerSignComparisonCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseIntegerSignComparisonCheck.cpp
index 0003429c62890..a3d3f0fa0ec93 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseIntegerSignComparisonCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseIntegerSignComparisonCheck.cpp
@@ -34,13 +34,12 @@ AST_MATCHER(clang::QualType, isActualChar) {
} // namespace
static BindableMatcher<clang::Stmt>
-intCastExpression(bool IsSigned,
- const std::string &CastBindName = std::string()) {
+intCastExpression(bool IsSigned, StringRef CastBindName = {}) {
// std::cmp_{} functions trigger a compile-time error if either LHS or RHS
// is a non-integer type, char, enum or bool
// (unsigned char/ signed char are Ok and can be used).
auto IntTypeExpr = expr(hasType(hasCanonicalType(qualType(
- isInteger(), IsSigned ? isSignedInteger() : isUnsignedInteger(),
+ IsSigned ? isSignedInteger() : isUnsignedInteger(),
unless(isActualChar()), unless(booleanType()), unless(enumType())))));
const auto ImplicitCastExpr =
@@ -71,7 +70,7 @@ static StringRef parseOpCode(BinaryOperator::Opcode Code) {
case BO_NE:
return "cmp_not_equal";
default:
- return "";
+ llvm_unreachable("invalid opcode");
}
}
@@ -119,23 +118,16 @@ void UseIntegerSignComparisonCheck::check(
Expr::EvalResult EVResult;
if (!SignedCastExpression->isValueDependent() &&
SignedCastExpression->getSubExpr()->EvaluateAsInt(EVResult,
- *Result.Context)) {
- const llvm::APSInt SValue = EVResult.Val.getInt();
- if (SValue.isNonNegative())
- return;
- }
+ *Result.Context) &&
+ EVResult.Val.getInt().isNonNegative())
+ return;
const auto *BinaryOp =
Result.Nodes.getNodeAs<BinaryOperator>("intComparison");
- if (BinaryOp == nullptr)
- return;
-
- const BinaryOperator::Opcode OpCode = BinaryOp->getOpcode();
+ assert(BinaryOp);
const Expr *LHS = BinaryOp->getLHS()->IgnoreImpCasts();
const Expr *RHS = BinaryOp->getRHS()->IgnoreImpCasts();
- if (LHS == nullptr || RHS == nullptr)
- return;
const Expr *SubExprLHS = nullptr;
const Expr *SubExprRHS = nullptr;
SourceRange R1(LHS->getBeginLoc());
@@ -144,8 +136,7 @@ void UseIntegerSignComparisonCheck::check(
RHS->getEndLoc(), 0, *Result.SourceManager, getLangOpts()));
if (const auto *LHSCast = llvm::dyn_cast<ExplicitCastExpr>(LHS)) {
SubExprLHS = LHSCast->getSubExpr();
- R1 = SourceRange(LHS->getBeginLoc(),
- SubExprLHS->getBeginLoc().getLocWithOffset(-1));
+ R1.setEnd(SubExprLHS->getBeginLoc().getLocWithOffset(-1));
R2.setBegin(Lexer::getLocForEndOfToken(
SubExprLHS->getEndLoc(), 0, *Result.SourceManager, getLangOpts()));
}
@@ -156,21 +147,21 @@ void UseIntegerSignComparisonCheck::check(
DiagnosticBuilder Diag =
diag(BinaryOp->getBeginLoc(),
"comparison between 'signed' and 'unsigned' integers");
- std::string CmpNamespace;
- llvm::StringRef CmpHeader;
+ StringRef CmpNamespace;
+ StringRef CmpHeader;
if (getLangOpts().CPlusPlus20) {
CmpHeader = "<utility>";
- CmpNamespace = llvm::Twine("std::" + parseOpCode(OpCode)).str();
+ CmpNamespace = "std::";
} else if (getLangOpts().CPlusPlus17 && EnableQtSupport) {
CmpHeader = "<QtCore/q20utility.h>";
- CmpNamespace = llvm::Twine("q20::" + parseOpCode(OpCode)).str();
+ CmpNamespace = "q20::";
}
// Prefer modernize-use-integer-sign-comparison when C++20 is available!
Diag << FixItHint::CreateReplacement(
CharSourceRange(R1, SubExprLHS != nullptr),
- llvm::Twine(CmpNamespace + "(").str());
+ Twine(CmpNamespace + parseOpCode(BinaryOp->getOpcode()) + "(").str());
Diag << FixItHint::CreateReplacement(R2, ",");
Diag << FixItHint::CreateReplacement(CharSourceRange::getCharRange(R3), ")");
|
// is a non-integer type, char, enum or bool | ||
// (unsigned char/ signed char are Ok and can be used). | ||
auto IntTypeExpr = expr(hasType(hasCanonicalType(qualType( | ||
isInteger(), IsSigned ? isSignedInteger() : isUnsignedInteger(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isInteger()
is redundant when we have isSignedInteger()
or isUnsignedInteger()
if (!SignedCastExpression->isValueDependent() && | ||
SignedCastExpression->getSubExpr()->EvaluateAsInt(EVResult, | ||
*Result.Context)) { | ||
const llvm::APSInt SValue = EVResult.Val.getInt(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getInt()
returns a reference, so this is an unnecessary copy
const Expr *LHS = BinaryOp->getLHS()->IgnoreImpCasts(); | ||
const Expr *RHS = BinaryOp->getRHS()->IgnoreImpCasts(); | ||
if (LHS == nullptr || RHS == nullptr) | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe either of BinaryOperation
's subexpressions can be null
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But can IgnoreImpCasts
return null? (Genuine question, I'll look into sources a bit later)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would be surprised if it did; in my understanding, all it does is optionally skip past some AST nodes, so what would cause it to return null? (It would be good to check though, yep)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess should not
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IgnoreImpCasts
repeatedly applies this function to the Expr
it's called on:
llvm-project/clang/include/clang/AST/IgnoreExpr.h
Lines 48 to 56 in 4d6f43d
inline Expr *IgnoreImplicitCastsSingleStep(Expr *E) { | |
if (auto *ICE = dyn_cast<ImplicitCastExpr>(E)) | |
return ICE->getSubExpr(); | |
if (auto *FE = dyn_cast<FullExpr>(E)) | |
return FE->getSubExpr(); | |
return E; | |
} |
until it reaches a fixed point. I don't think
ImplicitCastExpr
or FullExpr
can have a null subexpression, so I think this change is safe
static BindableMatcher<clang::Stmt> | ||
intCastExpression(bool IsSigned, | ||
const std::string &CastBindName = std::string()) { | ||
intCastExpression(bool IsSigned, StringRef CastBindName = {}) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
StringRef
is enough here, we don't need std::string
SubExprLHS = LHSCast->getSubExpr(); | ||
R1 = SourceRange(LHS->getBeginLoc(), | ||
SubExprLHS->getBeginLoc().getLocWithOffset(-1)); | ||
R1.setEnd(SubExprLHS->getBeginLoc().getLocWithOffset(-1)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At this point, R1
's begin location is already equal to LHS->getBeginLoc()
, so we only need to update the end location
Diag << FixItHint::CreateReplacement( | ||
CharSourceRange(R1, SubExprLHS != nullptr), | ||
llvm::Twine(CmpNamespace + "(").str()); | ||
Twine(CmpNamespace + parseOpCode(BinaryOp->getOpcode()) + "(").str()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moving the parseOpCode()
call down here removes the duplication above
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/144/builds/38185 Here is the relevant piece of the build log for the reference
|
No description provided.