From: Ted Kremenek Date: Thu, 9 Apr 2009 05:45:56 +0000 (+0000) Subject: GRExprEngine: Don't try to reason about the size of 'void' for the return type X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fe630b943e25bb794c46b9aede836c26fad9b590;p=clang GRExprEngine: Don't try to reason about the size of 'void' for the return type of messages sent to nil. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68683 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index caa0192ccd..7e3fd45ab9 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -1689,8 +1689,10 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, const GRState *StNull = Assume(state, L, false, isFeasibleNull); if (isFeasibleNull) { + QualType RetTy = ME->getType(); + // Check if the receiver was nil and the return value a struct. - if(ME->getType()->isRecordType()) { + if(RetTy->isRecordType()) { if (BR.getParentMap().isConsumedExpr(ME)) { // The [0 ...] expressions will return garbage. Flag either an // explicit or implicit error. Because of the structure of this @@ -1709,44 +1711,47 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, } } } - else if (BR.getParentMap().isConsumedExpr(ME)) { + else { ASTContext& Ctx = getContext(); - // sizeof(void *) - const uint64_t voidPtrSize = Ctx.getTypeSize(Ctx.VoidPtrTy); - // sizeof(return type) - const uint64_t returnTypeSize = Ctx.getTypeSize(ME->getType()); - - if(voidPtrSize < returnTypeSize) { - if (NodeTy* N = Builder->generateNode(ME, StNull, Pred)) { - N->markAsSink(); - if(isFeasibleNotNull) - NilReceiverLargerThanVoidPtrRetImplicit.insert(N); - else { - NilReceiverLargerThanVoidPtrRetExplicit.insert(N); + if (RetTy != Ctx.VoidTy) { + if (BR.getParentMap().isConsumedExpr(ME)) { + // sizeof(void *) + const uint64_t voidPtrSize = Ctx.getTypeSize(Ctx.VoidPtrTy); + // sizeof(return type) + const uint64_t returnTypeSize = Ctx.getTypeSize(ME->getType()); + + if(voidPtrSize < returnTypeSize) { + if (NodeTy* N = Builder->generateNode(ME, StNull, Pred)) { + N->markAsSink(); + if(isFeasibleNotNull) + NilReceiverLargerThanVoidPtrRetImplicit.insert(N); + else { + NilReceiverLargerThanVoidPtrRetExplicit.insert(N); + return; + } + } + } + else if (!isFeasibleNotNull) { + // Handle the safe cases where the return value is 0 if the + // receiver is nil. + // + // FIXME: For now take the conservative approach that we only + // return null values if we *know* that the receiver is nil. + // This is because we can have surprises like: + // + // ... = [[NSScreens screens] objectAtIndex:0]; + // + // What can happen is that [... screens] could return nil, but + // it most likely isn't nil. We should assume the semantics + // of this case unless we have *a lot* more knowledge. + // + SVal V = SVal::MakeZero(getBasicVals(), ME->getType()); + MakeNode(Dst, ME, Pred, BindExpr(StNull, ME, V)); return; } } } - else if (!isFeasibleNotNull) { - // FIXME: For now take the conservative approach that we only - // return null values if we *know* that the receiver is nil. - // This is because we can have surprises like: - // - // if ([[NSScreens screens] count]) { - // ... = [[NSScreens screens] objectAtIndex:0]; - // - // What can happen is that [... screens] should return the same - // value, but we won't necessarily catch that (yet). - // - - // Handle the safe cases where the return value is 0 if the receiver - // is nil. - SVal V = SVal::MakeZero(getBasicVals(), ME->getType()); - MakeNode(Dst, ME, Pred, BindExpr(StNull, ME, V)); - return; - } } - // We have handled the cases where the receiver is nil. The remainder // of this method should assume that the receiver is not nil. state = StNotNull; diff --git a/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m b/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m index 574b0385d1..b83be2c2fa 100644 --- a/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m +++ b/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m @@ -6,6 +6,7 @@ - (long long)longlongM; - (double)doubleM; - (long double)longDoubleM; +- (void)voidM; @end @implementation MyClass - (void *)voidPtrM { return (void *)0; } @@ -13,6 +14,7 @@ - (long long)longlongM { return 0; } - (double)doubleM { return 0.0; } - (long double)longDoubleM { return 0.0; } +- (void)voidM {} @end void createFoo() { @@ -57,3 +59,8 @@ void handleNilPruneLoop(MyClass *obj) { long long j = [obj longlongM]; // expected-warning{{The receiver in the message expression is 'nil' and results in the returned value}} } + +int handleVoidInComma() { + MyClass *obj = 0; + return [obj voidM], 0; +}