From: Craig Topper Date: Sun, 13 Dec 2015 05:41:41 +0000 (+0000) Subject: [Sema] Add -Wparentheses warnings for '^' in '|' expressions and '&' in '^' expressio... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=277287eaa915d298f3ccd59b680a5f54a7ad19a2;p=clang [Sema] Add -Wparentheses warnings for '^' in '|' expressions and '&' in '^' expressions to compliment '&' in '|' that is already present. Matches gcc behavior. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@255450 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 19dbbc76fc..cac26127a2 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -4977,8 +4977,8 @@ def note_logical_instead_of_bitwise_change_operator : Note< def note_logical_instead_of_bitwise_remove_constant : Note< "remove constant to silence this warning">; -def warn_bitwise_and_in_bitwise_or : Warning< - "'&' within '|'">, InGroup; +def warn_bitwise_op_in_bitwise_op : Warning< + "'%0' within '%1'">, InGroup; def warn_logical_and_in_logical_or : Warning< "'&&' within '||'">, InGroup; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 1b3f8dab3f..b8cb50c9ae 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -10504,21 +10504,6 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc, ParensRange); } -/// \brief It accepts a '&' expr that is inside a '|' one. -/// Emit a diagnostic together with a fixit hint that wraps the '&' expression -/// in parentheses. -static void -EmitDiagnosticForBitwiseAndInBitwiseOr(Sema &Self, SourceLocation OpLoc, - BinaryOperator *Bop) { - assert(Bop->getOpcode() == BO_And); - Self.Diag(Bop->getOperatorLoc(), diag::warn_bitwise_and_in_bitwise_or) - << Bop->getSourceRange() << OpLoc; - SuggestParentheses(Self, Bop->getOperatorLoc(), - Self.PDiag(diag::note_precedence_silence) - << Bop->getOpcodeStr(), - Bop->getSourceRange()); -} - /// \brief It accepts a '&&' expr that is inside a '||' one. /// Emit a diagnostic together with a fixit hint that wraps the '&&' expression /// in parentheses. @@ -10587,12 +10572,21 @@ static void DiagnoseLogicalAndInLogicalOrRHS(Sema &S, SourceLocation OpLoc, } } -/// \brief Look for '&' in the left or right hand of a '|' expr. -static void DiagnoseBitwiseAndInBitwiseOr(Sema &S, SourceLocation OpLoc, - Expr *OrArg) { - if (BinaryOperator *Bop = dyn_cast(OrArg)) { - if (Bop->getOpcode() == BO_And) - return EmitDiagnosticForBitwiseAndInBitwiseOr(S, OpLoc, Bop); +/// \brief Look for bitwise op in the left or right hand of a bitwise op with +/// lower precedence and emit a diagnostic together with a fixit hint that wraps +/// the '&' expression in parentheses. +static void DiagnoseBitwiseOpInBitwiseOp(Sema &S, BinaryOperatorKind Opc, + SourceLocation OpLoc, Expr *SubExpr) { + if (BinaryOperator *Bop = dyn_cast(SubExpr)) { + if (Bop->isBitwiseOp() && Bop->getOpcode() < Opc) { + S.Diag(Bop->getOperatorLoc(), diag::warn_bitwise_op_in_bitwise_op) + << Bop->getOpcodeStr() << BinaryOperator::getOpcodeStr(Opc) + << Bop->getSourceRange() << OpLoc; + SuggestParentheses(S, Bop->getOperatorLoc(), + S.PDiag(diag::note_precedence_silence) + << Bop->getOpcodeStr(), + Bop->getSourceRange()); + } } } @@ -10647,9 +10641,10 @@ static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc, DiagnoseBitwisePrecedence(Self, Opc, OpLoc, LHSExpr, RHSExpr); // Diagnose "arg1 & arg2 | arg3" - if (Opc == BO_Or && !OpLoc.isMacroID()/* Don't warn in macros. */) { - DiagnoseBitwiseAndInBitwiseOr(Self, OpLoc, LHSExpr); - DiagnoseBitwiseAndInBitwiseOr(Self, OpLoc, RHSExpr); + if ((Opc == BO_Or || Opc == BO_Xor) && + !OpLoc.isMacroID()/* Don't warn in macros. */) { + DiagnoseBitwiseOpInBitwiseOp(Self, Opc, OpLoc, LHSExpr); + DiagnoseBitwiseOpInBitwiseOp(Self, Opc, OpLoc, RHSExpr); } // Warn about arg1 || arg2 && arg3, as GCC 4.3+ does. diff --git a/test/Sema/parentheses.c b/test/Sema/parentheses.c index 739561dd2b..8c6c4999f7 100644 --- a/test/Sema/parentheses.c +++ b/test/Sema/parentheses.c @@ -55,6 +55,26 @@ void bitwise_rel(unsigned i) { // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:14-[[@LINE-2]]:14}:"(" // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:19-[[@LINE-3]]:19}:")" + (void)(i ^ i | i); // expected-warning {{'^' within '|'}} \ + // expected-note {{place parentheses around the '^' expression to silence this warning}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:10-[[@LINE-2]]:10}:"(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:15-[[@LINE-3]]:15}:")" + + (void)(i | i ^ i); // expected-warning {{'^' within '|'}} \ + // expected-note {{place parentheses around the '^' expression to silence this warning}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:14-[[@LINE-2]]:14}:"(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:19-[[@LINE-3]]:19}:")" + + (void)(i & i ^ i); // expected-warning {{'&' within '^'}} \ + // expected-note {{place parentheses around the '&' expression to silence this warning}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:10-[[@LINE-2]]:10}:"(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:15-[[@LINE-3]]:15}:")" + + (void)(i ^ i & i); // expected-warning {{'&' within '^'}} \ + // expected-note {{place parentheses around the '&' expression to silence this warning}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:14-[[@LINE-2]]:14}:"(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:19-[[@LINE-3]]:19}:")" + (void)(i || i && i); // expected-warning {{'&&' within '||'}} \ // expected-note {{place parentheses around the '&&' expression to silence this warning}}