rsmith added a comment.

The diagnostic we get for the case of three or more comparison operators here 
doesn't seem ideal. Perhaps we could do this check as part of the 
`SemaChecking` pass over the completed expression rather than doing it as we 
form the individual comparisons? That way we'll have the contextual information 
necessary to find the complete chained comparison; we'd also be able to detect 
the special case where the operator sequence is the operand of an `&`/`|`/`^` 
so that we need parentheses in the fixit.



================
Comment at: clang/docs/DiagnosticsReference.rst:1-5
 ..
   -------------------------------------------------------------------
   NOTE: This file is automatically generated by running clang-tblgen
   -gen-diag-docs. Do not edit this file by hand!!
   -------------------------------------------------------------------
----------------
Please note this :)

You can revert the changes to this file; it's auto-generated. (We only check in 
a version because the clang website infrastructure isn't yet able to generate 
it on-demand.)


================
Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:6137
+def note_compare_with_parens : Note<
+  "place parentheses around the '%0' comparison to silence this warning">;
+def note_compare_seperate_sides : Note<
----------------
If you're going to quote the operator here, you should prepend "first" or 
similar if both operators are the same.


================
Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:6139
+def note_compare_seperate_sides : Note<
+  "seperate the expression into two clauses to give it the intended 
mathematical meaning">;
+
----------------
Quuxplusone wrote:
> Both in the string and in the identifier, s/seperate/separate/.
> I would also s/sides/clauses/ or s/sides/expression/ just to avoid giving too 
> many different names to the same entity.
Don't say "intended". We don't know the intent.


================
Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:6135
+  "comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'">,
+  InGroup<CompareOpParentheses>, DefaultIgnore;
+
----------------
vabridgers wrote:
> Quuxplusone wrote:
> > Why is this `x<=y<=z` instead of the simpler `x<y<z` or even `x<=y<z` (the 
> > "half-open range" common case)?
> > IMHO you should mention the name "chained comparisons" here, since I think 
> > that's what people coming from such languages will understand.
> Thanks Arthur. I modeled the warning message after gcc's warning message. We 
> found internally that while gcc detected this, clang did not. See 
> https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#Warning-Options ...
> <q>
> -Wparentheses
> Warn if parentheses are omitted in certain contexts, such as when there is an 
> assignment in a context where a truth value is expected, or when operators 
> are nested whose precedence people often get confused about.
> 
> Also warn if a comparison like x<=y<=z appears; this is equivalent to (x<=y ? 
> 1 : 0) <= z, which is a different interpretation from that of ordinary 
> mathematical notation.
> ...
> </q>
> While this is the gcc documentation, we can craft whatever message we see fit 
> at this point in time :)  I'll add "chained" comparison for this next update, 
> we can tailor the message as we see fit. Thanks!
> 
Per our diagnostic best practices 
(http://clang.llvm.org/docs/InternalsManual.html#the-format-string), don't 
repeat the code in the diagnostic (or even an analogy of it such as 'x<=y<=z'); 
instead, consider underlining the chained comparison operators in the snippet. 
Also keep in mind that the developer will see the diagnostic and the notes 
together; you can use the notes to help clarify the meaning of the diagnostic:

```
error: chained comparison does not have its mathematical meaning
  if (a <= b < c)
         ^~   ~
note: perform two separate comparisons to compare the same operand twice
  if (a <= b < c)
             ^
             && b
note: place parentheses around the first comparison to compare against its 
'bool' result and silence this warning
  if (a <= b < c)
      ^
      (     )
```


================
Comment at: clang/lib/Sema/SemaExpr.cpp:14008-14010
+// Accepts (x ['<'|'<='|'>'|'>='] y ['<'|'<='|'>'|'>='] z), suggests:
+// 1) ((x ['<'|'<='|'>'|'>='] y) ['<'|'<='|'>'|'>='] z), or
+// 2) (x ['<'|'<='|'>'|'>='] (y ['<'|'<='|'>'|'>='] z)). or
----------------
Why not also `==` and `!=` here? `a < b == c < d` is a perfectly reasonable 
mathematical equation (modulo the spelling of `==`), and it would seem sensible 
to catch that with the same diagnostic.


================
Comment at: clang/lib/Sema/SemaExpr.cpp:14031
+
+  Self.Diag(LHSExpr->getBeginLoc(), diag::note_compare_seperate_sides)
+      << FixItHint::CreateInsertion(LHSExpr->getBeginLoc(), "(")
----------------
I think we should consider omitting the fixit if the `y` expression is long or 
has side-effects.


================
Comment at: clang/lib/Sema/SemaExpr.cpp:14032-14035
+      << FixItHint::CreateInsertion(LHSExpr->getBeginLoc(), "(")
+      << FixItHint::CreateInsertion(LHSExpr->getEndLoc(), ") && ")
+      << FixItHint::CreateInsertion(LHSBO->getRHS()->getBeginLoc(), "(y ")
+      << FixItHint::CreateInsertion(RHSExpr->getEndLoc(), ")");
----------------
The parentheses here clutter and distract from the point of the fixit (adding 
the `&& y`). We usually don't need them, and in the cases where we do need 
them, the parens you added here aren't correct.

For example, `cond1 && a + b < c < d + e && cond2` doesn't need any parens, and 
`a | b < c < d` needs parens around the entire rewritten `b < c && c < d` 
expression, not around the individual terms.

If you want the rewrite to always be correct, you should add a  `(` at the 
start, an `)` at the end, and a `&& y` before the second operator (or a `y &&` 
after the first operator). If you're OK with it being wrong in the weird case 
of an `&` / `|` / `^` operator adjacent to the chained comparison, then no 
parens are needed at all. But there's no need to parenthesize the individual 
operands of the `&&`.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D85097/new/

https://reviews.llvm.org/D85097

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to