Skip to content

Commit f39af73

Browse files
[clang][Sema] Warn consecutive builtin comparisons in an expression (#92200)
Add warning under `-Wparentheses` for consistency with `gcc 14.1`. Closes #20456 --------- Co-authored-by: Aaron Ballman <[email protected]>
1 parent 9917f3c commit f39af73

File tree

9 files changed

+31
-8
lines changed

9 files changed

+31
-8
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,9 @@ Improvements to Clang's diagnostics
498498
}
499499
};
500500

501+
- Clang emits a ``-Wparentheses`` warning for expressions with consecutive comparisons like ``x < y < z``.
502+
Fixes #GH20456.
503+
501504
Improvements to Clang's time-trace
502505
----------------------------------
503506

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6919,6 +6919,10 @@ def warn_precedence_bitwise_conditional : Warning<
69196919
def note_precedence_conditional_first : Note<
69206920
"place parentheses around the '?:' expression to evaluate it first">;
69216921

6922+
def warn_consecutive_comparison : Warning<
6923+
"comparisons like 'X<=Y<=Z' don't have their mathematical meaning">,
6924+
InGroup<Parentheses>;
6925+
69226926
def warn_enum_constant_in_bool_context : Warning<
69236927
"converting the enum constant to a boolean">,
69246928
InGroup<IntInBoolContext>, DefaultIgnore;

clang/lib/Sema/SemaExpr.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14867,6 +14867,11 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
1486714867
case BO_GT:
1486814868
ConvertHalfVec = true;
1486914869
ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc);
14870+
14871+
if (const auto *BI = dyn_cast<BinaryOperator>(LHSExpr);
14872+
BI && BI->isComparisonOp())
14873+
Diag(OpLoc, diag::warn_consecutive_comparison);
14874+
1487014875
break;
1487114876
case BO_EQ:
1487214877
case BO_NE:

clang/test/Sema/bool-compare.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ void f(int x, int y, int z) {
8585
if ((a<y) != -1) {}// expected-warning {{comparison of constant -1 with boolean expression is always true}}
8686

8787
if ((a<y) == z) {} // no warning
88-
if (a>y<z) {} // no warning
88+
if (a>y<z) {} // expected-warning {{comparisons like 'X<=Y<=Z' don't have their mathematical meaning}}
8989
if ((a<y) > z) {} // no warning
9090
if((a<y)>(z<y)) {} // no warning
9191
if((a<y)==(z<y)){} // no warning
@@ -145,7 +145,7 @@ void f(int x, int y, int z) {
145145
if (-1 !=(a<y)) {} // expected-warning {{comparison of constant -1 with boolean expression is always true}}
146146

147147
if (z ==(a<y)) {} // no warning
148-
if (z<a>y) {} // no warning
148+
if (z<a>y) {} // expected-warning {{comparisons like 'X<=Y<=Z' don't have their mathematical meaning}}
149149
if (z > (a<y)) {} // no warning
150150
if((z<y)>(a<y)) {} // no warning
151151
if((z<y)==(a<y)){} // no warning

clang/test/Sema/parentheses.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,3 +215,14 @@ namespace PR20735 {
215215
// fix-it:"{{.*}}":{[[@LINE-9]]:20-[[@LINE-9]]:20}:")"
216216
}
217217
}
218+
219+
void consecutive_builtin_compare(int x, int y, int z) {
220+
(void)(x < y < z); // expected-warning {{comparisons like 'X<=Y<=Z' don't have their mathematical meaning}}
221+
(void)(x < y > z); // expected-warning {{comparisons like 'X<=Y<=Z' don't have their mathematical meaning}}
222+
(void)(x < y <= z); // expected-warning {{comparisons like 'X<=Y<=Z' don't have their mathematical meaning}}
223+
(void)(x <= y > z); // expected-warning {{comparisons like 'X<=Y<=Z' don't have their mathematical meaning}}
224+
(void)((x < y) < z); // no-warning
225+
(void)((x < y) >= z); // no-warning
226+
227+
// TODO: Also issue warning for consecutive comparisons that use overloaded comparison operators?
228+
}

clang/test/SemaCXX/bool-compare.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ void f(int x, int y, int z) {
9898
if ((a<y) != -1) {}// expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}}
9999

100100
if ((a<y) == z) {} // no warning
101-
if (a>y<z) {} // no warning
101+
if (a>y<z) {} // expected-warning {{comparisons like 'X<=Y<=Z' don't have their mathematical meaning}}
102102
if ((a<y) > z) {} // no warning
103103
if((a<y)>(z<y)) {} // no warning
104104
if((a<y)==(z<y)){} // no warning
@@ -159,7 +159,7 @@ void f(int x, int y, int z) {
159159
if (-1 !=(a<y)) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}}
160160

161161
if (z ==(a<y)) {} // no warning
162-
if (z<a>y) {} // no warning
162+
if (z<a>y) {} // expected-warning {{comparisons like 'X<=Y<=Z' don't have their mathematical meaning}}
163163
if (z > (a<y)) {} // no warning
164164
if((z<y)>(a<y)) {} // no warning
165165
if((z<y)==(a<y)){} // no warning

clang/test/SemaCXX/cxx2a-adl-only-template-id.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ int e = h<0>(q); // ok, found by unqualified lookup
2727
void fn() {
2828
f<0>(q);
2929
int f;
30-
f<0>(q); // expected-error {{invalid operands to binary expression}}
30+
f<0>(q); // expected-error {{invalid operands to binary expression}} // expected-warning {{comparisons like 'X<=Y<=Z' don't have their mathematical meaning}}
3131
}
3232

3333
void disambig() {

clang/test/SemaTemplate/typo-dependent-name.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ struct X : Base<T> {
2020
bool f(T other) {
2121
// A pair of comparisons; 'inner' is a dependent name so can't be assumed
2222
// to be a template.
23-
return this->inner < other > ::z;
23+
return this->inner < other > ::z; // expected-warning {{comparisons like 'X<=Y<=Z' don't have their mathematical meaning}}
2424
}
2525
};
2626

27-
void use_x(X<int> x) { x.f(0); }
27+
void use_x(X<int> x) { x.f(0); } // expected-note {{requested here}}
2828

2929
template<typename T>
3030
struct Y {

clang/test/SemaTemplate/typo-template-name.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ namespace InExpr {
3636

3737
// These are valid expressions.
3838
foo<foo; // expected-warning {{self-comparison}}
39-
foo<int()>(0);
39+
foo<int()>(0); // expected-warning {{comparisons like 'X<=Y<=Z' don't have their mathematical meaning}}
4040
foo<int(), true>(false);
4141
foo<Base{}.n;
4242
}

0 commit comments

Comments
 (0)