forked from OSchip/llvm-project
[Sema] Add -Wpointer-compare
This patch adds a warning that diagnoses comparisons of pointers to '\0'. This is often indicative of a bug (e.g. the user might've forgotten to dereference the pointer). Patch by Elaina Guan! Differential Revision: https://reviews.llvm.org/D65595 llvm-svn: 367940
This commit is contained in:
parent
dcdbe6515b
commit
f708f0a243
|
@ -3296,6 +3296,10 @@ def warn_impcast_bool_to_null_pointer : Warning<
|
|||
def warn_non_literal_null_pointer : Warning<
|
||||
"expression which evaluates to zero treated as a null pointer constant of "
|
||||
"type %0">, InGroup<NonLiteralNullConversion>;
|
||||
def warn_pointer_compare : Warning<
|
||||
"comparing a pointer to a null character constant; did you mean "
|
||||
"to compare to %select{NULL|(void *)0}0?">,
|
||||
InGroup<DiagGroup<"pointer-compare">>;
|
||||
def warn_impcast_null_pointer_to_integer : Warning<
|
||||
"implicit conversion of %select{NULL|nullptr}0 constant to %1">,
|
||||
InGroup<NullConversion>;
|
||||
|
|
|
@ -10022,6 +10022,7 @@ public:
|
|||
QualType CheckShiftOperands( // C99 6.5.7
|
||||
ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
|
||||
BinaryOperatorKind Opc, bool IsCompAssign = false);
|
||||
void CheckPtrComparisonWithNullChar(ExprResult &E, ExprResult &NullE);
|
||||
QualType CheckCompareOperands( // C99 6.5.8/9
|
||||
ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
|
||||
BinaryOperatorKind Opc);
|
||||
|
|
|
@ -10443,6 +10443,32 @@ static QualType checkArithmeticOrEnumeralCompare(Sema &S, ExprResult &LHS,
|
|||
return S.Context.getLogicalOperationType();
|
||||
}
|
||||
|
||||
void Sema::CheckPtrComparisonWithNullChar(ExprResult &E, ExprResult &NullE) {
|
||||
if (!NullE.get()->getType()->isAnyPointerType())
|
||||
return;
|
||||
int NullValue = PP.isMacroDefined("NULL") ? 0 : 1;
|
||||
if (!E.get()->getType()->isAnyPointerType() &&
|
||||
E.get()->isNullPointerConstant(Context,
|
||||
Expr::NPC_ValueDependentIsNotNull) ==
|
||||
Expr::NPCK_ZeroExpression) {
|
||||
if (const auto *CL = dyn_cast<CharacterLiteral>(E.get())) {
|
||||
if (CL->getValue() == 0)
|
||||
Diag(E.get()->getExprLoc(), diag::warn_pointer_compare)
|
||||
<< NullValue
|
||||
<< FixItHint::CreateReplacement(E.get()->getExprLoc(),
|
||||
NullValue ? "NULL" : "(void *)0");
|
||||
} else if (const auto *CE = dyn_cast<CStyleCastExpr>(E.get())) {
|
||||
TypeSourceInfo *TI = CE->getTypeInfoAsWritten();
|
||||
QualType T = Context.getCanonicalType(TI->getType()).getUnqualifiedType();
|
||||
if (T == Context.CharTy)
|
||||
Diag(E.get()->getExprLoc(), diag::warn_pointer_compare)
|
||||
<< NullValue
|
||||
<< FixItHint::CreateReplacement(E.get()->getExprLoc(),
|
||||
NullValue ? "NULL" : "(void *)0");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// C99 6.5.8, C++ [expr.rel]
|
||||
QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
|
||||
SourceLocation Loc,
|
||||
|
@ -10476,6 +10502,10 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
|
|||
}
|
||||
|
||||
checkArithmeticNull(*this, LHS, RHS, Loc, /*IsCompare=*/true);
|
||||
if (!getLangOpts().CPlusPlus && BinaryOperator::isEqualityOp(Opc)) {
|
||||
CheckPtrComparisonWithNullChar(LHS, RHS);
|
||||
CheckPtrComparisonWithNullChar(RHS, LHS);
|
||||
}
|
||||
|
||||
// Handle vector comparisons separately.
|
||||
if (LHS.get()->getType()->isVectorType() ||
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify -Wall %s
|
||||
|
||||
int test1(int *a) {
|
||||
return a == '\0'; // expected-warning {{comparing a pointer to a null character constant; did you mean to compare to (void *)0?}}
|
||||
}
|
||||
|
||||
int test2(int *a) {
|
||||
return '\0' == a; // expected-warning {{comparing a pointer to a null character constant; did you mean to compare to (void *)0?}}
|
||||
}
|
||||
|
||||
int test3(int *a) {
|
||||
return a == L'\0'; // expected-warning {{comparing a pointer to a null character constant; did you mean to compare to (void *)0?}}
|
||||
}
|
||||
|
||||
int test4(int *a) {
|
||||
return a == u'\0'; // expected-warning {{comparing a pointer to a null character constant; did you mean to compare to (void *)0?}}
|
||||
}
|
||||
|
||||
int test5(int *a) {
|
||||
return a == U'\0'; // expected-warning {{comparing a pointer to a null character constant; did you mean to compare to (void *)0?}}
|
||||
}
|
||||
|
||||
int test6(int *a) {
|
||||
return a == (char)0; // expected-warning {{comparing a pointer to a null character constant; did you mean to compare to (void *)0?}}
|
||||
}
|
||||
|
||||
typedef char my_char;
|
||||
int test7(int *a) {
|
||||
return a == (my_char)0;
|
||||
// expected-warning@-1 {{comparing a pointer to a null character constant; did you mean to compare to (void *)0?}}
|
||||
}
|
||||
|
||||
int test8(int *a) {
|
||||
return a != '\0'; // expected-warning {{comparing a pointer to a null character constant; did you mean to compare to (void *)0?}}
|
||||
}
|
||||
|
||||
#define NULL (void *)0
|
||||
int test9(int *a) {
|
||||
return a == '\0'; // expected-warning {{comparing a pointer to a null character constant; did you mean to compare to NULL?}}
|
||||
}
|
||||
|
||||
#define MYCHAR char
|
||||
int test10(int *a) {
|
||||
return a == (MYCHAR)0; // expected-warning {{comparing a pointer to a null character constant; did you mean to compare to NULL?}}
|
||||
}
|
||||
|
||||
int test11(int *a) {
|
||||
return a > '\0';
|
||||
}
|
Loading…
Reference in New Issue