Skip to content

Commit 19c3713

Browse files
committed
[clang-tidy] false positive narrowing conversion
Let's consider the following code from the issue #139467: void test(int cond, char c) { char ret = cond > 0 ? ':' : c; } Initializer of 'ret' looks the following: -ImplicitCastExpr 'char' <IntegralCast> `-ConditionalOperator 'int' |-BinaryOperator 'int' '>' | |-ImplicitCastExpr 'int' <LValueToRValue> | | `-DeclRefExpr 'int' lvalue ParmVar 'cond' 'int' | `-IntegerLiteral 'int' 0 |-CharacterLiteral 'int' 58 `-ImplicitCastExpr 'int' <IntegralCast> `-ImplicitCastExpr 'char' <LValueToRValue> `-DeclRefExpr 'char' lvalue ParmVar 'c' 'char' So it could be seen that 'RHS' of the conditional operator is DeclRefExpr 'c' which is casted to 'int' and then the whole conditional expression is casted to 'char'. But this last conversion is not narrowing, because 'RHS' was 'char' _initially_. We should just remove the cast from 'char' to 'int' before the narrowing conversion check.
1 parent 3e393d9 commit 19c3713

File tree

3 files changed

+20
-4
lines changed

3 files changed

+20
-4
lines changed

clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -554,15 +554,23 @@ bool NarrowingConversionsCheck::handleConditionalOperator(
554554
// We have an expression like so: `output = cond ? lhs : rhs`
555555
// From the point of view of narrowing conversion we treat it as two
556556
// expressions `output = lhs` and `output = rhs`.
557-
handleBinaryOperator(Context, CO->getLHS()->getExprLoc(), Lhs,
558-
*CO->getLHS());
559-
handleBinaryOperator(Context, CO->getRHS()->getExprLoc(), Lhs,
560-
*CO->getRHS());
557+
handleConditionalOperatorArgument(Context, Lhs, CO->getLHS());
558+
handleConditionalOperatorArgument(Context, Lhs, CO->getRHS());
561559
return true;
562560
}
563561
return false;
564562
}
565563

564+
void NarrowingConversionsCheck::handleConditionalOperatorArgument(
565+
const ASTContext &Context, const Expr &Lhs, const Expr *Arg) {
566+
if (const auto *ICE = llvm::dyn_cast<ImplicitCastExpr>(Arg)) {
567+
if (!Arg->getIntegerConstantExpr(Context)) {
568+
Arg = ICE->getSubExpr();
569+
}
570+
}
571+
handleBinaryOperator(Context, Arg->getExprLoc(), Lhs, *Arg);
572+
}
573+
566574
void NarrowingConversionsCheck::handleImplicitCast(
567575
const ASTContext &Context, const ImplicitCastExpr &Cast) {
568576
if (Cast.getExprLoc().isMacroID())

clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ class NarrowingConversionsCheck : public ClangTidyCheck {
8585
bool handleConditionalOperator(const ASTContext &Context, const Expr &Lhs,
8686
const Expr &Rhs);
8787

88+
void handleConditionalOperatorArgument(const ASTContext &Context, const Expr &Lhs,
89+
const Expr *Arg);
8890
void handleImplicitCast(const ASTContext &Context,
8991
const ImplicitCastExpr &Cast);
9092

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// RUN: %check_clang_tidy %s bugprone-narrowing-conversions %t -- --
2+
3+
char test(int cond, char c) {
4+
char ret = cond > 0 ? ':' : c;
5+
return ret;
6+
}

0 commit comments

Comments
 (0)