mgrabovsky updated this revision to Diff 37987.
mgrabovsky added a comment.

Correction for C++ tests


http://reviews.llvm.org/D13643

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaChecking.cpp
  test/Sema/bool-compare.c
  test/SemaCXX/bool-compare.cpp

Index: test/SemaCXX/bool-compare.cpp
===================================================================
--- test/SemaCXX/bool-compare.cpp
+++ test/SemaCXX/bool-compare.cpp
@@ -98,7 +98,9 @@
   if ((a<y) != -1) {}// expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}}
 
   if ((a<y) == z) {} // no warning
-  if (a>y<z)      {} // no warning
+  if (a>y<z)      {} // expected-warning {{comparisons such as 'a > b < c' do not have their mathematical meaning}} \
+                     // expected-note {{to achieve the expected behavior, turn this expression into a conjunction of two comparisons}} \
+                     // expected-note {{place parentheses around either of the comparisons to silence this warning}}
   if ((a<y) > z)  {} // no warning
   if((a<y)>(z<y)) {} // no warning
   if((a<y)==(z<y)){} // no warning
@@ -159,7 +161,9 @@
   if (-1 !=(a<y)) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}}
 
   if (z ==(a<y))  {} // no warning
-  if (z<a>y)      {} // no warning
+  if (z<a>y)      {} // expected-warning {{comparisons such as 'a < b > c' do not have their mathematical meaning}} \
+                     // expected-note {{to achieve the expected behavior, turn this expression into a conjunction of two comparisons}} \
+                     // expected-note {{place parentheses around either of the comparisons to silence this warning}}
   if (z > (a<y))  {} // no warning
   if((z<y)>(a<y)) {} // no warning
   if((z<y)==(a<y)){} // no warning
Index: test/Sema/bool-compare.c
===================================================================
--- test/Sema/bool-compare.c
+++ test/Sema/bool-compare.c
@@ -85,7 +85,9 @@
   if ((a<y) != -1) {}// expected-warning {{comparison of constant -1 with boolean expression is always true}}
 
   if ((a<y) == z) {} // no warning
-  if (a>y<z)      {} // no warning
+  if (a>y<z)      {} // expected-warning {{comparisons such as 'a > b < c' do not have their mathematical meaning}} \
+                     // expected-note {{to achieve the expected behavior, turn this expression into a conjunction of two comparisons}} \
+                     // expected-note {{place parentheses around either of the comparisons to silence this warning}}
   if ((a<y) > z)  {} // no warning
   if((a<y)>(z<y)) {} // no warning
   if((a<y)==(z<y)){} // no warning
@@ -144,10 +146,25 @@
   if (z !=(a<y))  {} // no warning
   if (-1 !=(a<y)) {} // expected-warning {{comparison of constant -1 with boolean expression is always true}}
 
-  if (z ==(a<y))  {}    // no warning
-  if (z<a>y)      {}        // no warning
-  if (z > (a<y))  {}    // no warning
-  if((z<y)>(a<y)) {}   // no warning
+  if (a==b==z) {} // expected-warning {{comparisons such as 'a == b == c' do not have their mathematical meaning}} \
+                  // expected-note {{to achieve the expected behavior, turn this expression into a conjunction of two comparisons}} \
+                  // expected-note {{place parentheses around either of the comparisons to silence this warning}}
+  if ((a==y)==z) {} // no warning
+  if (a==(y==z)) {} // no warning
+
+  if (z ==(a<y))  {}  // no warning
+  if (z<a>y)      {}  // expected-warning {{comparisons such as 'a < b > c' do not have their mathematical meaning}} \
+                      // expected-note {{to achieve the expected behavior, turn this expression into a conjunction of two comparisons}} \
+                      // expected-note {{place parentheses around either of the comparisons to silence this warning}}
+  if (x>y!=z) {} // expected-warning {{comparisons such as 'a > b != c' do not have their mathematical meaning}} \
+                 // expected-note {{to achieve the expected behavior, turn this expression into a conjunction of two comparisons}} \
+                 // expected-note {{place parentheses around either of the comparisons to silence this warning}}
+  if (1.0<2.0<3.0) {} // expected-warning {{comparisons such as 'a < b < c' do not have their mathematical meaning}} \
+                      // expected-note {{to achieve the expected behavior, turn this expression into a conjunction of two comparisons}} \
+                      // expected-note {{place parentheses around either of the comparisons to silence this warning}}
+
+  if (z > (a<y))  {}  // no warning
+  if((z<y)>(a<y)) {}  // no warning
   if((z<y)==(a<y)){}  // no warning
   if((z<y)!=(a<y)){}  // no warning
   if((y==z)<(z==x)){}  // no warning
Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -6693,6 +6693,24 @@
         << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange());
 }
 
+/// Diagnose attempts at ternary comparison, e.g., 1 < x < 2
+static void DiagnoseTernaryComparison(Sema &S, BinaryOperator *E) {
+  BinaryOperator *LHS = dyn_cast<BinaryOperator>(E->getLHS()->IgnoreImpCasts());
+  if (!LHS || !LHS->isComparisonOp())
+    return;
+
+  SourceLocation Loc = E->getSourceRange().getBegin();
+
+  S.Diag(Loc, diag::warn_ternary_comparison)
+    << LHS->getOpcodeStr()
+    << E->getOpcodeStr()
+    << E->getSourceRange();
+  S.Diag(Loc, diag::note_ternary_comparison_to_conjunction);
+  S.Diag(Loc, diag::note_ternary_comparison_silence)
+    << FixItHint::CreateInsertion(LHS->getSourceRange().getBegin(), "(")
+    << FixItHint::CreateInsertion(LHS->getSourceRange().getEnd(), ")");
+}
+
 /// Analyze the operands of the given comparison.  Implements the
 /// fallback case from AnalyzeComparison.
 static void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) {
@@ -6704,6 +6722,9 @@
 ///
 /// \param E the binary operator to check for warnings
 static void AnalyzeComparison(Sema &S, BinaryOperator *E) {
+  // We want to do this, no matter the types
+  DiagnoseTernaryComparison(S, E);
+
   // The type the comparison is being performed in.
   QualType T = E->getLHS()->getType();
 
@@ -6718,9 +6739,9 @@
 
   Expr *LHS = E->getLHS()->IgnoreParenImpCasts();
   Expr *RHS = E->getRHS()->IgnoreParenImpCasts();
-  
+
   bool IsComparisonConstant = false;
-  
+
   // Check whether an integer constant comparison results in a value
   // of 'true' or 'false'.
   if (T->isIntegralType(S.Context)) {
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -5872,6 +5872,14 @@
 def note_condition_assign_silence : Note<
   "place parentheses around the assignment to silence this warning">;
 
+def warn_ternary_comparison : Warning<"comparisons such as 'a %0 b %1 c' do not "
+  "have their mathematical meaning">,
+  InGroup<Parentheses>;
+def note_ternary_comparison_to_conjunction : Note<"to achieve the expected behavior, "
+  "turn this expression into a conjunction of two comparisons">;
+def note_ternary_comparison_silence : Note<"place parentheses around either "
+  "of the comparisons to silence this warning">;
+
 def warn_equality_with_extra_parens : Warning<"equality comparison with "
   "extraneous parentheses">, InGroup<ParenthesesOnEquality>;
 def note_equality_comparison_to_assign : Note<
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to