From: Ted Kremenek Date: Thu, 5 Mar 2009 20:22:13 +0000 (+0000) Subject: Fix regression in GRExprEngine::VisitCast: Do not wrap symbolic function pointers... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c530291ada4085f962cfbab7a1732a45e992688c;p=clang Fix regression in GRExprEngine::VisitCast: Do not wrap symbolic function pointers with TypedViewRegions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66187 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index 1d2c70cba2..c2e898abe3 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -1757,6 +1757,7 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){ NodeTy* N = *I1; const GRState* state = GetState(N); SVal V = GetSVal(state, Ex); + ASTContext& C = getContext(); // Unknown? if (V.isUnknown()) { @@ -1765,19 +1766,13 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){ } // Undefined? - if (V.isUndef()) { - MakeNode(Dst, CastE, N, BindExpr(state, CastE, V)); - continue; - } + if (V.isUndef()) + goto PassThrough; // For const casts, just propagate the value. - ASTContext& C = getContext(); - if (C.getCanonicalType(T).getUnqualifiedType() == - C.getCanonicalType(ExTy).getUnqualifiedType()) { - MakeNode(Dst, CastE, N, BindExpr(state, CastE, V)); - continue; - } + C.getCanonicalType(ExTy).getUnqualifiedType()) + goto PassThrough; // Check for casts from pointers to integers. if (T->isIntegerType() && Loc::IsLocType(ExTy)) { @@ -1791,19 +1786,16 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){ // Just unpackage the lval and return it. V = LV->getLoc(); MakeNode(Dst, CastE, N, BindExpr(state, CastE, V)); + continue; } - MakeNode(Dst, CastE, N, BindExpr(state, CastE, - EvalCast(V, CastE->getType()))); - - continue; + goto DispatchCast; } // Just pass through function and block pointers. if (ExTy->isBlockPointerType() || ExTy->isFunctionPointerType()) { assert(Loc::IsLocType(T)); - MakeNode(Dst, CastE, N, BindExpr(state, CastE, V)); - continue; + goto PassThrough; } // Check for casts from array type to another type. @@ -1813,10 +1805,8 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){ // 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(state, CastE, V)); - continue; - } + if (T->isPointerType()) + goto PassThrough; // Are we casting from an array to an integer? If so, cast the decayed // pointer value to an integer. @@ -1853,6 +1843,12 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){ // TypedViewRegion subregion. if (loc::SymbolVal* SV = dyn_cast(&V)) { SymbolRef Sym = SV->getSymbol(); + QualType SymTy = getSymbolManager().getType(Sym); + + // Just pass through symbols that are function or block pointers. + if (SymTy->isFunctionPointerType() || SymTy->isBlockPointerType()) + goto PassThrough; + StoreManager& StoreMgr = getStoreManager(); const MemRegion* R = StoreMgr.getRegionManager().getSymbolicRegion(Sym, getSymbolManager()); @@ -1871,9 +1867,16 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){ continue; } - // All other cases. - MakeNode(Dst, CastE, N, BindExpr(state, CastE, - EvalCast(V, CastE->getType()))); + // All other cases. + DispatchCast: { + MakeNode(Dst, CastE, N, BindExpr(state, CastE, + EvalCast(V, CastE->getType()))); + continue; + } + + PassThrough: { + MakeNode(Dst, CastE, N, BindExpr(state, CastE, V)); + } } } diff --git a/test/Analysis/casts.m b/test/Analysis/casts.m new file mode 100644 index 0000000000..37b8e3d122 --- /dev/null +++ b/test/Analysis/casts.m @@ -0,0 +1,16 @@ +// RUN: clang -analyze -checker-cfref -analyzer-store=basic --verify %s && +// RUN: clang -analyze -checker-cfref -analyzer-store=region --verify %s + +// Test function pointer casts. Currently we track function addresses using +// loc::FunctionVal. Because casts can be arbitrary, do we need to model +// functions with regions? + +typedef void (*MyFuncTest1)(void); + +MyFuncTest1 test1_aux(void); +void test1(void) { + void *x; + void* (*p)(void); + p = ((void*) test1_aux()); + if (p != ((void*) 0)) x = (*p)(); +}