• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  // SValBuilder.h - Construction of SVals from evaluating expressions -*- 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 SValBuilder, a class that defines the interface for
11  //  "symbolical evaluators" which construct an SVal from an expression.
12  //
13  //===----------------------------------------------------------------------===//
14  
15  #ifndef LLVM_CLANG_GR_SVALBUILDER
16  #define LLVM_CLANG_GR_SVALBUILDER
17  
18  #include "clang/AST/Expr.h"
19  #include "clang/AST/ExprCXX.h"
20  #include "clang/AST/ExprObjC.h"
21  #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
22  #include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
23  #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
24  
25  namespace clang {
26  
27  class CXXBoolLiteralExpr;
28  
29  namespace ento {
30  
31  class SValBuilder {
32    virtual void anchor();
33  protected:
34    ASTContext &Context;
35  
36    /// Manager of APSInt values.
37    BasicValueFactory BasicVals;
38  
39    /// Manages the creation of symbols.
40    SymbolManager SymMgr;
41  
42    /// Manages the creation of memory regions.
43    MemRegionManager MemMgr;
44  
45    ProgramStateManager &StateMgr;
46  
47    /// The scalar type to use for array indices.
48    const QualType ArrayIndexTy;
49  
50    /// The width of the scalar type used for array indices.
51    const unsigned ArrayIndexWidth;
52  
53    virtual SVal evalCastFromNonLoc(NonLoc val, QualType castTy) = 0;
54    virtual SVal evalCastFromLoc(Loc val, QualType castTy) = 0;
55  
56  public:
57    // FIXME: Make these protected again once RegionStoreManager correctly
58    // handles loads from different bound value types.
59    virtual SVal dispatchCast(SVal val, QualType castTy) = 0;
60  
61  public:
SValBuilder(llvm::BumpPtrAllocator & alloc,ASTContext & context,ProgramStateManager & stateMgr)62    SValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context,
63                ProgramStateManager &stateMgr)
64      : Context(context), BasicVals(context, alloc),
65        SymMgr(context, BasicVals, alloc),
66        MemMgr(context, alloc),
67        StateMgr(stateMgr),
68        ArrayIndexTy(context.IntTy),
69        ArrayIndexWidth(context.getTypeSize(ArrayIndexTy)) {}
70  
~SValBuilder()71    virtual ~SValBuilder() {}
72  
haveSameType(const SymExpr * Sym1,const SymExpr * Sym2)73    bool haveSameType(const SymExpr *Sym1, const SymExpr *Sym2) {
74      return haveSameType(Sym1->getType(Context), Sym2->getType(Context));
75    }
76  
haveSameType(QualType Ty1,QualType Ty2)77    bool haveSameType(QualType Ty1, QualType Ty2) {
78      // FIXME: Remove the second disjunct when we support symbolic
79      // truncation/extension.
80      return (Context.getCanonicalType(Ty1) == Context.getCanonicalType(Ty2) ||
81              (Ty2->isIntegerType() && Ty2->isIntegerType()));
82    }
83  
84    SVal evalCast(SVal val, QualType castTy, QualType originalType);
85  
86    virtual SVal evalMinus(NonLoc val) = 0;
87  
88    virtual SVal evalComplement(NonLoc val) = 0;
89  
90    /// Create a new value which represents a binary expression with two non
91    /// location operands.
92    virtual SVal evalBinOpNN(ProgramStateRef state, BinaryOperator::Opcode op,
93                             NonLoc lhs, NonLoc rhs, QualType resultTy) = 0;
94  
95    /// Create a new value which represents a binary expression with two memory
96    /// location operands.
97    virtual SVal evalBinOpLL(ProgramStateRef state, BinaryOperator::Opcode op,
98                             Loc lhs, Loc rhs, QualType resultTy) = 0;
99  
100    /// Create a new value which represents a binary expression with a memory
101    /// location and non location operands. For example, this would be used to
102    /// evaluate a pointer arithmetic operation.
103    virtual SVal evalBinOpLN(ProgramStateRef state, BinaryOperator::Opcode op,
104                             Loc lhs, NonLoc rhs, QualType resultTy) = 0;
105  
106    /// Evaluates a given SVal. If the SVal has only one possible (integer) value,
107    /// that value is returned. Otherwise, returns NULL.
108    virtual const llvm::APSInt *getKnownValue(ProgramStateRef state, SVal val) = 0;
109  
110    /// Handles generation of the value in case the builder is not smart enough to
111    /// handle the given binary expression. Depending on the state, decides to
112    /// either keep the expression or forget the history and generate an
113    /// UnknownVal.
114    SVal makeGenericVal(ProgramStateRef state, BinaryOperator::Opcode op,
115                            NonLoc lhs, NonLoc rhs, QualType resultTy);
116  
117    SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
118                   SVal lhs, SVal rhs, QualType type);
119  
120    DefinedOrUnknownSVal evalEQ(ProgramStateRef state, DefinedOrUnknownSVal lhs,
121                                DefinedOrUnknownSVal rhs);
122  
getContext()123    ASTContext &getContext() { return Context; }
getContext()124    const ASTContext &getContext() const { return Context; }
125  
getStateManager()126    ProgramStateManager &getStateManager() { return StateMgr; }
127  
getConditionType()128    QualType getConditionType() const {
129      return  getContext().IntTy;
130    }
131  
getArrayIndexType()132    QualType getArrayIndexType() const {
133      return ArrayIndexTy;
134    }
135  
getBasicValueFactory()136    BasicValueFactory &getBasicValueFactory() { return BasicVals; }
getBasicValueFactory()137    const BasicValueFactory &getBasicValueFactory() const { return BasicVals; }
138  
getSymbolManager()139    SymbolManager &getSymbolManager() { return SymMgr; }
getSymbolManager()140    const SymbolManager &getSymbolManager() const { return SymMgr; }
141  
getRegionManager()142    MemRegionManager &getRegionManager() { return MemMgr; }
getRegionManager()143    const MemRegionManager &getRegionManager() const { return MemMgr; }
144  
145    // Forwarding methods to SymbolManager.
146  
147    const SymbolConjured* getConjuredSymbol(const Stmt *stmt,
148                                            const LocationContext *LCtx,
149                                            QualType type,
150                                            unsigned visitCount,
151                                            const void *symbolTag = 0) {
152      return SymMgr.getConjuredSymbol(stmt, LCtx, type, visitCount, symbolTag);
153    }
154  
155    const SymbolConjured* getConjuredSymbol(const Expr *expr,
156                                            const LocationContext *LCtx,
157                                            unsigned visitCount,
158                                            const void *symbolTag = 0) {
159      return SymMgr.getConjuredSymbol(expr, LCtx, visitCount, symbolTag);
160    }
161  
162    /// Construct an SVal representing '0' for the specified type.
163    DefinedOrUnknownSVal makeZeroVal(QualType type);
164  
165    /// Make a unique symbol for value of region.
166    DefinedOrUnknownSVal getRegionValueSymbolVal(const TypedValueRegion *region);
167  
168    /// \brief Create a new symbol with a unique 'name'.
169    ///
170    /// We resort to conjured symbols when we cannot construct a derived symbol.
171    /// The advantage of symbols derived/built from other symbols is that we
172    /// preserve the relation between related(or even equivalent) expressions, so
173    /// conjured symbols should be used sparingly.
174    DefinedOrUnknownSVal getConjuredSymbolVal(const void *symbolTag,
175                                              const Expr *expr,
176                                              const LocationContext *LCtx,
177                                              unsigned count);
178    DefinedOrUnknownSVal getConjuredSymbolVal(const void *symbolTag,
179                                              const Expr *expr,
180                                              const LocationContext *LCtx,
181                                              QualType type,
182                                              unsigned count);
183  
184    DefinedOrUnknownSVal getConjuredSymbolVal(const Stmt *stmt,
185                                              const LocationContext *LCtx,
186                                              QualType type,
187                                              unsigned visitCount);
188  
189    DefinedOrUnknownSVal getDerivedRegionValueSymbolVal(
190        SymbolRef parentSymbol, const TypedValueRegion *region);
191  
192    DefinedSVal getMetadataSymbolVal(
193        const void *symbolTag, const MemRegion *region,
194        const Expr *expr, QualType type, unsigned count);
195  
196    DefinedSVal getFunctionPointer(const FunctionDecl *func);
197  
198    DefinedSVal getBlockPointer(const BlockDecl *block, CanQualType locTy,
199                                const LocationContext *locContext);
200  
makeCompoundVal(QualType type,llvm::ImmutableList<SVal> vals)201    NonLoc makeCompoundVal(QualType type, llvm::ImmutableList<SVal> vals) {
202      return nonloc::CompoundVal(BasicVals.getCompoundValData(type, vals));
203    }
204  
makeLazyCompoundVal(const StoreRef & store,const TypedValueRegion * region)205    NonLoc makeLazyCompoundVal(const StoreRef &store,
206                               const TypedValueRegion *region) {
207      return nonloc::LazyCompoundVal(
208          BasicVals.getLazyCompoundValData(store, region));
209    }
210  
makeZeroArrayIndex()211    NonLoc makeZeroArrayIndex() {
212      return nonloc::ConcreteInt(BasicVals.getValue(0, ArrayIndexTy));
213    }
214  
makeArrayIndex(uint64_t idx)215    NonLoc makeArrayIndex(uint64_t idx) {
216      return nonloc::ConcreteInt(BasicVals.getValue(idx, ArrayIndexTy));
217    }
218  
219    SVal convertToArrayIndex(SVal val);
220  
makeIntVal(const IntegerLiteral * integer)221    nonloc::ConcreteInt makeIntVal(const IntegerLiteral* integer) {
222      return nonloc::ConcreteInt(
223          BasicVals.getValue(integer->getValue(),
224                       integer->getType()->isUnsignedIntegerOrEnumerationType()));
225    }
226  
makeBoolVal(const ObjCBoolLiteralExpr * boolean)227    nonloc::ConcreteInt makeBoolVal(const ObjCBoolLiteralExpr *boolean) {
228      return makeTruthVal(boolean->getValue(), boolean->getType());
229    }
230  
231    nonloc::ConcreteInt makeBoolVal(const CXXBoolLiteralExpr *boolean);
232  
makeIntVal(const llvm::APSInt & integer)233    nonloc::ConcreteInt makeIntVal(const llvm::APSInt& integer) {
234      return nonloc::ConcreteInt(BasicVals.getValue(integer));
235    }
236  
makeIntLocVal(const llvm::APSInt & integer)237    loc::ConcreteInt makeIntLocVal(const llvm::APSInt &integer) {
238      return loc::ConcreteInt(BasicVals.getValue(integer));
239    }
240  
makeIntVal(const llvm::APInt & integer,bool isUnsigned)241    NonLoc makeIntVal(const llvm::APInt& integer, bool isUnsigned) {
242      return nonloc::ConcreteInt(BasicVals.getValue(integer, isUnsigned));
243    }
244  
makeIntVal(uint64_t integer,QualType type)245    DefinedSVal makeIntVal(uint64_t integer, QualType type) {
246      if (Loc::isLocType(type))
247        return loc::ConcreteInt(BasicVals.getValue(integer, type));
248  
249      return nonloc::ConcreteInt(BasicVals.getValue(integer, type));
250    }
251  
makeIntVal(uint64_t integer,bool isUnsigned)252    NonLoc makeIntVal(uint64_t integer, bool isUnsigned) {
253      return nonloc::ConcreteInt(BasicVals.getIntValue(integer, isUnsigned));
254    }
255  
makeIntValWithPtrWidth(uint64_t integer,bool isUnsigned)256    NonLoc makeIntValWithPtrWidth(uint64_t integer, bool isUnsigned) {
257      return nonloc::ConcreteInt(
258          BasicVals.getIntWithPtrWidth(integer, isUnsigned));
259    }
260  
makeIntVal(uint64_t integer,unsigned bitWidth,bool isUnsigned)261    NonLoc makeIntVal(uint64_t integer, unsigned bitWidth, bool isUnsigned) {
262      return nonloc::ConcreteInt(
263          BasicVals.getValue(integer, bitWidth, isUnsigned));
264    }
265  
makeLocAsInteger(Loc loc,unsigned bits)266    NonLoc makeLocAsInteger(Loc loc, unsigned bits) {
267      return nonloc::LocAsInteger(BasicVals.getPersistentSValWithData(loc, bits));
268    }
269  
270    NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
271                      const llvm::APSInt& rhs, QualType type);
272  
273    NonLoc makeNonLoc(const llvm::APSInt& rhs, BinaryOperator::Opcode op,
274                      const SymExpr *lhs, QualType type);
275  
276    NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
277                      const SymExpr *rhs, QualType type);
278  
279    /// \brief Create a NonLoc value for cast.
280    NonLoc makeNonLoc(const SymExpr *operand, QualType fromTy, QualType toTy);
281  
makeTruthVal(bool b,QualType type)282    nonloc::ConcreteInt makeTruthVal(bool b, QualType type) {
283      return nonloc::ConcreteInt(BasicVals.getTruthValue(b, type));
284    }
285  
makeTruthVal(bool b)286    nonloc::ConcreteInt makeTruthVal(bool b) {
287      return nonloc::ConcreteInt(BasicVals.getTruthValue(b));
288    }
289  
makeNull()290    Loc makeNull() {
291      return loc::ConcreteInt(BasicVals.getZeroWithPtrWidth());
292    }
293  
makeLoc(SymbolRef sym)294    Loc makeLoc(SymbolRef sym) {
295      return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
296    }
297  
makeLoc(const MemRegion * region)298    Loc makeLoc(const MemRegion* region) {
299      return loc::MemRegionVal(region);
300    }
301  
makeLoc(const AddrLabelExpr * expr)302    Loc makeLoc(const AddrLabelExpr *expr) {
303      return loc::GotoLabel(expr->getLabel());
304    }
305  
makeLoc(const llvm::APSInt & integer)306    Loc makeLoc(const llvm::APSInt& integer) {
307      return loc::ConcreteInt(BasicVals.getValue(integer));
308    }
309  
310  };
311  
312  SValBuilder* createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc,
313                                       ASTContext &context,
314                                       ProgramStateManager &stateMgr);
315  
316  } // end GR namespace
317  
318  } // end clang namespace
319  
320  #endif
321