blob: 2a8d23d02ca21d9c8ad5bc1446e1c22ac6abecfa [file] [log] [blame]
Ted Kremenek94e915e2008-02-16 01:12:31 +00001// ValueManager.h - Low-level value management for Value Tracking -*- 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 files defines ValueManager, a class that manages the lifetime of APSInt
11// objects and symbolic constraints used by GRExprEngine and related classes.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/Analysis/PathSensitive/ValueManager.h"
16
17using namespace clang;
18
19ValueManager::~ValueManager() {
20 // Note that the dstor for the contents of APSIntSet will never be called,
21 // so we iterate over the set and invoke the dstor for each APSInt. This
22 // frees an aux. memory allocated to represent very large constants.
23 for (APSIntSetTy::iterator I=APSIntSet.begin(), E=APSIntSet.end(); I!=E; ++I)
24 I->getValue().~APSInt();
25}
26
27const llvm::APSInt& ValueManager::getValue(const llvm::APSInt& X) {
28 llvm::FoldingSetNodeID ID;
29 void* InsertPos;
30 typedef llvm::FoldingSetNodeWrapper<llvm::APSInt> FoldNodeTy;
31
32 X.Profile(ID);
33 FoldNodeTy* P = APSIntSet.FindNodeOrInsertPos(ID, InsertPos);
34
35 if (!P) {
36 P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
37 new (P) FoldNodeTy(X);
38 APSIntSet.InsertNode(P, InsertPos);
39 }
40
41 return *P;
42}
43
44const llvm::APSInt& ValueManager::getValue(uint64_t X, unsigned BitWidth,
45 bool isUnsigned) {
46 llvm::APSInt V(BitWidth, isUnsigned);
47 V = X;
48 return getValue(V);
49}
50
51const llvm::APSInt& ValueManager::getValue(uint64_t X, QualType T,
52 SourceLocation Loc) {
53
54 unsigned bits = Ctx.getTypeSize(T, Loc);
55 llvm::APSInt V(bits, T->isUnsignedIntegerType());
56 V = X;
57 return getValue(V);
58}
59
60const SymIntConstraint&
61ValueManager::getConstraint(SymbolID sym, BinaryOperator::Opcode Op,
62 const llvm::APSInt& V) {
63
64 llvm::FoldingSetNodeID ID;
65 SymIntConstraint::Profile(ID, sym, Op, V);
66 void* InsertPos;
67
68 SymIntConstraint* C = SymIntCSet.FindNodeOrInsertPos(ID, InsertPos);
69
70 if (!C) {
71 C = (SymIntConstraint*) BPAlloc.Allocate<SymIntConstraint>();
72 new (C) SymIntConstraint(sym, Op, V);
73 SymIntCSet.InsertNode(C, InsertPos);
74 }
75
76 return *C;
77}
78
Ted Kremenekc2d07202008-02-28 20:32:03 +000079const llvm::APSInt*
Ted Kremenek94e915e2008-02-16 01:12:31 +000080ValueManager::EvaluateAPSInt(BinaryOperator::Opcode Op,
81 const llvm::APSInt& V1, const llvm::APSInt& V2) {
82
83 switch (Op) {
84 default:
85 assert (false && "Invalid Opcode.");
86
87 case BinaryOperator::Mul:
Ted Kremenekc2d07202008-02-28 20:32:03 +000088 return &getValue( V1 * V2 );
Ted Kremenek94e915e2008-02-16 01:12:31 +000089
90 case BinaryOperator::Div:
Ted Kremenekc2d07202008-02-28 20:32:03 +000091 return &getValue( V1 / V2 );
Ted Kremenek94e915e2008-02-16 01:12:31 +000092
93 case BinaryOperator::Rem:
Ted Kremenekc2d07202008-02-28 20:32:03 +000094 return &getValue( V1 % V2 );
Ted Kremenek94e915e2008-02-16 01:12:31 +000095
96 case BinaryOperator::Add:
Ted Kremenekc2d07202008-02-28 20:32:03 +000097 return &getValue( V1 + V2 );
Ted Kremenek94e915e2008-02-16 01:12:31 +000098
99 case BinaryOperator::Sub:
Ted Kremenekc2d07202008-02-28 20:32:03 +0000100 return &getValue( V1 - V2 );
Ted Kremenek94e915e2008-02-16 01:12:31 +0000101
Ted Kremenekc2d07202008-02-28 20:32:03 +0000102 case BinaryOperator::Shl: {
103
104 // FIXME: This logic should probably go higher up, where we can
105 // test these conditions symbolically.
Ted Kremenek94e915e2008-02-16 01:12:31 +0000106
Ted Kremenekc2d07202008-02-28 20:32:03 +0000107 // FIXME: Expand these checks to include all undefined behavior.
108
109 if (V2.isSigned() && V2.isNegative())
110 return NULL;
111
112 uint64_t Amt = V2.getZExtValue();
113
114 if (Amt > V1.getBitWidth())
115 return NULL;
116
117 return &getValue( V1.operator<<( (unsigned) Amt ));
118 }
119
120 case BinaryOperator::Shr: {
121
122 // FIXME: This logic should probably go higher up, where we can
123 // test these conditions symbolically.
124
125 // FIXME: Expand these checks to include all undefined behavior.
126
127 if (V2.isSigned() && V2.isNegative())
128 return NULL;
129
130 uint64_t Amt = V2.getZExtValue();
131
132 if (Amt > V1.getBitWidth())
133 return NULL;
134
135 return &getValue( V1.operator>>( (unsigned) Amt ));
136 }
Ted Kremenek94e915e2008-02-16 01:12:31 +0000137
138 case BinaryOperator::LT:
Ted Kremenekc2d07202008-02-28 20:32:03 +0000139 return &getTruthValue( V1 < V2 );
Ted Kremenek94e915e2008-02-16 01:12:31 +0000140
141 case BinaryOperator::GT:
Ted Kremenekc2d07202008-02-28 20:32:03 +0000142 return &getTruthValue( V1 > V2 );
Ted Kremenek94e915e2008-02-16 01:12:31 +0000143
144 case BinaryOperator::LE:
Ted Kremenekc2d07202008-02-28 20:32:03 +0000145 return &getTruthValue( V1 <= V2 );
Ted Kremenek94e915e2008-02-16 01:12:31 +0000146
147 case BinaryOperator::GE:
Ted Kremenekc2d07202008-02-28 20:32:03 +0000148 return &getTruthValue( V1 >= V2 );
Ted Kremenek94e915e2008-02-16 01:12:31 +0000149
150 case BinaryOperator::EQ:
Ted Kremenekc2d07202008-02-28 20:32:03 +0000151 return &getTruthValue( V1 == V2 );
Ted Kremenek94e915e2008-02-16 01:12:31 +0000152
153 case BinaryOperator::NE:
Ted Kremenekc2d07202008-02-28 20:32:03 +0000154 return &getTruthValue( V1 != V2 );
Ted Kremenek94e915e2008-02-16 01:12:31 +0000155
156 // Note: LAnd, LOr, Comma are handled specially by higher-level logic.
157
158 case BinaryOperator::And:
Ted Kremenekc2d07202008-02-28 20:32:03 +0000159 return &getValue( V1 & V2 );
Ted Kremenek94e915e2008-02-16 01:12:31 +0000160
161 case BinaryOperator::Or:
Ted Kremenekc2d07202008-02-28 20:32:03 +0000162 return &getValue( V1 | V2 );
Ted Kremenek7c79a792008-02-19 20:53:37 +0000163
164 case BinaryOperator::Xor:
Ted Kremenekc2d07202008-02-28 20:32:03 +0000165 return &getValue( V1 ^ V2 );
Ted Kremenek94e915e2008-02-16 01:12:31 +0000166 }
167}