forked from OSchip/llvm-project
[analyzer] Warn when nil receiver results in forming null reference
This also allows us to ensure IDC/return null suppression gets triggered in such cases. llvm-svn: 178686
This commit is contained in:
parent
b5d2fe8a1d
commit
c610bcacde
|
@ -366,17 +366,23 @@ void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C,
|
|||
|
||||
if (!BT_msg_ret)
|
||||
BT_msg_ret.reset(
|
||||
new BuiltinBug("Receiver in message expression is "
|
||||
"'nil' and returns a garbage value"));
|
||||
new BuiltinBug("Receiver in message expression is 'nil'"));
|
||||
|
||||
const ObjCMessageExpr *ME = msg.getOriginExpr();
|
||||
|
||||
QualType ResTy = msg.getResultType();
|
||||
|
||||
SmallString<200> buf;
|
||||
llvm::raw_svector_ostream os(buf);
|
||||
os << "The receiver of message '" << ME->getSelector().getAsString()
|
||||
<< "' is nil and returns a value of type '";
|
||||
msg.getResultType().print(os, C.getLangOpts());
|
||||
os << "' that will be garbage";
|
||||
<< "' is nil";
|
||||
if (ResTy->isReferenceType()) {
|
||||
os << ", which results in forming a null reference";
|
||||
} else {
|
||||
os << " and returns a value of type '";
|
||||
msg.getResultType().print(os, C.getLangOpts());
|
||||
os << "' that will be garbage";
|
||||
}
|
||||
|
||||
BugReport *report = new BugReport(*BT_msg_ret, os.str(), N);
|
||||
report->addRange(ME->getReceiverRange());
|
||||
|
@ -419,13 +425,14 @@ void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C,
|
|||
const uint64_t voidPtrSize = Ctx.getTypeSize(Ctx.VoidPtrTy);
|
||||
const uint64_t returnTypeSize = Ctx.getTypeSize(CanRetTy);
|
||||
|
||||
if (voidPtrSize < returnTypeSize &&
|
||||
!(supportsNilWithFloatRet(Ctx.getTargetInfo().getTriple()) &&
|
||||
(Ctx.FloatTy == CanRetTy ||
|
||||
Ctx.DoubleTy == CanRetTy ||
|
||||
Ctx.LongDoubleTy == CanRetTy ||
|
||||
Ctx.LongLongTy == CanRetTy ||
|
||||
Ctx.UnsignedLongLongTy == CanRetTy))) {
|
||||
if (CanRetTy.getTypePtr()->isReferenceType()||
|
||||
(voidPtrSize < returnTypeSize &&
|
||||
!(supportsNilWithFloatRet(Ctx.getTargetInfo().getTriple()) &&
|
||||
(Ctx.FloatTy == CanRetTy ||
|
||||
Ctx.DoubleTy == CanRetTy ||
|
||||
Ctx.LongDoubleTy == CanRetTy ||
|
||||
Ctx.LongLongTy == CanRetTy ||
|
||||
Ctx.UnsignedLongLongTy == CanRetTy)))) {
|
||||
if (ExplodedNode *N = C.generateSink(state, 0 , &Tag))
|
||||
emitNilReceiverBug(C, Msg, N);
|
||||
return;
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
// RUN: %clang_cc1 -analyze -analyzer-checker=core -verify -Wno-null-dereference %s
|
||||
|
||||
@interface Foo
|
||||
- (int &)ref;
|
||||
@end
|
||||
|
||||
Foo *getFoo() { return 0; }
|
||||
|
||||
void testNullPointerSuppression() {
|
||||
getFoo().ref = 1;
|
||||
}
|
||||
|
||||
void testPositiveNullReference() {
|
||||
Foo *x = 0;
|
||||
x.ref = 1; // expected-warning {{The receiver of message 'ref' is nil, which results in forming a null reference}}
|
||||
}
|
||||
|
Loading…
Reference in New Issue