Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -5862,6 +5862,14 @@ def note_condition_assign_silence : Note< "place parentheses around the assignment to silence this warning">; +def warn_ternary_comparison : Warning<"ternary comparisons do not work " + "as expected">, + 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,22 @@ << 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.DiagRuntimeBehavior(Loc, E, + S.PDiag(diag::warn_ternary_comparison) << E->getSourceRange()); + S.DiagRuntimeBehavior(Loc, E, + S.PDiag(diag::note_ternary_comparison_to_conjunction)); + S.DiagRuntimeBehavior(Loc, E, + S.PDiag(diag::note_ternary_comparison_silence)); +} + /// Analyze the operands of the given comparison. Implements the /// fallback case from AnalyzeComparison. static void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) { @@ -6720,7 +6736,9 @@ Expr *RHS = E->getRHS()->IgnoreParenImpCasts(); bool IsComparisonConstant = false; - + + DiagnoseTernaryComparison(S, E); + // 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 z) {} // no warning if((a(zy) {} // no warning - if (z > (a(ay) {} // expected-warning {{ternary comparisons do not work as expected}} \ + // 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