forked from OSchip/llvm-project
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; llvm-svn: 133196
This commit is contained in:
parent
3e9f21f739
commit
701fb36b95
|
@ -2994,6 +2994,8 @@ def warn_runsigned_always_true_comparison : Warning<
|
|||
def warn_comparison_of_mixed_enum_types : Warning<
|
||||
"comparison of two values with different enumeration types (%0 and %1)">,
|
||||
InGroup<DiagGroup<"enum-compare">>;
|
||||
def warn_null_in_arithmetic_operation : Warning<
|
||||
"use of NULL in arithmetic operation">;
|
||||
|
||||
def err_invalid_this_use : Error<
|
||||
"invalid use of 'this' outside of a nonstatic member function">;
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -fblocks -verify %s
|
||||
#include <stddef.h>
|
||||
|
||||
void f() {
|
||||
int a;
|
||||
bool b;
|
||||
|
||||
a = 0 ? NULL + a : a + NULL; // expected-warning 2{{use of NULL in arithmetic operation}}
|
||||
a = 0 ? NULL - a : a - NULL; // expected-warning 2{{use of NULL in arithmetic operation}}
|
||||
a = 0 ? NULL / a : a / NULL; // expected-warning 2{{use of NULL in arithmetic operation}} \
|
||||
// expected-warning {{division by zero is undefined}}
|
||||
a = 0 ? NULL * a : a * NULL; // expected-warning 2{{use of NULL in arithmetic operation}}
|
||||
a = 0 ? NULL >> a : a >> NULL; // expected-warning 2{{use of NULL in arithmetic operation}}
|
||||
a = 0 ? NULL << a : a << NULL; // expected-warning 2{{use of NULL in arithmetic operation}}
|
||||
a = 0 ? NULL % a : a % NULL; // expected-warning 2{{use of NULL in arithmetic operation}} \
|
||||
expected-warning {{remainder by zero is undefined}}
|
||||
a = 0 ? NULL & a : a & NULL; // expected-warning 2{{use of NULL in arithmetic operation}}
|
||||
a = 0 ? NULL | a : a | NULL; // expected-warning 2{{use of NULL in arithmetic operation}}
|
||||
a = 0 ? NULL ^ a : a ^ NULL; // expected-warning 2{{use of NULL in arithmetic operation}}
|
||||
|
||||
// Using two NULLs should only give one error instead of two.
|
||||
a = NULL + NULL; // expected-warning{{use of NULL in arithmetic operation}}
|
||||
a = NULL - NULL; // expected-warning{{use of NULL in arithmetic operation}}
|
||||
a = NULL / NULL; // expected-warning{{use of NULL in arithmetic operation}} \
|
||||
// expected-warning{{division by zero is undefined}}
|
||||
a = NULL * NULL; // expected-warning{{use of NULL in arithmetic operation}}
|
||||
a = NULL >> NULL; // expected-warning{{use of NULL in arithmetic operation}}
|
||||
a = NULL << NULL; // expected-warning{{use of NULL in arithmetic operation}}
|
||||
a = NULL % NULL; // expected-warning{{use of NULL in arithmetic operation}} \
|
||||
// expected-warning{{remainder by zero is undefined}}
|
||||
a = NULL & NULL; // expected-warning{{use of NULL in arithmetic operation}}
|
||||
a = NULL | NULL; // expected-warning{{use of NULL in arithmetic operation}}
|
||||
a = NULL ^ NULL; // expected-warning{{use of NULL in arithmetic operation}}
|
||||
|
||||
a += NULL; // expected-warning{{use of NULL in arithmetic operation}}
|
||||
a -= NULL; // expected-warning{{use of NULL in arithmetic operation}}
|
||||
a /= NULL; // expected-warning{{use of NULL in arithmetic operation}} \
|
||||
// expected-warning{{division by zero is undefined}}
|
||||
a *= NULL; // expected-warning{{use of NULL in arithmetic operation}}
|
||||
a >>= NULL; // expected-warning{{use of NULL in arithmetic operation}}
|
||||
a <<= NULL; // expected-warning{{use of NULL in arithmetic operation}}
|
||||
a %= NULL; // expected-warning{{use of NULL in arithmetic operation}} \
|
||||
// expected-warning{{remainder by zero is undefined}}
|
||||
a &= NULL; // expected-warning{{use of NULL in arithmetic operation}}
|
||||
a |= NULL; // expected-warning{{use of NULL in arithmetic operation}}
|
||||
a ^= NULL; // expected-warning{{use of NULL in arithmetic operation}}
|
||||
|
||||
b = a < NULL || NULL < a; // expected-warning 2{{use of NULL in arithmetic operation}}
|
||||
b = a > NULL || NULL > a; // expected-warning 2{{use of NULL in arithmetic operation}}
|
||||
b = a <= NULL || NULL <= a; // expected-warning 2{{use of NULL in arithmetic operation}}
|
||||
b = a >= NULL || NULL >= a; // expected-warning 2{{use of NULL in arithmetic operation}}
|
||||
b = a == NULL || NULL == a; // expected-warning 2{{use of NULL in arithmetic operation}}
|
||||
b = a != NULL || NULL != a; // expected-warning 2{{use of NULL in arithmetic operation}}
|
||||
|
||||
b = &a < NULL || NULL < &a || &a > NULL || NULL > &a;
|
||||
b = &a <= NULL || NULL <= &a || &a >= NULL || NULL >= &a;
|
||||
b = &a == NULL || NULL == &a || &a != NULL || NULL != &a;
|
||||
|
||||
b = 0 == a;
|
||||
b = 0 == &a;
|
||||
|
||||
b = ((NULL)) != a; // expected-warning{{use of NULL in arithmetic operation}}
|
||||
|
||||
void (^c)();
|
||||
b = c == NULL || NULL == c || c != NULL || NULL != c;
|
||||
|
||||
class X;
|
||||
void (X::*d) ();
|
||||
b = d == NULL || NULL == d || d != NULL || NULL != d;
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -fblocks -std=c++0x -verify %s
|
||||
|
||||
void f() {
|
||||
int a;
|
||||
bool b;
|
||||
|
||||
a = 0 ? nullptr + a : a + nullptr; // expected-error 2{{invalid operands to binary expression}}
|
||||
a = 0 ? nullptr - a : a - nullptr; // expected-error 2{{invalid operands to binary expression}}
|
||||
a = 0 ? nullptr / a : a / nullptr; // expected-error 2{{invalid operands to binary expression}}
|
||||
a = 0 ? nullptr * a : a * nullptr; // expected-error 2{{invalid operands to binary expression}}
|
||||
a = 0 ? nullptr >> a : a >> nullptr; // expected-error 2{{invalid operands to binary expression}}
|
||||
a = 0 ? nullptr << a : a << nullptr; // expected-error 2{{invalid operands to binary expression}}
|
||||
a = 0 ? nullptr % a : a % nullptr; // expected-error 2{{invalid operands to binary expression}}
|
||||
a = 0 ? nullptr & a : a & nullptr; // expected-error 2{{invalid operands to binary expression}}
|
||||
a = 0 ? nullptr | a : a | nullptr; // expected-error 2{{invalid operands to binary expression}}
|
||||
a = 0 ? nullptr ^ a : a ^ nullptr; // expected-error 2{{invalid operands to binary expression}}
|
||||
|
||||
// Using two nullptrs should only give one error instead of two.
|
||||
a = nullptr + nullptr; // expected-error{{invalid operands to binary expression}}
|
||||
a = nullptr - nullptr; // expected-error{{invalid operands to binary expression}}
|
||||
a = nullptr / nullptr; // expected-error{{invalid operands to binary expression}}
|
||||
a = nullptr * nullptr; // expected-error{{invalid operands to binary expression}}
|
||||
a = nullptr >> nullptr; // expected-error{{invalid operands to binary expression}}
|
||||
a = nullptr << nullptr; // expected-error{{invalid operands to binary expression}}
|
||||
a = nullptr % nullptr; // expected-error{{invalid operands to binary expression}}
|
||||
a = nullptr & nullptr; // expected-error{{invalid operands to binary expression}}
|
||||
a = nullptr | nullptr; // expected-error{{invalid operands to binary expression}}
|
||||
a = nullptr ^ nullptr; // expected-error{{invalid operands to binary expression}}
|
||||
|
||||
a += nullptr; // expected-error{{invalid operands to binary expression}}
|
||||
a -= nullptr; // expected-error{{invalid operands to binary expression}}
|
||||
a /= nullptr; // expected-error{{invalid operands to binary expression}}
|
||||
a *= nullptr; // expected-error{{invalid operands to binary expression}}
|
||||
a >>= nullptr; // expected-error{{invalid operands to binary expression}}
|
||||
a <<= nullptr; // expected-error{{invalid operands to binary expression}}
|
||||
a %= nullptr; // expected-error{{invalid operands to binary expression}}
|
||||
a &= nullptr; // expected-error{{invalid operands to binary expression}}
|
||||
a |= nullptr; // expected-error{{invalid operands to binary expression}}
|
||||
a ^= nullptr; // expected-error{{invalid operands to binary expression}}
|
||||
|
||||
b = a < nullptr || nullptr < a; // expected-error 2{{invalid operands to binary expression}}
|
||||
b = a > nullptr || nullptr > a; // expected-error 2{{invalid operands to binary expression}}
|
||||
b = a <= nullptr || nullptr <= a; // expected-error 2{{invalid operands to binary expression}}
|
||||
b = a >= nullptr || nullptr >= a; // expected-error 2{{invalid operands to binary expression}}
|
||||
b = a == nullptr || nullptr == a; // expected-error 2{{invalid operands to binary expression}}
|
||||
b = a != nullptr || nullptr != a; // expected-error 2{{invalid operands to binary expression}}
|
||||
|
||||
b = &a < nullptr || nullptr < &a || &a > nullptr || nullptr > &a;
|
||||
b = &a <= nullptr || nullptr <= &a || &a >= nullptr || nullptr >= &a;
|
||||
b = &a == nullptr || nullptr == &a || &a != nullptr || nullptr != &a;
|
||||
|
||||
b = 0 == a;
|
||||
b = 0 == &a;
|
||||
|
||||
b = ((nullptr)) != a; // expected-error{{invalid operands to binary expression}}
|
||||
|
||||
void (^c)();
|
||||
c = nullptr;
|
||||
b = c == nullptr || nullptr == c || c != nullptr || nullptr != c;
|
||||
|
||||
class X;
|
||||
void (X::*d) ();
|
||||
d = nullptr;
|
||||
b = d == nullptr || nullptr == d || d != nullptr || nullptr != d;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
#define NULL __null
|
||||
|
||||
@interface X
|
||||
@end
|
||||
|
||||
void f() {
|
||||
bool b;
|
||||
X *d;
|
||||
b = d < NULL || NULL < d || d > NULL || NULL > d;
|
||||
b = d <= NULL || NULL <= d || d >= NULL || NULL >= d;
|
||||
b = d == NULL || NULL == d || d != NULL || NULL != d;
|
||||
}
|
Loading…
Reference in New Issue