Improve the fix-its for -Wparentheses to ensure that the fix-it

suggestions follow recovery. Additionally, add a note to these
diagnostics which suggests a fix-it for changing the behavior to what
the user probably meant. Examples:

t.cpp:2:9: warning: & has lower precedence than ==; == will be evaluated first
      [-Wparentheses]
  if (i & j == k) {
        ^~~~~~~~
          (     )
t.cpp:2:9: note: place parentheses around the & expression to evaluate it first
  if (i & j == k) {
        ^
      (    )

t.cpp:14:9: warning: using the result of an assignment as a condition
without
      parentheses [-Wparentheses]
  if (i = f()) {
      ~~^~~~~
      (      )
t.cpp:14:9: note: use '==' to turn this assignment into an equality
comparison
  if (i = f()) {
        ^
        ==




git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92975 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Douglas Gregor 2010-01-08 00:20:23 +00:00
Родитель 41d63ed274
Коммит 827feec561
4 изменённых файлов: 71 добавлений и 23 удалений

Просмотреть файл

@ -1563,7 +1563,9 @@ def warn_shift_gt_typewidth : Warning<
def warn_precedence_bitwise_rel : Warning< def warn_precedence_bitwise_rel : Warning<
"%0 has lower precedence than %1; %1 will be evaluated first">, "%0 has lower precedence than %1; %1 will be evaluated first">,
InGroup<Parentheses>; InGroup<Parentheses>;
def note_precedence_bitwise_first : Note<
"place parentheses around the %0 expression to evaluate it first">;
def err_sizeof_nonfragile_interface : Error< def err_sizeof_nonfragile_interface : Error<
"invalid application of '%select{alignof|sizeof}1' to interface %0 in " "invalid application of '%select{alignof|sizeof}1' to interface %0 in "
"non-fragile ABI">; "non-fragile ABI">;
@ -1968,6 +1970,8 @@ def warn_condition_is_assignment : Warning<"using the result of an "
def warn_condition_is_idiomatic_assignment : Warning<"using the result " def warn_condition_is_idiomatic_assignment : Warning<"using the result "
"of an assignment as a condition without parentheses">, "of an assignment as a condition without parentheses">,
InGroup<DiagGroup<"idiomatic-parentheses">>, DefaultIgnore; InGroup<DiagGroup<"idiomatic-parentheses">>, DefaultIgnore;
def note_condition_assign_to_comparison : Note<
"use '==' to turn this assignment into an equality comparison">;
def warn_value_always_zero : Warning< def warn_value_always_zero : Warning<
"%0 is always %select{zero|false|NULL}1 in this context">; "%0 is always %select{zero|false|NULL}1 in this context">;

Просмотреть файл

@ -6150,8 +6150,9 @@ Action::OwningExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
/// ParenRange in parentheses. /// ParenRange in parentheses.
static void SuggestParentheses(Sema &Self, SourceLocation Loc, static void SuggestParentheses(Sema &Self, SourceLocation Loc,
const PartialDiagnostic &PD, const PartialDiagnostic &PD,
SourceRange ParenRange) SourceRange ParenRange,
{ const PartialDiagnostic &SecondPD = PartialDiagnostic(0),
SourceRange SecondParenRange = SourceRange()) {
SourceLocation EndLoc = Self.PP.getLocForEndOfToken(ParenRange.getEnd()); SourceLocation EndLoc = Self.PP.getLocForEndOfToken(ParenRange.getEnd());
if (!ParenRange.getEnd().isFileID() || EndLoc.isInvalid()) { if (!ParenRange.getEnd().isFileID() || EndLoc.isInvalid()) {
// We can't display the parentheses, so just dig the // We can't display the parentheses, so just dig the
@ -6163,6 +6164,21 @@ static void SuggestParentheses(Sema &Self, SourceLocation Loc,
Self.Diag(Loc, PD) Self.Diag(Loc, PD)
<< CodeModificationHint::CreateInsertion(ParenRange.getBegin(), "(") << CodeModificationHint::CreateInsertion(ParenRange.getBegin(), "(")
<< CodeModificationHint::CreateInsertion(EndLoc, ")"); << CodeModificationHint::CreateInsertion(EndLoc, ")");
if (!SecondPD.getDiagID())
return;
EndLoc = Self.PP.getLocForEndOfToken(SecondParenRange.getEnd());
if (!SecondParenRange.getEnd().isFileID() || EndLoc.isInvalid()) {
// We can't display the parentheses, so just dig the
// warning/error and return.
Self.Diag(Loc, SecondPD);
return;
}
Self.Diag(Loc, SecondPD)
<< CodeModificationHint::CreateInsertion(SecondParenRange.getBegin(), "(")
<< CodeModificationHint::CreateInsertion(EndLoc, ")");
} }
/// DiagnoseBitwisePrecedence - Emit a warning when bitwise and comparison /// DiagnoseBitwisePrecedence - Emit a warning when bitwise and comparison
@ -6194,12 +6210,18 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperator::Opcode Opc,
PDiag(diag::warn_precedence_bitwise_rel) PDiag(diag::warn_precedence_bitwise_rel)
<< SourceRange(lhs->getLocStart(), OpLoc) << SourceRange(lhs->getLocStart(), OpLoc)
<< BinOp::getOpcodeStr(Opc) << BinOp::getOpcodeStr(lhsopc), << BinOp::getOpcodeStr(Opc) << BinOp::getOpcodeStr(lhsopc),
lhs->getSourceRange(),
PDiag(diag::note_precedence_bitwise_first)
<< BinOp::getOpcodeStr(Opc),
SourceRange(cast<BinOp>(lhs)->getRHS()->getLocStart(), rhs->getLocEnd())); SourceRange(cast<BinOp>(lhs)->getRHS()->getLocStart(), rhs->getLocEnd()));
else if (BinOp::isComparisonOp(rhsopc)) else if (BinOp::isComparisonOp(rhsopc))
SuggestParentheses(Self, OpLoc, SuggestParentheses(Self, OpLoc,
PDiag(diag::warn_precedence_bitwise_rel) PDiag(diag::warn_precedence_bitwise_rel)
<< SourceRange(OpLoc, rhs->getLocEnd()) << SourceRange(OpLoc, rhs->getLocEnd())
<< BinOp::getOpcodeStr(Opc) << BinOp::getOpcodeStr(rhsopc), << BinOp::getOpcodeStr(Opc) << BinOp::getOpcodeStr(rhsopc),
rhs->getSourceRange(),
PDiag(diag::note_precedence_bitwise_first)
<< BinOp::getOpcodeStr(Opc),
SourceRange(lhs->getLocEnd(), cast<BinOp>(rhs)->getLHS()->getLocStart())); SourceRange(lhs->getLocEnd(), cast<BinOp>(rhs)->getLHS()->getLocStart()));
} }
@ -7251,6 +7273,8 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) {
<< E->getSourceRange() << E->getSourceRange()
<< CodeModificationHint::CreateInsertion(Open, "(") << CodeModificationHint::CreateInsertion(Open, "(")
<< CodeModificationHint::CreateInsertion(Close, ")"); << CodeModificationHint::CreateInsertion(Close, ")");
Diag(Loc, diag::note_condition_assign_to_comparison)
<< CodeModificationHint::CreateReplacement(Loc, "==");
} }
bool Sema::CheckBooleanCondition(Expr *&E, SourceLocation Loc) { bool Sema::CheckBooleanCondition(Expr *&E, SourceLocation Loc) {

Просмотреть файл

@ -4,14 +4,18 @@
// Test the various warnings under -Wparentheses // Test the various warnings under -Wparentheses
void if_assign(void) { void if_assign(void) {
int i; int i;
if (i = 4) {} // expected-warning {{assignment as a condition}} if (i = 4) {} // expected-warning {{assignment as a condition}} \
// expected-note{{use '==' to turn this assignment into an equality comparison}}
if ((i = 4)) {} if ((i = 4)) {}
} }
void bitwise_rel(unsigned i) { void bitwise_rel(unsigned i) {
(void)(i & 0x2 == 0); // expected-warning {{& has lower precedence than ==}} (void)(i & 0x2 == 0); // expected-warning {{& has lower precedence than ==}} \
(void)(0 == i & 0x2); // expected-warning {{& has lower precedence than ==}} // expected-note{{place parentheses around the & expression to evaluate it first}}
(void)(i & 0xff < 30); // expected-warning {{& has lower precedence than <}} (void)(0 == i & 0x2); // expected-warning {{& has lower precedence than ==}} \
// expected-note{{place parentheses around the & expression to evaluate it first}}
(void)(i & 0xff < 30); // expected-warning {{& has lower precedence than <}} \
// expected-note{{place parentheses around the & expression to evaluate it first}}
(void)((i & 0x2) == 0); (void)((i & 0x2) == 0);
(void)(i & (0x2 == 0)); (void)(i & (0x2 == 0));
// Eager logical op // Eager logical op

Просмотреть файл

@ -11,26 +11,34 @@ void test() {
A a, b; A a, b;
// With scalars. // With scalars.
if (x = 7) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} if (x = 7) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \
// expected-note{{use '==' to turn this assignment into an equality comparison}}
if ((x = 7)) {} if ((x = 7)) {}
do { do {
} while (x = 7); // expected-warning {{using the result of an assignment as a condition without parentheses}} } while (x = 7); // expected-warning {{using the result of an assignment as a condition without parentheses}} \
// expected-note{{use '==' to turn this assignment into an equality comparison}}
do { do {
} while ((x = 7)); } while ((x = 7));
while (x = 7) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} while (x = 7) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \
// expected-note{{use '==' to turn this assignment into an equality comparison}}
while ((x = 7)) {} while ((x = 7)) {}
for (; x = 7; ) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} for (; x = 7; ) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \
// expected-note{{use '==' to turn this assignment into an equality comparison}}
for (; (x = 7); ) {} for (; (x = 7); ) {}
if (p = p) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} if (p = p) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \
// expected-note{{use '==' to turn this assignment into an equality comparison}}
if ((p = p)) {} if ((p = p)) {}
do { do {
} while (p = p); // expected-warning {{using the result of an assignment as a condition without parentheses}} } while (p = p); // expected-warning {{using the result of an assignment as a condition without parentheses}} \
// expected-note{{use '==' to turn this assignment into an equality comparison}}
do { do {
} while ((p = p)); } while ((p = p));
while (p = p) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} while (p = p) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \
// expected-note{{use '==' to turn this assignment into an equality comparison}}
while ((p = p)) {} while ((p = p)) {}
for (; p = p; ) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} for (; p = p; ) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \
// expected-note{{use '==' to turn this assignment into an equality comparison}}
for (; (p = p); ) {} for (; (p = p); ) {}
// Initializing variables (shouldn't warn). // Initializing variables (shouldn't warn).
@ -40,26 +48,34 @@ void test() {
while (A y = a) {} while (A y = a) {}
// With temporaries. // With temporaries.
if (x = (b+b).foo()) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} if (x = (b+b).foo()) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \
// expected-note{{use '==' to turn this assignment into an equality comparison}}
if ((x = (b+b).foo())) {} if ((x = (b+b).foo())) {}
do { do {
} while (x = (b+b).foo()); // expected-warning {{using the result of an assignment as a condition without parentheses}} } while (x = (b+b).foo()); // expected-warning {{using the result of an assignment as a condition without parentheses}} \
// expected-note{{use '==' to turn this assignment into an equality comparison}}
do { do {
} while ((x = (b+b).foo())); } while ((x = (b+b).foo()));
while (x = (b+b).foo()) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} while (x = (b+b).foo()) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \
// expected-note{{use '==' to turn this assignment into an equality comparison}}
while ((x = (b+b).foo())) {} while ((x = (b+b).foo())) {}
for (; x = (b+b).foo(); ) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} for (; x = (b+b).foo(); ) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \
// expected-note{{use '==' to turn this assignment into an equality comparison}}
for (; (x = (b+b).foo()); ) {} for (; (x = (b+b).foo()); ) {}
// With a user-defined operator. // With a user-defined operator.
if (a = b + b) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} if (a = b + b) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \
// expected-note{{use '==' to turn this assignment into an equality comparison}}
if ((a = b + b)) {} if ((a = b + b)) {}
do { do {
} while (a = b + b); // expected-warning {{using the result of an assignment as a condition without parentheses}} } while (a = b + b); // expected-warning {{using the result of an assignment as a condition without parentheses}} \
// expected-note{{use '==' to turn this assignment into an equality comparison}}
do { do {
} while ((a = b + b)); } while ((a = b + b));
while (a = b + b) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} while (a = b + b) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \
// expected-note{{use '==' to turn this assignment into an equality comparison}}
while ((a = b + b)) {} while ((a = b + b)) {}
for (; a = b + b; ) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} for (; a = b + b; ) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \
// expected-note{{use '==' to turn this assignment into an equality comparison}}
for (; (a = b + b); ) {} for (; (a = b + b); ) {}
} }