diff --git a/clang/docs/DiagnosticsReference.rst b/clang/docs/DiagnosticsReference.rst --- a/clang/docs/DiagnosticsReference.rst +++ b/clang/docs/DiagnosticsReference.rst @@ -2850,6 +2850,15 @@ +---------------------------------------------------------------------------+ +-Wcompare-op-parentheses +-------------------------------- +**Diagnostic text:** + ++----------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'`| ++----------------------------------------------------------------------------------------------------------+ + + -Wcomplex-component-init ------------------------ **Diagnostic text:** @@ -9873,7 +9882,7 @@ ------------- Some of the diagnostics controlled by this flag are enabled by default. -Also controls `-Wbitwise-conditional-parentheses`_, `-Wbitwise-op-parentheses`_, `-Wdangling-else`_, `-Wlogical-not-parentheses`_, `-Wlogical-op-parentheses`_, `-Woverloaded-shift-op-parentheses`_, `-Wparentheses-equality`_, `-Wshift-op-parentheses`_. +Also controls `-Wbitwise-conditional-parentheses`_, `-Wbitwise-op-parentheses`_, `-Wcompare-op-parentheses`_, `-Wdangling-else`_, `-Wlogical-not-parentheses`_, `-Wlogical-op-parentheses`_, `-Woverloaded-shift-op-parentheses`_, `-Wparentheses-equality`_, `-Wshift-op-parentheses`_. **Diagnostic text:** diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -341,6 +341,7 @@ def GlobalConstructors : DiagGroup<"global-constructors">; def BitwiseConditionalParentheses: DiagGroup<"bitwise-conditional-parentheses">; def BitwiseOpParentheses: DiagGroup<"bitwise-op-parentheses">; +def CompareOpParentheses: DiagGroup<"compare-op-parentheses">; def LogicalOpParentheses: DiagGroup<"logical-op-parentheses">; def LogicalNotParentheses: DiagGroup<"logical-not-parentheses">; def ShiftOpParentheses: DiagGroup<"shift-op-parentheses">; @@ -786,7 +787,8 @@ // do not want these warnings. def ParenthesesOnEquality : DiagGroup<"parentheses-equality">; def Parentheses : DiagGroup<"parentheses", - [LogicalOpParentheses, + [CompareOpParentheses, + LogicalOpParentheses, LogicalNotParentheses, BitwiseConditionalParentheses, BitwiseOpParentheses, diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6130,6 +6130,18 @@ def warn_bitwise_op_in_bitwise_op : Warning< "'%0' within '%1'">, InGroup, DefaultIgnore; +def warn_compare_parentheses : Warning< + "chained comparisons may need parentheses for clarity">, + InGroup, DefaultIgnore; + +def warn_relation_parentheses : Warning< + "chained comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'">, + InGroup, DefaultIgnore; +def note_compare_with_parens : Note< + "place parentheses around the '%0' comparison to silence this warning">; +def note_compare_separate_sides : Note< + "separate the expression into two clauses to give it the intended mathematical meaning">; + def warn_logical_and_in_logical_or : Warning< "'&&' within '||'">, InGroup, DefaultIgnore; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -14002,6 +14002,83 @@ ParensRange); } +// Emit diagnostics for ambiguous compares, loosely x<=y<=z, or +// more precisely... +// +// Accepts (x ['<'|'<='|'>'|'>='] y ['<'|'<='|'>'|'>='] z), suggests: +// 1) ((x ['<'|'<='|'>'|'>='] y) ['<'|'<='|'>'|'>='] z), or +// 2) (x ['<'|'<='|'>'|'>='] (y ['<'|'<='|'>'|'>='] z)). or +// 3) (x ['<'|'<='|'>'|'>='] y) && (y ['<'|'<='|'>'|'>='] z) +static void EmitDiagnosticForAmbiguousRelationOp(Sema &Self, + BinaryOperatorKind Opc, + SourceLocation OpLoc, + Expr *LHSExpr, Expr *RHSExpr) { + BinaryOperator *LHSBO = dyn_cast(LHSExpr); + + SourceRange DiagRange = SourceRange(LHSExpr->getBeginLoc(), OpLoc); + + Self.Diag(OpLoc, diag::warn_relation_parentheses) << DiagRange << OpLoc; + SuggestParentheses(Self, LHSExpr->getBeginLoc(), + Self.PDiag(diag::note_compare_with_parens) + << LHSBO->getOpcodeStr(), + SourceRange(LHSExpr->getBeginLoc(), LHSExpr->getEndLoc())); + SuggestParentheses( + Self, OpLoc, + Self.PDiag(diag::note_compare_with_parens) + << BinaryOperator::getOpcodeStr(Opc), + SourceRange(LHSBO->getRHS()->getBeginLoc(), RHSExpr->getEndLoc())); + + std::string LHSLOpStr = "xyz"; // = LHSBO->getRHS()->getName();//"xyz"; + + Expr *lhs = LHSBO->getRHS(); + if (DeclRefExpr *DRE = + dyn_cast(lhs->IgnoreImplicit()->IgnoreParens())) { + if (VarDecl *VD = dyn_cast(DRE->getDecl())) { + LHSLOpStr = VD->getQualifiedNameAsString(); + } + } + + Self.Diag(LHSExpr->getBeginLoc(), diag::note_compare_separate_sides) + << FixItHint::CreateInsertion(LHSExpr->getBeginLoc(), "(") + << FixItHint::CreateInsertion(LHSExpr->getEndLoc(), ") && ") + << FixItHint::CreateInsertion(LHSBO->getRHS()->getBeginLoc(), + "( " + LHSLOpStr) + << FixItHint::CreateInsertion(RHSExpr->getEndLoc(), ")"); +} + +static void EmitDiagnosticForAmbiguousCompareOp(Sema &Self, + BinaryOperatorKind Opc, + SourceLocation OpLoc, + Expr *LHSExpr, Expr *RHSExpr) { + BinaryOperator *LHSBO = dyn_cast(LHSExpr); + BinaryOperator *RHSBO = dyn_cast(RHSExpr); + + bool isLeftCompare = LHSBO && LHSBO->isComparisonOp(); + bool isRightCompare = RHSBO && RHSBO->isComparisonOp(); + + SourceRange DiagRange = isLeftCompare + ? SourceRange(LHSExpr->getBeginLoc(), OpLoc) + : SourceRange(OpLoc, RHSExpr->getEndLoc()); + + StringRef OpStr = + isLeftCompare ? LHSBO->getOpcodeStr() : RHSBO->getOpcodeStr(); + SourceRange ParensRange = + isLeftCompare + ? SourceRange(LHSBO->getRHS()->getBeginLoc(), RHSExpr->getEndLoc()) + : SourceRange(LHSExpr->getBeginLoc(), RHSBO->getLHS()->getEndLoc()); + + Self.Diag(OpLoc, diag::warn_compare_parentheses) << DiagRange << OpLoc; + // see line 13980 ... for reference + SuggestParentheses(Self, OpLoc, + Self.PDiag(diag::note_compare_with_parens) << OpStr, + DiagRange); + + SuggestParentheses(Self, OpLoc, + Self.PDiag(diag::note_compare_with_parens) + << BinaryOperator::getOpcodeStr(Opc), + DiagRange); +} + /// It accepts a '&&' expr that is inside a '||' one. /// Emit a diagnostic together with a fixit hint that wraps the '&&' expression /// in parentheses. @@ -14033,6 +14110,24 @@ E->EvaluateAsBooleanCondition(Res, S.getASTContext()) && !Res; } +// Finds ambiguous compares, loosely x<=y<=z, and emits diagnostics if found. +static void DiagnoseAmbiguousComparison(Sema &S, BinaryOperatorKind Opc, + SourceLocation OpLoc, Expr *LHSExpr, + Expr *RHSExpr) { + BinaryOperator *LBop = dyn_cast(LHSExpr); + BinaryOperator *RBop = dyn_cast(RHSExpr); + bool isRelationOp = + (LBop && LBop->isRelationalOp()) || (RBop && RBop->isRelationalOp()); + bool isCompareOp = + (LBop && LBop->isComparisonOp()) || (RBop && RBop->isComparisonOp()); + if (isRelationOp && BinaryOperator::isRelationalOp(Opc)) { + return EmitDiagnosticForAmbiguousRelationOp(S, Opc, OpLoc, LHSExpr, + RHSExpr); + } else if (isCompareOp) { + return EmitDiagnosticForAmbiguousCompareOp(S, Opc, OpLoc, LHSExpr, RHSExpr); + } +} + /// Look for '&&' in the left hand of a '||' expr. static void DiagnoseLogicalAndInLogicalOrLHS(Sema &S, SourceLocation OpLoc, Expr *LHSExpr, Expr *RHSExpr) { @@ -14160,8 +14255,15 @@ // Warn on overloaded shift operators and comparisons, such as: // cout << 5 == 4; - if (BinaryOperator::isComparisonOp(Opc)) + if (BinaryOperator::isComparisonOp(Opc)) { DiagnoseShiftCompare(Self, OpLoc, LHSExpr, RHSExpr); + // Warn on ambiguous compares, loosely x<=y<=z + DiagnoseAmbiguousComparison(Self, Opc, OpLoc, LHSExpr, RHSExpr); + } + + // Warn on ambiguous compares, loosely x<=y<=z + // if (BinaryOperator::isRelationalOp(Opc)) + // DiagnoseAmbiguousComparison(Self, Opc, OpLoc, LHSExpr, RHSExpr); } // Binary Operators. 'Tok' is the token for the operator. diff --git a/clang/test/Misc/warning-wall.c b/clang/test/Misc/warning-wall.c --- a/clang/test/Misc/warning-wall.c +++ b/clang/test/Misc/warning-wall.c @@ -83,6 +83,7 @@ CHECK-NEXT: -Wextern-c-compat CHECK-NEXT: -Wuser-defined-warnings CHECK-NEXT: -Wparentheses +CHECK-NEXT: -Wcompare-op-parentheses CHECK-NEXT: -Wlogical-op-parentheses CHECK-NEXT: -Wlogical-not-parentheses CHECK-NEXT: -Wbitwise-conditional-parentheses diff --git a/clang/test/Sema/warn-compare-op-parentheses.c b/clang/test/Sema/warn-compare-op-parentheses.c new file mode 100644 --- /dev/null +++ b/clang/test/Sema/warn-compare-op-parentheses.c @@ -0,0 +1,263 @@ +// RUN: %clang_cc1 -fsyntax-only -Wcompare-op-parentheses -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wparentheses -verify %s + +int tests(int p1, int p2, int p3, int p4, int p5, int p6) { + int b = 0; + b = p1 < p2 < p3; + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + b = p1 < p2 <= p3; + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '<=' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + b = p1 <= p2 <= p3; + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '<=' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '<=' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + b = p1 <= p2 < p3; + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '<=' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + + b = p1 > p2 > p3; + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '>' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '>' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + b = p1 > p2 >= p3; + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '>' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '>=' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + b = p1 >= p2 >= p3; + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '>=' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '>=' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + b = p1 >= p2 > p3; + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '>=' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '>' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + + b = p1 > p2 < p3; + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '>' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + b = p1 p3; + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '>' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + + b = p1 > p2 <= p3; + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '>' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '<=' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + b = p1 < p2 >= p3; + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '>=' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + + b = p1 >= p2 < p3; + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '>=' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + b = p1 <= p2 > p3; + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '<=' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '>' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + + b = p1 >= p2 <= p3; + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '>=' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '<=' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + b = p1 <= p2 >= p3; + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '<=' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '>=' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + + b = p1 < p2 < p3 < p4; + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + // expected-warning@-5 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-6 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-7 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-8 {{separate the expression into two clauses to give it the intended mathematical meaning}} + b = (p1 < p2) < p3 < p4; + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + b = p1 < (p2 < p3) < p4; + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + b = p1 < p2 < (p3 < p4); + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + b = (p1 < p2 < p3) < p4; + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + b = p1 < (p2 < p3 < p4); + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + + b = p1 < p2 <= p3 < p4; + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '<=' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + // expected-warning@-5 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-6 {{place parentheses around the '<=' comparison to silence this warning}} + // expected-note@-7 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-8 {{separate the expression into two clauses to give it the intended mathematical meaning}} + + b = (p1 < p2) < p3; // no warning + b = p1 < (p2 < p3); // no warning + b = (p1 < p2) <= p3; // no warning + b = p1 < (p2 <= p3); // no warning + b = (p1 <= p2) <= p3; // no warning + b = p1 <= (p2 <= p3); // no warning + b = (p1 <= p2) < p3; // no warning + b = p1 <= (p2 < p3); // no warning + b = (p1 > p2) > p3; // no warning + b = p1 > (p2 > p3); // no warning + b = (p1 > p2) >= p3; // no warning + b = p1 > (p2 >= p3); // no warning + b = (p1 >= p2) >= p3; // no warning + b = p1 >= (p2 >= p3); // no warning + b = (p1 >= p2) > p3; // no warning + b = p1 >= (p2 > p3); // no warning + b = (p1 > p2) < p3; // no warning + b = p1 > (p2 < p3); // no warning + b = (p1 < p2) > p3; // no warning + b = p1 < (p2 > p3); // no warning + b = (p1 > p2) <= p3; // no warning + b = p1 > (p2 <= p3); // no warning + b = (p1 < p2) >= p3; // no warning + b = p1 < (p2 >= p3); // no warning + b = (p1 >= p2) < p3; // no warning + b = p1 >= (p2 < p3); // no warning + b = (p1 <= p2) > p3; // no warning + b = p1 <= (p2 > p3); // no warning + b = (p1 >= p2) <= p3; // no warning + b = p1 >= (p2 <= p3); // no warning + b = (p1 <= p2) >= p3; // no warning + b = p1 <= (p2 >= p3); // no warning + + b = (p1 < p2) < (p3 < p4); // no warning + b = p1 < ((p2 < p3) < p4); // no warning + b = ((p1 < p2) < p3) < p4; // no warning + + b = (p1 < p2) <= (p3 < p4); // no warning + + b = (p1 < p2 < p3); + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + b = ((p1 < p2) && (p2 < p3)); // no warning + b = ((p1 < p2) && (p2)); // no warning + b = ((p1) && (p3 < p2)); // no warning + b = (p1 < p2) < p3 < p1; + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + b = (p1 <= p2 < p3); + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '<=' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + b = (p1 < p2 <= p3); + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '<=' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + b = (p1 <= p2 <= p3); + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '<=' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '<=' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + + b = (p1 > p2 < p3); + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '>' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + + b = (p1 > p2 > p3); + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '>' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '>' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + + b = (p1 >= p2 > p3); + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '>=' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '>' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + + b = (p1 >= p2 >= p3); + // expected-warning@-1 {{comparisons like 'x<=y<=z' are interpreted as '(x<=y ? 1 : 0) <= z'}} + // expected-note@-2 {{place parentheses around the '>=' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '>=' comparison to silence this warning}} + // expected-note@-4 {{separate the expression into two clauses to give it the intended mathematical meaning}} + + b = (p1 >= p2 || p3); // no warning + b = (p1 && p3 < p2); // no warning + b = ((p1 < p2) < p3); // no warning + b = (p1 < (p2 < p3)); // no warning + + b = (0 <= (p1 < p2)); + // expected-warning@-1 {{result of comparison of constant 0 with boolean expression is always true}} + + // FIXME - These do not currently trigger any warnings + b = (p1 == p2 < p3); // maybe intentional, but definitely deserving of a warning + // expected-warning@-1 {{chained comparisons may need parentheses for clarity}} + // expected-note@-2 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '==' comparison to silence this warning}} + b = (p1 == p2 == p3); // definitely buggy and deserving of a warning + // expected-warning@-1 {{chained comparisons may need parentheses for clarity}} + // expected-note@-2 {{place parentheses around the '==' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '==' comparison to silence this warning}} + b = (p1 != p2 != p3); // definitely buggy and deserving of a warning + // expected-warning@-1 {{chained comparisons may need parentheses for clarity}} + // expected-note@-2 {{place parentheses around the '!=' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '!=' comparison to silence this warning}} + b = (p1 < p2 == p3 < p4); // maybe intentional, but definitely deserving of a warning + // expected-warning@-1 {{chained comparisons may need parentheses for clarity}} + // expected-note@-2 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '==' comparison to silence this warning}} + b = (p1 == p2 < p3 == p4); // definitely buggy and deserving of a warning + // expected-warning@-1 {{chained comparisons may need parentheses for clarity}} + // expected-note@-2 {{place parentheses around the '<' comparison to silence this warning}} + // expected-note@-3 {{place parentheses around the '==' comparison to silence this warning}} + // expected-warning@-4 {{chained comparisons may need parentheses for clarity}} + // expected-note@-5 {{place parentheses around the '==' comparison to silence this warning}} + // expected-note@-6 {{place parentheses around the '==' comparison to silence this warning}} + + return b; +}