diff options
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 7 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 26 | ||||
-rw-r--r-- | clang/test/Sema/parentheses.c | 3 |
3 files changed, 32 insertions, 4 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 55109d089be..4c8325621fb 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2156,7 +2156,12 @@ def note_precedence_bitwise_silence : Note< def warn_logical_instead_of_bitwise : Warning< "use of logical %0 with constant operand; switch to bitwise %1 or " "remove constant">, InGroup<DiagGroup<"constant-logical-operand">>; - + +def warn_logical_and_in_logical_or : Warning< + "'&&' within '||'">, InGroup<Parentheses>; +def note_logical_and_in_logical_or_silence : Note< + "place parentheses around the '&&' expression to silence this warning">; + def err_sizeof_nonfragile_interface : Error< "invalid application of '%select{alignof|sizeof}1' to interface %0 in " "non-fragile ABI">; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 7555af375f7..80ee2963a72 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -7329,13 +7329,33 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc, rhs->getSourceRange()); } +static void DiagnoseLogicalAndInLogicalOr(Sema &Self, SourceLocation OpLoc, + Expr *E) { + if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(E)) { + if (Bop->getOpcode() == BO_LAnd) { + SuggestParentheses(Self, OpLoc, + Self.PDiag(diag::warn_logical_and_in_logical_or) + << E->getSourceRange(), + Self.PDiag(diag::note_logical_and_in_logical_or_silence), + E->getSourceRange(), + Self.PDiag(0), SourceRange()); + } + } +} + /// DiagnoseBinOpPrecedence - Emit warnings for expressions with tricky -/// precedence. This currently diagnoses only "arg1 'bitwise' arg2 'eq' arg3". -/// But it could also warn about arg1 && arg2 || arg3, as GCC 4.3+ does. +/// precedence. static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc, SourceLocation OpLoc, Expr *lhs, Expr *rhs){ + // Diagnose "arg1 'bitwise' arg2 'eq' arg3". if (BinaryOperator::isBitwiseOp(Opc)) - DiagnoseBitwisePrecedence(Self, Opc, OpLoc, lhs, rhs); + return DiagnoseBitwisePrecedence(Self, Opc, OpLoc, lhs, rhs); + + /// Warn about arg1 && arg2 || arg3, as GCC 4.3+ does. + if (Opc == BO_LOr) { + DiagnoseLogicalAndInLogicalOr(Self, OpLoc, lhs); + DiagnoseLogicalAndInLogicalOr(Self, OpLoc, rhs); + } } // Binary Operators. 'Tok' is the token for the operator. diff --git a/clang/test/Sema/parentheses.c b/clang/test/Sema/parentheses.c index e53f0eb99bc..a219c9b342d 100644 --- a/clang/test/Sema/parentheses.c +++ b/clang/test/Sema/parentheses.c @@ -25,4 +25,7 @@ void bitwise_rel(unsigned i) { // Eager logical op (void)(i == 1 | i == 2 | i == 3); (void)(i != 1 & i != 2 & i != 3); + + (void)(i || i && i); // expected-warning {{'&&' within '||'}} \ + // expected-note {{place parentheses around the '&&' expression to silence this warning}} } |