forked from OSchip/llvm-project
patch to issue warning on comparing parameters with
nonnull attribute when comparison is always true/false. Patch by Steven Wu with few fixes and minor refactoring and adding tests by me. rdar://18712242 llvm-svn: 220496
This commit is contained in:
parent
28d6b27bba
commit
4c8cb14c1a
|
@ -2500,6 +2500,10 @@ def warn_impcast_pointer_to_bool : Warning<
|
|||
"address of%select{| function| array}0 '%1' will always evaluate to "
|
||||
"'true'">,
|
||||
InGroup<PointerBoolConversion>;
|
||||
def warn_cast_nonnull_to_bool : Warning<
|
||||
"nonnull parameter '%0' will always evaluate to "
|
||||
"'true'">,
|
||||
InGroup<PointerBoolConversion>;
|
||||
def warn_this_bool_conversion : Warning<
|
||||
"'this' pointer cannot be null in well-defined C++ code; pointer may be "
|
||||
"assumed to always convert to true">, InGroup<UndefinedBoolConversion>;
|
||||
|
@ -2512,6 +2516,10 @@ def warn_null_pointer_compare : Warning<
|
|||
"comparison of %select{address of|function|array}0 '%1' %select{not |}2"
|
||||
"equal to a null pointer is always %select{true|false}2">,
|
||||
InGroup<TautologicalPointerCompare>;
|
||||
def warn_nonnull_parameter_compare : Warning<
|
||||
"comparison of nonnull parameter '%0' %select{not |}1"
|
||||
"equal to a null pointer is always %select{true|false}1">,
|
||||
InGroup<TautologicalPointerCompare>;
|
||||
def warn_this_null_compare : Warning<
|
||||
"'this' pointer cannot be null in well-defined C++ code; comparison may be "
|
||||
"assumed to always evaluate to %select{true|false}0">,
|
||||
|
|
|
@ -6678,7 +6678,37 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E,
|
|||
// Weak Decls can be null.
|
||||
if (!D || D->isWeak())
|
||||
return;
|
||||
|
||||
// Check for parameter decl with nonnull attribute
|
||||
if (ParmVarDecl* PV = dyn_cast<ParmVarDecl>(D)) {
|
||||
if (FunctionDecl* FD = dyn_cast<FunctionDecl>(PV->getDeclContext())) {
|
||||
unsigned NumArgs = FD->getNumParams();
|
||||
llvm::SmallBitVector AttrNonNull(NumArgs);
|
||||
for (const auto *NonNull : FD->specific_attrs<NonNullAttr>()) {
|
||||
if (!NonNull->args_size()) {
|
||||
AttrNonNull.set(0, NumArgs);
|
||||
break;
|
||||
}
|
||||
for (unsigned Val : NonNull->args()) {
|
||||
if (Val >= NumArgs)
|
||||
continue;
|
||||
AttrNonNull.set(Val);
|
||||
}
|
||||
}
|
||||
if (!AttrNonNull.empty())
|
||||
for (unsigned i = 0; i < NumArgs; ++i)
|
||||
if (FD->getParamDecl(i) == PV && AttrNonNull[i]) {
|
||||
std::string Str;
|
||||
llvm::raw_string_ostream S(Str);
|
||||
E->printPretty(S, nullptr, getPrintingPolicy());
|
||||
unsigned DiagID = IsCompare ? diag::warn_nonnull_parameter_compare
|
||||
: diag::warn_cast_nonnull_to_bool;
|
||||
Diag(E->getExprLoc(), DiagID) << S.str() << E->getSourceRange()
|
||||
<< Range << IsEqual;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QualType T = D->getType();
|
||||
const bool IsArray = T->isArrayType();
|
||||
const bool IsFunction = T->isFunctionType();
|
||||
|
|
|
@ -83,3 +83,28 @@ void redecl_test(void *p) {
|
|||
redecl(p, 0); // expected-warning{{null passed}}
|
||||
redecl(0, p); // expected-warning{{null passed}}
|
||||
}
|
||||
|
||||
// rdar://18712242
|
||||
#define NULL (void*)0
|
||||
__attribute__((__nonnull__))
|
||||
int evil_nonnull_func(int* pointer, void * pv)
|
||||
{
|
||||
if (pointer == NULL) { // expected-warning {{comparison of nonnull parameter 'pointer' equal to a null pointer is always false}}
|
||||
return 0;
|
||||
} else {
|
||||
return *pointer;
|
||||
}
|
||||
|
||||
if (pv == NULL) {} // expected-warning {{comparison of nonnull parameter 'pv' equal to a null pointer is always false}}
|
||||
}
|
||||
|
||||
int another_evil_nonnull_func(int* pointer, char ch, void * pv) __attribute__((nonnull(1, 3)));
|
||||
int another_evil_nonnull_func(int* pointer, char ch, void * pv) {
|
||||
if (pointer == NULL) { // expected-warning {{comparison of nonnull parameter 'pointer' equal to a null pointer is always false}}
|
||||
return 0;
|
||||
} else {
|
||||
return *pointer;
|
||||
}
|
||||
|
||||
if (pv == NULL) {} // expected-warning {{comparison of nonnull parameter 'pv' equal to a null pointer is always false}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue