blob: 079481a62ac5eeb2c3fc922b9aa05f83fb7c2caf [file] [log] [blame]
Ted Kremenek32c3fa42009-07-21 21:03:30 +00001// SValuator.cpp - Basic class for all SValuator implementations --*- C++ -*--//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines SValuator, the base class for all (complete) SValuator
11// implementations.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/Analysis/PathSensitive/SValuator.h"
16#include "clang/Analysis/PathSensitive/GRState.h"
17
18using namespace clang;
19
20SValuator::CastResult SValuator::EvalCast(SVal val, const GRState *state,
21 QualType castTy, QualType originalTy){
22
23 if (val.isUnknownOrUndef() || castTy == originalTy)
24 return CastResult(state, val);
25
26 ASTContext &C = ValMgr.getContext();
27
28 // For const casts, just propagate the value.
29 if (C.getCanonicalType(castTy).getUnqualifiedType() ==
30 C.getCanonicalType(originalTy).getUnqualifiedType())
31 return CastResult(state, val);
32
33 // Check for casts from pointers to integers.
34 if (castTy->isIntegerType() && Loc::IsLocType(originalTy))
35 return CastResult(state, EvalCastL(cast<Loc>(val), castTy));
36
37 // Check for casts from integers to pointers.
38 if (Loc::IsLocType(castTy) && originalTy->isIntegerType()) {
39 if (nonloc::LocAsInteger *LV = dyn_cast<nonloc::LocAsInteger>(&val)) {
40 // Just unpackage the lval and return it.
41 return CastResult(state, LV->getLoc());
42 }
43
44 goto DispatchCast;
45 }
46
47 // Just pass through function and block pointers.
48 if (originalTy->isBlockPointerType() || originalTy->isFunctionPointerType()) {
49 assert(Loc::IsLocType(castTy));
50 return CastResult(state, val);
51 }
52
53 // Check for casts from array type to another type.
54 if (originalTy->isArrayType()) {
55 // We will always decay to a pointer.
56 val = ValMgr.getStateManager().ArrayToPointer(cast<Loc>(val));
57
58 // Are we casting from an array to a pointer? If so just pass on
59 // the decayed value.
60 if (castTy->isPointerType())
61 return CastResult(state, val);
62
63 // Are we casting from an array to an integer? If so, cast the decayed
64 // pointer value to an integer.
65 assert(castTy->isIntegerType());
66
67 // FIXME: Keep these here for now in case we decide soon that we
68 // need the original decayed type.
69 // QualType elemTy = cast<ArrayType>(originalTy)->getElementType();
70 // QualType pointerTy = C.getPointerType(elemTy);
71 return CastResult(state, EvalCastL(cast<Loc>(val), castTy));
72 }
73
74 // Check for casts from a region to a specific type.
75 if (const MemRegion *R = val.getAsRegion()) {
Ted Kremenek32c3fa42009-07-21 21:03:30 +000076 // FIXME: We should handle the case where we strip off view layers to get
77 // to a desugared type.
78
79 assert(Loc::IsLocType(castTy));
80 // We get a symbolic function pointer for a dereference of a function
81 // pointer, but it is of function type. Example:
82
83 // struct FPRec {
84 // void (*my_func)(int * x);
85 // };
86 //
87 // int bar(int x);
88 //
89 // int f1_a(struct FPRec* foo) {
90 // int x;
91 // (*foo->my_func)(&x);
92 // return bar(x)+1; // no-warning
93 // }
94
95 assert(Loc::IsLocType(originalTy) || originalTy->isFunctionType() ||
96 originalTy->isBlockPointerType());
97
98 StoreManager &storeMgr = ValMgr.getStateManager().getStoreManager();
99
100 // Delegate to store manager to get the result of casting a region
101 // to a different type.
102 const StoreManager::CastResult& Res = storeMgr.CastRegion(state, R, castTy);
103
104 // Inspect the result. If the MemRegion* returned is NULL, this
105 // expression evaluates to UnknownVal.
106 R = Res.getRegion();
107
108 if (R)
109 return CastResult(Res.getState(), loc::MemRegionVal(R));
110
111 return CastResult(Res.getState(), UnknownVal());
112 }
113
114 // All other cases.
115DispatchCast:
116 return CastResult(state,
117 isa<Loc>(val) ? EvalCastL(cast<Loc>(val), castTy)
118 : EvalCastNL(cast<NonLoc>(val), castTy));
Owen Anderson4a28d5d2009-07-24 23:12:58 +0000119}