static analyzer: Handle casts from arrays to integers. This fixes PR 3297.
llvm-svn: 62130
This commit is contained in:
parent
167f2fa5f4
commit
eb68db238f
|
@ -542,6 +542,11 @@ protected:
|
|||
|
||||
/// VisitCast - Transfer function logic for all casts (implicit and explicit).
|
||||
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.
|
||||
void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, NodeTy* Pred,
|
||||
|
|
|
@ -1668,6 +1668,22 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
|
|||
// 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){
|
||||
NodeSet S1;
|
||||
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.
|
||||
if (T->isIntegerType() && Loc::IsLocType(ExTy)) {
|
||||
unsigned bits = getContext().getTypeSize(ExTy);
|
||||
|
||||
// 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));
|
||||
VisitCastPointerToInteger(V, St, ExTy, CastE, N, Dst);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1744,11 +1753,24 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
|
|||
continue;
|
||||
}
|
||||
|
||||
// Check for casts from array type to pointer type.
|
||||
// Check for casts from array type to another type.
|
||||
if (ExTy->isArrayType()) {
|
||||
assert(T->isPointerType());
|
||||
// We will always decay to a pointer.
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,27 @@ int f4(int *p) {
|
|||
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() {
|
||||
|
||||
char *s = "hello world";
|
||||
|
|
Loading…
Reference in New Issue