static analyzer: Handle casts from arrays to integers. This fixes PR 3297.

llvm-svn: 62130
This commit is contained in:
Ted Kremenek 2009-01-13 01:04:21 +00:00
parent 167f2fa5f4
commit eb68db238f
3 changed files with 59 additions and 11 deletions

View File

@ -543,6 +543,11 @@ protected:
/// VisitCast - Transfer function logic for all casts (implicit and explicit). /// VisitCast - Transfer function logic for all casts (implicit and explicit).
void VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst); void VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst);
/// VisitCastPointerToInteger - Transfer function (called by VisitCast) that
/// handles pointer to integer casts and array to integer casts.
void VisitCastPointerToInteger(SVal V, const GRState* state, QualType PtrTy,
Expr* CastE, NodeTy* Pred, NodeSet& Dst);
/// VisitCompoundLiteralExpr - Transfer function logic for compound literals. /// VisitCompoundLiteralExpr - Transfer function logic for compound literals.
void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, NodeTy* Pred, void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, NodeTy* Pred,
NodeSet& Dst, bool asLValue); NodeSet& Dst, bool asLValue);

View File

@ -1668,6 +1668,22 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
// Transfer functions: Miscellaneous statements. // Transfer functions: Miscellaneous statements.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
void GRExprEngine::VisitCastPointerToInteger(SVal V, const GRState* state,
QualType PtrTy,
Expr* CastE, NodeTy* Pred,
NodeSet& Dst) {
if (!V.isUnknownOrUndef()) {
// FIXME: Determine if the number of bits of the target type is
// equal or exceeds the number of bits to store the pointer value.
// If not, flag an error.
unsigned bits = getContext().getTypeSize(PtrTy);
V = nonloc::LocAsInteger::Make(getBasicVals(), cast<Loc>(V), bits);
}
MakeNode(Dst, CastE, Pred, BindExpr(state, CastE, V));
}
void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
NodeSet S1; NodeSet S1;
QualType T = CastE->getType(); QualType T = CastE->getType();
@ -1724,14 +1740,7 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
// Check for casts from pointers to integers. // Check for casts from pointers to integers.
if (T->isIntegerType() && Loc::IsLocType(ExTy)) { if (T->isIntegerType() && Loc::IsLocType(ExTy)) {
unsigned bits = getContext().getTypeSize(ExTy); VisitCastPointerToInteger(V, St, ExTy, CastE, N, Dst);
// FIXME: Determine if the number of bits of the target type is
// equal or exceeds the number of bits to store the pointer value.
// If not, flag an error.
V = nonloc::LocAsInteger::Make(getBasicVals(), cast<Loc>(V), bits);
MakeNode(Dst, CastE, N, BindExpr(St, CastE, V));
continue; continue;
} }
@ -1744,11 +1753,24 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
continue; continue;
} }
// Check for casts from array type to pointer type. // Check for casts from array type to another type.
if (ExTy->isArrayType()) { if (ExTy->isArrayType()) {
assert(T->isPointerType()); // We will always decay to a pointer.
V = StateMgr.ArrayToPointer(V); V = StateMgr.ArrayToPointer(V);
MakeNode(Dst, CastE, N, BindExpr(St, CastE, V));
// Are we casting from an array to a pointer? If so just pass on
// the decayed value.
if (T->isPointerType()) {
MakeNode(Dst, CastE, N, BindExpr(St, CastE, V));
continue;
}
// Are we casting from an array to an integer? If so, cast the decayed
// pointer value to an integer.
assert(T->isIntegerType());
QualType ElemTy = cast<ArrayType>(ExTy)->getElementType();
QualType PointerTy = getContext().getPointerType(ElemTy);
VisitCastPointerToInteger(V, St, PointerTy, CastE, N, Dst);
continue; continue;
} }

View File

@ -52,6 +52,27 @@ int f4(int *p) {
return *q; // expected-warning{{Dereference of null pointer.}} return *q; // expected-warning{{Dereference of null pointer.}}
} }
int f4_b() {
short array[2];
uintptr_t x = array; // expected-warning{{incompatible pointer to integer conversion initializing}}
short *p = x; // expected-warning{{incompatible integer to pointer conversion initializing}}
// The following branch should be infeasible.
if (!(p = &array[0])) {
p = 0;
*p = 1; // no-warning
}
if (p) {
*p = 5; // no-warning
p = 0;
}
else return;
*p += 10; // expected-warning{{Dereference of null pointer}}
}
int f5() { int f5() {
char *s = "hello world"; char *s = "hello world";