diff --git a/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp @@ -34,6 +34,11 @@ bool operator<(const MagnitudeBits &Other) const noexcept { return WidthWithoutSignBit < Other.WidthWithoutSignBit; } + + bool operator!=(const MagnitudeBits &Other) const noexcept { + return WidthWithoutSignBit != Other.WidthWithoutSignBit || + BitFieldWidth != Other.BitFieldWidth; + } }; } // namespace @@ -184,13 +189,19 @@ if (LoopVar->getType() != LoopIncrement->getType()) return; - const QualType LoopVarType = LoopVar->getType(); - const QualType UpperBoundType = UpperBound->getType(); - ASTContext &Context = *Result.Context; + const QualType LoopVarType = LoopVar->getType(); const MagnitudeBits LoopVarMagnitudeBits = calcMagnitudeBits(Context, LoopVarType, LoopVar); + + const MagnitudeBits LoopIncrementMagnitudeBits = + calcMagnitudeBits(Context, LoopIncrement->getType(), LoopIncrement); + // We matched the loop variable incorrectly. + if (LoopIncrementMagnitudeBits != LoopVarMagnitudeBits) + return; + + const QualType UpperBoundType = UpperBound->getType(); const MagnitudeBits UpperBoundMagnitudeBits = calcUpperBoundMagnitudeBits(Context, UpperBound, UpperBoundType); diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/too-small-loop-variable.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/too-small-loop-variable.cpp --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/too-small-loop-variable.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/too-small-loop-variable.cpp @@ -373,3 +373,20 @@ } } +void goodForLoopWithBitfieldOnUpperBoundOnly() { + struct S { + int x : 4; + } s; + + for (int i = 10; i > s.x; --i) { + } +} + +void goodForLoopWithIntegersOnUpperBoundOnly() { + struct S { + short x; + } s; + + for (int i = 10; i > s.x; --i) { + } +}