forked from OSchip/llvm-project
Enhance analyzer reasoning about sending messages to nil. A nil receiver returns 0 for scalars of size <= sizeof(void*).
llvm-svn: 68629
This commit is contained in:
parent
d43aaad1b1
commit
5451c60f5a
|
@ -95,6 +95,8 @@ public:
|
|||
return getRawKind() > UnknownKind;
|
||||
}
|
||||
|
||||
static SVal MakeZero(BasicValueFactory &BasicVals, QualType T);
|
||||
|
||||
bool isZeroConstant() const;
|
||||
|
||||
/// getAsLocSymbol - If this SVal is a location (subclasses Loc) and
|
||||
|
@ -211,11 +213,7 @@ class Loc : public SVal {
|
|||
protected:
|
||||
Loc(unsigned SubKind, const void* D)
|
||||
: SVal(const_cast<void*>(D), true, SubKind) {}
|
||||
|
||||
// // Equality operators.
|
||||
// NonLoc EQ(SymbolManager& SM, Loc R) const;
|
||||
// NonLoc NE(SymbolManager& SM, Loc R) const;
|
||||
|
||||
|
||||
public:
|
||||
void print(llvm::raw_ostream& Out) const;
|
||||
|
||||
|
@ -228,6 +226,8 @@ public:
|
|||
|
||||
static Loc MakeVal(SymbolRef sym);
|
||||
|
||||
static Loc MakeNull(BasicValueFactory &BasicVals);
|
||||
|
||||
// Implement isa<T> support.
|
||||
static inline bool classof(const SVal* V) {
|
||||
return V->getBaseKind() == LocKind;
|
||||
|
|
|
@ -1682,7 +1682,7 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
|
|||
|
||||
// "Assume" that the receiver is not NULL.
|
||||
bool isFeasibleNotNull = false;
|
||||
Assume(state, L, true, isFeasibleNotNull);
|
||||
const GRState *StNotNull = Assume(state, L, true, isFeasibleNotNull);
|
||||
|
||||
// "Assume" that the receiver is NULL.
|
||||
bool isFeasibleNull = false;
|
||||
|
@ -1724,8 +1724,21 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
|
|||
NilReceiverLargerThanVoidPtrRetExplicit.insert(N);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We have handled the cases where the receiver is nil. The remainder
|
||||
// of this method should assume that the receiver is not nil.
|
||||
if (!isFeasibleNotNull)
|
||||
return;
|
||||
|
||||
state = StNotNull;
|
||||
}
|
||||
|
||||
// Check if the "raise" message was sent.
|
||||
|
@ -2445,7 +2458,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
|
|||
// transfer functions as "0 == E".
|
||||
|
||||
if (isa<Loc>(V)) {
|
||||
loc::ConcreteInt X(getBasicVals().getZeroWithPtrWidth());
|
||||
Loc X = Loc::MakeNull(getBasicVals());
|
||||
SVal Result = EvalBinOp(BinaryOperator::EQ, cast<Loc>(V), X,
|
||||
U->getType());
|
||||
state = BindExpr(state, U, Result);
|
||||
|
|
|
@ -201,6 +201,22 @@ SVal loc::ConcreteInt::EvalBinOp(BasicValueFactory& BasicVals,
|
|||
return UndefinedVal();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Utility methods for constructing SVals.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
SVal SVal::MakeZero(BasicValueFactory &BasicVals, QualType T) {
|
||||
if (Loc::IsLocType(T))
|
||||
return Loc::MakeNull(BasicVals);
|
||||
|
||||
if (T->isIntegerType())
|
||||
return NonLoc::MakeVal(BasicVals, 0, T);
|
||||
|
||||
// FIXME: Handle floats.
|
||||
// FIXME: Handle structs.
|
||||
return UnknownVal();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Utility methods for constructing Non-Locs.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -314,6 +330,10 @@ Loc Loc::MakeVal(AddrLabelExpr* E) { return loc::GotoLabel(E->getLabel()); }
|
|||
|
||||
Loc Loc::MakeVal(SymbolRef sym) { return loc::SymbolVal(sym); }
|
||||
|
||||
Loc Loc::MakeNull(BasicValueFactory &BasicVals) {
|
||||
return loc::ConcreteInt(BasicVals.getZeroWithPtrWidth());
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Pretty-Printing.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -46,3 +46,14 @@ void createFoo5() {
|
|||
double d = [obj doubleM]; // no-warning
|
||||
}
|
||||
|
||||
void handleNilPruneLoop(MyClass *obj) {
|
||||
if (!!obj)
|
||||
return;
|
||||
|
||||
// Test if [obj intM] evaluates to 0, thus pruning the entire loop.
|
||||
for (int i = 0; i < [obj intM]; i++) {
|
||||
long long j = [obj longlongM]; // no-warning
|
||||
}
|
||||
|
||||
long long j = [obj longlongM]; // expected-warning{{The receiver in the message expression is 'nil' and results in the returned value}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue