[Sema] Move 'char-expression-as-unsigned < 0' into a separate diagnostic

This change splits '-Wtautological-unsigned-zero-compare' by reporting
char-expressions-interpreted-as-unsigned under a separate diagnostic
'-Wtautological-unsigned-char-zero-compare'. This is beneficial for
projects that want to enable '-Wtautological-unsigned-zero-compare' but at
the same time want to keep code portable for platforms with char being
signed or unsigned, such as Chromium.

Differential Revision: https://reviews.llvm.org/D99808
This commit is contained in:
Anton Bikineev 2021-04-02 20:14:44 +02:00
parent f4ecd5a128
commit 69545154cc
4 changed files with 53 additions and 5 deletions

View File

@ -591,11 +591,13 @@ def SwiftNameAttribute : DiagGroup<"swift-name-attribute">;
def IntInBoolContext : DiagGroup<"int-in-bool-context">;
def TautologicalTypeLimitCompare : DiagGroup<"tautological-type-limit-compare">;
def TautologicalUnsignedZeroCompare : DiagGroup<"tautological-unsigned-zero-compare">;
def TautologicalUnsignedCharZeroCompare : DiagGroup<"tautological-unsigned-char-zero-compare">;
def TautologicalUnsignedEnumZeroCompare : DiagGroup<"tautological-unsigned-enum-zero-compare">;
// For compatibility with GCC. Tautological comparison warnings for constants
// that are an extremal value of the type.
def TypeLimits : DiagGroup<"type-limits", [TautologicalTypeLimitCompare,
TautologicalUnsignedZeroCompare,
TautologicalUnsignedCharZeroCompare,
TautologicalUnsignedEnumZeroCompare]>;
// Additional tautological comparison warnings based on the expression, not
// only on its type.

View File

@ -6784,6 +6784,10 @@ def warn_unsigned_always_true_comparison : Warning<
"result of comparison of %select{%3|unsigned expression}0 %2 "
"%select{unsigned expression|%3}0 is always %4">,
InGroup<TautologicalUnsignedZeroCompare>, DefaultIgnore;
def warn_unsigned_char_always_true_comparison : Warning<
"result of comparison of %select{%3|char expression}0 %2 "
"%select{char expression|%3}0 is always %4, since char is interpreted as "
"unsigned">, InGroup<TautologicalUnsignedCharZeroCompare>, DefaultIgnore;
def warn_unsigned_enum_always_true_comparison : Warning<
"result of comparison of %select{%3|unsigned enum expression}0 %2 "
"%select{unsigned enum expression|%3}0 is always %4">,

View File

@ -11446,11 +11446,14 @@ static bool CheckTautologicalComparison(Sema &S, BinaryOperator *E,
<< OtherIsBooleanDespiteType << *Result
<< E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange());
} else {
unsigned Diag = (isKnownToHaveUnsignedValue(OriginalOther) && Value == 0)
? (HasEnumType(OriginalOther)
? diag::warn_unsigned_enum_always_true_comparison
: diag::warn_unsigned_always_true_comparison)
: diag::warn_tautological_constant_compare;
bool IsCharTy = OtherT.withoutLocalFastQualifiers() == S.Context.CharTy;
unsigned Diag =
(isKnownToHaveUnsignedValue(OriginalOther) && Value == 0)
? (HasEnumType(OriginalOther)
? diag::warn_unsigned_enum_always_true_comparison
: IsCharTy ? diag::warn_unsigned_char_always_true_comparison
: diag::warn_unsigned_always_true_comparison)
: diag::warn_tautological_constant_compare;
S.Diag(E->getOperatorLoc(), Diag)
<< RhsConstant << OtherT << E->getOpcodeStr() << OS.str() << *Result

View File

@ -0,0 +1,39 @@
// RUN: %clang_cc1 -fsyntax-only \
// RUN: -fno-signed-char \
// RUN: -Wtautological-unsigned-zero-compare \
// RUN: -Wtautological-unsigned-char-zero-compare \
// RUN: -verify=unsigned %s
// RUN: %clang_cc1 -fsyntax-only \
// RUN: -Wtautological-unsigned-zero-compare \
// RUN: -Wtautological-unsigned-char-zero-compare \
// RUN: -verify=signed %s
void f(char c, unsigned char uc, signed char cc) {
if (c < 0)
return;
// unsigned-warning@-2 {{comparison of char expression < 0 is always false, since char is interpreted as unsigned}}
if (uc < 0)
return;
// unsigned-warning@-2 {{comparison of unsigned expression < 0 is always false}}
// signed-warning@-3 {{comparison of unsigned expression < 0 is always false}}
if (cc < 0)
return;
// Promoted to integer expressions should not warn.
if (c - 4 < 0)
return;
}
void ref(char &c, unsigned char &uc, signed char &cc) {
if (c < 0)
return;
// unsigned-warning@-2 {{comparison of char expression < 0 is always false, since char is interpreted as unsigned}}
if (uc < 0)
return;
// unsigned-warning@-2 {{comparison of unsigned expression < 0 is always false}}
// signed-warning@-3 {{comparison of unsigned expression < 0 is always false}}
if (cc < 0)
return;
// Promoted to integer expressions should not warn.
if (c - 4 < 0)
return;
}