diff options
author | Richard Trieu <rtrieu@google.com> | 2011-06-16 21:36:56 +0000 |
---|---|---|
committer | Richard Trieu <rtrieu@google.com> | 2011-06-16 21:36:56 +0000 |
commit | 3e95ba94fd34c5f6420c57d7732f601875074681 (patch) | |
tree | f9d91882f472c5ab6fc330c73d0819f5e98ed7f9 /lib/Sema/SemaExpr.cpp | |
parent | a92d7e7a55a35b28437103130904a6401bf35408 (diff) |
Add a new warning when a NULL constant is used in arithmetic operations. The warning will fire on cases such as:
int x = 1 + NULL;
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133196 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 76612cd6d8..2c988d15e3 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -8925,6 +8925,60 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, rhs = move(resolvedRHS); } + bool LeftNull = Expr::NPCK_GNUNull == + lhs.get()->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNotNull); + bool RightNull = Expr::NPCK_GNUNull == + rhs.get()->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNotNull); + + // Detect when a NULL constant is used improperly in an expression. These + // are mainly cases where the null pointer is used as an integer instead + // of a pointer. + if (LeftNull || RightNull) { + if (Opc == BO_Mul || Opc == BO_Div || Opc == BO_Rem || Opc == BO_Add || + Opc == BO_Sub || Opc == BO_Shl || Opc == BO_Shr || Opc == BO_And || + Opc == BO_Xor || Opc == BO_Or || Opc == BO_MulAssign || + Opc == BO_DivAssign || Opc == BO_AddAssign || Opc == BO_SubAssign || + Opc == BO_RemAssign || Opc == BO_ShlAssign || Opc == BO_ShrAssign || + Opc == BO_AndAssign || Opc == BO_OrAssign || Opc == BO_XorAssign) { + // These are the operations that would not make sense with a null pointer + // no matter what the other expression is. + if (LeftNull && RightNull) { + Diag(OpLoc, diag::warn_null_in_arithmetic_operation) + << lhs.get()->getSourceRange() << rhs.get()->getSourceRange(); + } else if (LeftNull) { + Diag(OpLoc, diag::warn_null_in_arithmetic_operation) + << lhs.get()->getSourceRange(); + } else if (RightNull) { + Diag(OpLoc, diag::warn_null_in_arithmetic_operation) + << rhs.get()->getSourceRange(); + } + } else if (Opc == BO_LE || Opc == BO_LT || Opc == BO_GE || Opc == BO_GT || + Opc == BO_EQ || Opc == BO_NE) { + // These are the operations that would not make sense with a null pointer + // if the other expression the other expression is not a pointer. + QualType LeftType = lhs.get()->getType(); + QualType RightType = rhs.get()->getType(); + bool LeftPointer = LeftType->isPointerType() || + LeftType->isBlockPointerType() || + LeftType->isMemberPointerType() || + LeftType->isObjCObjectPointerType(); + bool RightPointer = RightType->isPointerType() || + RightType->isBlockPointerType() || + RightType->isMemberPointerType() || + RightType->isObjCObjectPointerType(); + if ((LeftNull != RightNull) && !LeftPointer && !RightPointer) { + if (LeftNull) + Diag(OpLoc, diag::warn_null_in_arithmetic_operation) + << lhs.get()->getSourceRange(); + if (RightNull) + Diag(OpLoc, diag::warn_null_in_arithmetic_operation) + << rhs.get()->getSourceRange(); + } + } + } + switch (Opc) { case BO_Assign: ResultTy = CheckAssignmentOperands(lhs.get(), rhs, OpLoc, QualType()); |