forked from OSchip/llvm-project
[analyzer] Check all 'nonnull' attributes, not just the first one.
Patch by Daniel Fahlgren! llvm-svn: 219625
This commit is contained in:
parent
193d87fd8c
commit
679659f58c
|
@ -49,16 +49,27 @@ void NonNullParamChecker::checkPreCall(const CallEvent &Call,
|
|||
if (!FD)
|
||||
return;
|
||||
|
||||
// FIXME: This is wrong; there can be multiple attributes with different sets
|
||||
// of non-null parameter indices.
|
||||
const NonNullAttr *Att = FD->getAttr<NonNullAttr>();
|
||||
// Merge all non-null attributes
|
||||
unsigned NumArgs = Call.getNumArgs();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
ProgramStateRef state = C.getState();
|
||||
|
||||
CallEvent::param_type_iterator TyI = Call.param_type_begin(),
|
||||
TyE = Call.param_type_end();
|
||||
|
||||
for (unsigned idx = 0, count = Call.getNumArgs(); idx != count; ++idx){
|
||||
for (unsigned idx = 0; idx < NumArgs; ++idx) {
|
||||
|
||||
// Check if the parameter is a reference. We want to report when reference
|
||||
// to a null pointer is passed as a paramter.
|
||||
|
@ -68,7 +79,7 @@ void NonNullParamChecker::checkPreCall(const CallEvent &Call,
|
|||
TyI++;
|
||||
}
|
||||
|
||||
bool haveAttrNonNull = Att && Att->isNonNull(idx);
|
||||
bool haveAttrNonNull = AttrNonNull[idx];
|
||||
if (!haveAttrNonNull) {
|
||||
// Check if the parameter is also marked 'nonnull'.
|
||||
ArrayRef<ParmVarDecl*> parms = Call.parameters();
|
||||
|
|
|
@ -76,6 +76,104 @@ int rdar16153464(union rdar16153464_full_ctx_t inner)
|
|||
rdar16153464_check(0); // expected-warning{{nonnull}}
|
||||
}
|
||||
|
||||
// Multiple attributes, the basic case
|
||||
void multipleAttributes_1(char *p, char *q) __attribute((nonnull(1))) __attribute((nonnull(2)));
|
||||
|
||||
void testMultiple_1(void) {
|
||||
char c;
|
||||
multipleAttributes_1(&c, &c); // no-warning
|
||||
}
|
||||
|
||||
void testMultiple_2(void) {
|
||||
char c;
|
||||
multipleAttributes_1(0, &c); // expected-warning{{nonnull}}
|
||||
}
|
||||
|
||||
void testMultiple_3(void) {
|
||||
char c;
|
||||
multipleAttributes_1(&c, 0); // expected-warning{{nonnull}}
|
||||
}
|
||||
|
||||
void testMultiple_4(void) {
|
||||
multipleAttributes_1(0, 0);// expected-warning{{nonnull}}
|
||||
}
|
||||
|
||||
// Multiple attributes, multiple prototypes
|
||||
void multipleAttributes_2(char *p, char *q) __attribute((nonnull(1)));
|
||||
void multipleAttributes_2(char *p, char *q) __attribute((nonnull(2)));
|
||||
|
||||
void testMultiple_5(void) {
|
||||
char c;
|
||||
multipleAttributes_2(0, &c);// expected-warning{{nonnull}}
|
||||
}
|
||||
|
||||
void testMultiple_6(void) {
|
||||
char c;
|
||||
multipleAttributes_2(&c, 0);// expected-warning{{nonnull}}
|
||||
}
|
||||
|
||||
void testMultiple_7(void) {
|
||||
multipleAttributes_2(0, 0);// expected-warning{{nonnull}}
|
||||
}
|
||||
|
||||
// Multiple attributes, same index
|
||||
void multipleAttributes_3(char *p, char *q) __attribute((nonnull(1))) __attribute((nonnull(1)));
|
||||
|
||||
void testMultiple_8(void) {
|
||||
char c;
|
||||
multipleAttributes_3(0, &c); // expected-warning{{nonnull}}
|
||||
}
|
||||
|
||||
void testMultiple_9(void) {
|
||||
char c;
|
||||
multipleAttributes_3(&c, 0); // no-warning
|
||||
}
|
||||
|
||||
// Multiple attributes, the middle argument is missing an attribute
|
||||
void multipleAttributes_4(char *p, char *q, char *r) __attribute((nonnull(1))) __attribute((nonnull(3)));
|
||||
|
||||
void testMultiple_10(void) {
|
||||
char c;
|
||||
multipleAttributes_4(0, &c, &c); // expected-warning{{nonnull}}
|
||||
}
|
||||
|
||||
void testMultiple_11(void) {
|
||||
char c;
|
||||
multipleAttributes_4(&c, 0, &c); // no-warning
|
||||
}
|
||||
|
||||
void testMultiple_12(void) {
|
||||
char c;
|
||||
multipleAttributes_4(&c, &c, 0); // expected-warning{{nonnull}}
|
||||
}
|
||||
|
||||
|
||||
// Multiple attributes, when the last is without index
|
||||
void multipleAttributes_all_1(char *p, char *q) __attribute((nonnull(1))) __attribute((nonnull));
|
||||
|
||||
void testMultiple_13(void) {
|
||||
char c;
|
||||
multipleAttributes_all_1(0, &c); // expected-warning{{nonnull}}
|
||||
}
|
||||
|
||||
void testMultiple_14(void) {
|
||||
char c;
|
||||
multipleAttributes_all_1(&c, 0); // expected-warning{{nonnull}}
|
||||
}
|
||||
|
||||
// Multiple attributes, when the first is without index
|
||||
void multipleAttributes_all_2(char *p, char *q) __attribute((nonnull)) __attribute((nonnull(2)));
|
||||
|
||||
void testMultiple_15(void) {
|
||||
char c;
|
||||
multipleAttributes_all_2(0, &c); // expected-warning{{nonnull}}
|
||||
}
|
||||
|
||||
void testMultiple_16(void) {
|
||||
char c;
|
||||
multipleAttributes_all_2(&c, 0); // expected-warning{{nonnull}}
|
||||
}
|
||||
|
||||
void testVararg(int k, void *p) {
|
||||
extern void testVararg_check(int, ...) __attribute__((nonnull));
|
||||
void *n = 0;
|
||||
|
|
Loading…
Reference in New Issue