summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/Analysis/GRExprEngine.cpp49
-rw-r--r--clang/test/Analysis/casts.m16
2 files changed, 42 insertions, 23 deletions
diff --git a/clang/lib/Analysis/GRExprEngine.cpp b/clang/lib/Analysis/GRExprEngine.cpp
index 1d2c70cba2a..c2e898abe3b 100644
--- a/clang/lib/Analysis/GRExprEngine.cpp
+++ b/clang/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<loc::SymbolVal>(&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/clang/test/Analysis/casts.m b/clang/test/Analysis/casts.m
new file mode 100644
index 00000000000..37b8e3d122b
--- /dev/null
+++ b/clang/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)();
+}
OpenPOWER on IntegriCloud