diff options
author | Sebastian Redl <sebastian.redl@getdesigned.at> | 2009-10-26 15:24:15 +0000 |
---|---|---|
committer | Sebastian Redl <sebastian.redl@getdesigned.at> | 2009-10-26 15:24:15 +0000 |
commit | 9e1d29bb369530c15230e4c92aa67239c283ece2 (patch) | |
tree | aabef2c8556c5b94ed52219e33cc1686bb28b92b /lib/Sema | |
parent | 8d737cc78cb28f39179d6c7ca00eb5d3cf563129 (diff) |
Implement a warning for mixing bitwise logical with comparison ops. Fixes PR5297.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@85117 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 78647e392f..84a430ab52 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -5412,6 +5412,53 @@ Action::OwningExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, OpLoc)); } +static inline bool IsBitwise(int Opc) { + return Opc >= BinaryOperator::And && Opc <= BinaryOperator::Or; +} +static inline bool IsEqOrRel(int Opc) { + return Opc >= BinaryOperator::LT && Opc <= BinaryOperator::NE; +} + +static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperator::Opcode Opc, + SourceLocation OpLoc,Expr *lhs,Expr *rhs){ + typedef BinaryOperator::Opcode Opcode; + int lhsopc = -1, rhsopc = -1; + if (BinaryOperator *BO = dyn_cast<BinaryOperator>(lhs)) + lhsopc = BO->getOpcode(); + if (BinaryOperator *BO = dyn_cast<BinaryOperator>(rhs)) + rhsopc = BO->getOpcode(); + + // Subs are not binary operators. + if (lhsopc == -1 && rhsopc == -1) + return; + + // Bitwise operations are sometimes used as eager logical ops. + // Don't diagnose this. + if ((IsEqOrRel(lhsopc) || IsBitwise(lhsopc)) && + (IsEqOrRel(rhsopc) || IsBitwise(rhsopc))) + return; + + if (IsEqOrRel(lhsopc)) + Self.Diag(OpLoc, diag::warn_precedence_bitwise_rel) + << SourceRange(lhs->getLocStart(), OpLoc) + << BinaryOperator::getOpcodeStr(Opc) + << BinaryOperator::getOpcodeStr(static_cast<Opcode>(lhsopc)); + else if (IsEqOrRel(rhsopc)) + Self.Diag(OpLoc, diag::warn_precedence_bitwise_rel) + << SourceRange(OpLoc, rhs->getLocEnd()) + << BinaryOperator::getOpcodeStr(Opc) + << BinaryOperator::getOpcodeStr(static_cast<Opcode>(rhsopc)); +} + +/// 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. +static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperator::Opcode Opc, + SourceLocation OpLoc, Expr *lhs, Expr *rhs){ + if (IsBitwise(Opc)) + DiagnoseBitwisePrecedence(Self, Opc, OpLoc, lhs, rhs); +} + // Binary Operators. 'Tok' is the token for the operator. Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, tok::TokenKind Kind, @@ -5422,6 +5469,9 @@ Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, assert((lhs != 0) && "ActOnBinOp(): missing left expression"); assert((rhs != 0) && "ActOnBinOp(): missing right expression"); + // Emit warnings for tricky precedence issues, e.g. "bitfield & 0x4 == 0" + DiagnoseBinOpPrecedence(*this, Opc, TokLoc, lhs, rhs); + if (getLangOptions().CPlusPlus && (lhs->getType()->isOverloadableType() || rhs->getType()->isOverloadableType())) { |