Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -5866,6 +5866,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; +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; def note_equality_comparison_to_assign : Note< 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(E->getLHS()); + 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) { @@ -6716,11 +6734,13 @@ if (E->isValueDependent()) return AnalyzeImpConvsInComparison(S, E); + DiagnoseTernaryComparison(S, E); + 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: test/Sema/bool-compare.c =================================================================== --- test/Sema/bool-compare.c +++ test/Sema/bool-compare.c @@ -85,7 +85,9 @@ if ((ayy 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 z) {} // no warning if((a(zy) {} // no warning - if (z > (a(ay) {} // 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(a