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 | 4302824fe26039e00cf48da39f1c799d3c1de368 (patch) | |
tree | 11c83942927bf18c2f4d81eac2b13262a1bdd763 /clang/lib | |
parent | b3549d74da5a6fd077d6c5313df3a36589bd6aeb (diff) | |
download | bcm5719-llvm-4302824fe26039e00cf48da39f1c799d3c1de368.tar.gz bcm5719-llvm-4302824fe26039e00cf48da39f1c799d3c1de368.zip |
Implement a warning for mixing bitwise logical with comparison ops. Fixes PR5297.
llvm-svn: 85117
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 78647e392fb..84a430ab523 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/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())) { |