Move the warning about unused relational comparison from -Wunused-value to

-Wunused-comparison.  Also, newly warn on unused result from overloaded
relational comparisons, now also in -Wunused-comparison.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@203535 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Richard Trieu 2014-03-11 03:11:08 +00:00
parent 4e2325b14b
commit 61e100da3c
7 changed files with 58 additions and 24 deletions

View File

@ -5813,7 +5813,7 @@ def warn_unused_volatile : Warning<
InGroup<DiagGroup<"unused-volatile-lvalue">>; InGroup<DiagGroup<"unused-volatile-lvalue">>;
def warn_unused_comparison : Warning< def warn_unused_comparison : Warning<
"%select{equality|inequality}0 comparison result unused">, "%select{%select{|in}1equality|relational}0 comparison result unused">,
InGroup<UnusedComparison>; InGroup<UnusedComparison>;
def note_inequality_comparison_to_or_assign : Note< def note_inequality_comparison_to_or_assign : Note<
"use '|=' to turn this inequality comparison into an or-assignment">; "use '|=' to turn this inequality comparison into an or-assignment">;

View File

@ -2064,15 +2064,22 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
return true; return true;
case CXXOperatorCallExprClass: { case CXXOperatorCallExprClass: {
// We warn about operator== and operator!= even when user-defined operator // Warn about operator ==,!=,<,>,<=, and >= even when user-defined operator
// overloads as there is no reasonable way to define these such that they // overloads as there is no reasonable way to define these such that they
// have non-trivial, desirable side-effects. See the -Wunused-comparison // have non-trivial, desirable side-effects. See the -Wunused-comparison
// warning: these operators are commonly typo'ed, and so warning on them // warning: operators == and != are commonly typo'ed, and so warning on them
// provides additional value as well. If this list is updated, // provides additional value as well. If this list is updated,
// DiagnoseUnusedComparison should be as well. // DiagnoseUnusedComparison should be as well.
const CXXOperatorCallExpr *Op = cast<CXXOperatorCallExpr>(this); const CXXOperatorCallExpr *Op = cast<CXXOperatorCallExpr>(this);
if (Op->getOperator() == OO_EqualEqual || switch (Op->getOperator()) {
Op->getOperator() == OO_ExclaimEqual) { default:
break;
case OO_EqualEqual:
case OO_ExclaimEqual:
case OO_Less:
case OO_Greater:
case OO_GreaterEqual:
case OO_LessEqual:
WarnE = this; WarnE = this;
Loc = Op->getOperatorLoc(); Loc = Op->getOperatorLoc();
R1 = Op->getSourceRange(); R1 = Op->getSourceRange();

View File

@ -114,25 +114,38 @@ void Sema::ActOnForEachDeclStmt(DeclGroupPtrTy dg) {
} }
} }
/// \brief Diagnose unused '==' and '!=' as likely typos for '=' or '|='. /// \brief Diagnose unused comparisons, both builtin and overloaded operators.
/// For '==' and '!=', suggest fixits for '=' or '|='.
/// ///
/// Adding a cast to void (or other expression wrappers) will prevent the /// Adding a cast to void (or other expression wrappers) will prevent the
/// warning from firing. /// warning from firing.
static bool DiagnoseUnusedComparison(Sema &S, const Expr *E) { static bool DiagnoseUnusedComparison(Sema &S, const Expr *E) {
SourceLocation Loc; SourceLocation Loc;
bool IsNotEqual, CanAssign; bool IsNotEqual, CanAssign, IsRelational;
if (const BinaryOperator *Op = dyn_cast<BinaryOperator>(E)) { if (const BinaryOperator *Op = dyn_cast<BinaryOperator>(E)) {
if (Op->getOpcode() != BO_EQ && Op->getOpcode() != BO_NE) if (!Op->isComparisonOp())
return false; return false;
IsRelational = Op->isRelationalOp();
Loc = Op->getOperatorLoc(); Loc = Op->getOperatorLoc();
IsNotEqual = Op->getOpcode() == BO_NE; IsNotEqual = Op->getOpcode() == BO_NE;
CanAssign = Op->getLHS()->IgnoreParenImpCasts()->isLValue(); CanAssign = Op->getLHS()->IgnoreParenImpCasts()->isLValue();
} else if (const CXXOperatorCallExpr *Op = dyn_cast<CXXOperatorCallExpr>(E)) { } else if (const CXXOperatorCallExpr *Op = dyn_cast<CXXOperatorCallExpr>(E)) {
if (Op->getOperator() != OO_EqualEqual && switch (Op->getOperator()) {
Op->getOperator() != OO_ExclaimEqual) default:
return false; return false;
case OO_EqualEqual:
case OO_ExclaimEqual:
IsRelational = false;
break;
case OO_Less:
case OO_Greater:
case OO_GreaterEqual:
case OO_LessEqual:
IsRelational = true;
break;
}
Loc = Op->getOperatorLoc(); Loc = Op->getOperatorLoc();
IsNotEqual = Op->getOperator() == OO_ExclaimEqual; IsNotEqual = Op->getOperator() == OO_ExclaimEqual;
@ -148,11 +161,11 @@ static bool DiagnoseUnusedComparison(Sema &S, const Expr *E) {
return false; return false;
S.Diag(Loc, diag::warn_unused_comparison) S.Diag(Loc, diag::warn_unused_comparison)
<< (unsigned)IsNotEqual << E->getSourceRange(); << (unsigned)IsRelational << (unsigned)IsNotEqual << E->getSourceRange();
// If the LHS is a plausible entity to assign to, provide a fixit hint to // If the LHS is a plausible entity to assign to, provide a fixit hint to
// correct common typos. // correct common typos.
if (CanAssign) { if (!IsRelational && CanAssign) {
if (IsNotEqual) if (IsNotEqual)
S.Diag(Loc, diag::note_inequality_comparison_to_or_assign) S.Diag(Loc, diag::note_inequality_comparison_to_or_assign)
<< FixItHint::CreateReplacement(Loc, "|="); << FixItHint::CreateReplacement(Loc, "|=");

View File

@ -7,11 +7,11 @@ double sqrt(double X); // implicitly const because of no -fmath-errno!
void bar(volatile int *VP, int *P, int A, void bar(volatile int *VP, int *P, int A,
_Complex double C, volatile _Complex double VC) { _Complex double C, volatile _Complex double VC) {
VP < P; // expected-warning {{expression result unused}} VP < P; // expected-warning {{relational comparison result unused}}
(void)A; (void)A;
(void)foo(1,2); // no warning. (void)foo(1,2); // no warning.
A < foo(1, 2); // expected-warning {{expression result unused}} A < foo(1, 2); // expected-warning {{relational comparison result unused}}
foo(1,2)+foo(4,3); // expected-warning {{expression result unused}} foo(1,2)+foo(4,3); // expected-warning {{expression result unused}}
@ -54,23 +54,23 @@ void t4(int a) {
int b = 0; int b = 0;
if (a) if (a)
b < 1; // expected-warning{{expression result unused}} b < 1; // expected-warning{{relational comparison result unused}}
else else
b < 2; // expected-warning{{expression result unused}} b < 2; // expected-warning{{relational comparison result unused}}
while (1) while (1)
b < 3; // expected-warning{{expression result unused}} b < 3; // expected-warning{{relational comparison result unused}}
do do
b < 4; // expected-warning{{expression result unused}} b < 4; // expected-warning{{relational comparison result unused}}
while (1); while (1);
for (;;) for (;;)
b < 5; // expected-warning{{expression result unused}} b < 5; // expected-warning{{relational comparison result unused}}
for (b < 1;;) {} // expected-warning{{expression result unused}} for (b < 1;;) {} // expected-warning{{relational comparison result unused}}
for (;b < 1;) {} for (;b < 1;) {}
for (;;b < 1) {} // expected-warning{{expression result unused}} for (;;b < 1) {} // expected-warning{{relational comparison result unused}}
} }
// rdar://7186119 // rdar://7186119

View File

@ -303,7 +303,7 @@ struct SP9 {
__declspec(property(get=GetV, put=SetV)) T V; __declspec(property(get=GetV, put=SetV)) T V;
T GetV() { return 0; } T GetV() { return 0; }
void SetV(T v) {} void SetV(T v) {}
void f() { V = this->V; V < this->V; } bool f() { V = this->V; return V < this->V; }
void g() { V++; } void g() { V++; }
void h() { V*=2; } void h() { V*=2; }
}; };

View File

@ -3,6 +3,10 @@
struct A { struct A {
bool operator==(const A&); bool operator==(const A&);
bool operator!=(const A&); bool operator!=(const A&);
bool operator<(const A&);
bool operator>(const A&);
bool operator<=(const A&);
bool operator>=(const A&);
A operator|=(const A&); A operator|=(const A&);
operator bool(); operator bool();
}; };
@ -15,6 +19,11 @@ void test() {
// expected-note {{use '=' to turn this equality comparison into an assignment}} // expected-note {{use '=' to turn this equality comparison into an assignment}}
x != 7; // expected-warning {{inequality comparison result unused}} \ x != 7; // expected-warning {{inequality comparison result unused}} \
// expected-note {{use '|=' to turn this inequality comparison into an or-assignment}} // expected-note {{use '|=' to turn this inequality comparison into an or-assignment}}
x < 7; // expected-warning {{relational comparison result unused}}
x > 7; // expected-warning {{relational comparison result unused}}
x <= 7; // expected-warning {{relational comparison result unused}}
x >= 7; // expected-warning {{relational comparison result unused}}
7 == x; // expected-warning {{equality comparison result unused}} 7 == x; // expected-warning {{equality comparison result unused}}
p == p; // expected-warning {{equality comparison result unused}} \ p == p; // expected-warning {{equality comparison result unused}} \
// expected-note {{use '=' to turn this equality comparison into an assignment}} \ // expected-note {{use '=' to turn this equality comparison into an assignment}} \
@ -25,6 +34,11 @@ void test() {
// expected-note {{use '=' to turn this equality comparison into an assignment}} // expected-note {{use '=' to turn this equality comparison into an assignment}}
a != b; // expected-warning {{inequality comparison result unused}} \ a != b; // expected-warning {{inequality comparison result unused}} \
// expected-note {{use '|=' to turn this inequality comparison into an or-assignment}} // expected-note {{use '|=' to turn this inequality comparison into an or-assignment}}
a < b; // expected-warning {{relational comparison result unused}}
a > b; // expected-warning {{relational comparison result unused}}
a <= b; // expected-warning {{relational comparison result unused}}
a >= b; // expected-warning {{relational comparison result unused}}
A() == b; // expected-warning {{equality comparison result unused}} A() == b; // expected-warning {{equality comparison result unused}}
if (42) x == 7; // expected-warning {{equality comparison result unused}} \ if (42) x == 7; // expected-warning {{equality comparison result unused}} \
// expected-note {{use '=' to turn this equality comparison into an assignment}} // expected-note {{use '=' to turn this equality comparison into an assignment}}

View File

@ -67,10 +67,10 @@ int main()
b = (void (*)()) twoT<int>; b = (void (*)()) twoT<int>;
one < one; //expected-warning {{self-comparison always evaluates to false}} \ one < one; //expected-warning {{self-comparison always evaluates to false}} \
//expected-warning {{expression result unused}} //expected-warning {{relational comparison result unused}}
oneT<int> < oneT<int>; //expected-warning {{self-comparison always evaluates to false}} \ oneT<int> < oneT<int>; //expected-warning {{self-comparison always evaluates to false}} \
//expected-warning {{expression result unused}} //expected-warning {{relational comparison result unused}}
two < two; //expected-error 2 {{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} expected-error {{invalid operands to binary expression ('void' and 'void')}} two < two; //expected-error 2 {{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} expected-error {{invalid operands to binary expression ('void' and 'void')}}
twoT<int> < twoT<int>; //expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} {{cannot resolve overloaded function 'twoT' from context}} twoT<int> < twoT<int>; //expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} {{cannot resolve overloaded function 'twoT' from context}}